9

记录日志时DebugTree,我看到类名,但是当我创建自定义树时,标签是null. 这是我的自定义树的样子:

public class CrashlyticsTree extends Timber.Tree {
private static final String CRASHLYTICS_KEY_PRIORITY = "priority";
private static final String CRASHLYTICS_KEY_TAG = "tag";
private static final String CRASHLYTICS_KEY_MESSAGE = "message";

@Override
protected boolean isLoggable(int priority) {
    if (priority == Log.VERBOSE || priority == Log.DEBUG || priority == Log.INFO) {
        return false;
    }

    // only log WARN(Timber.w), ERROR(Timber.e), or WTF(Timber.wtf)
    return true;
}

@Override
protected void log(int priority, @Nullable String tag, @Nullable String message, @Nullable Throwable t) {
    if(User.CurrentUser.isLoggedIn()){
        Crashlytics.setUserIdentifier(Long.toString(User.CurrentUser.getUserId()));
    }

    Crashlytics.setInt(CRASHLYTICS_KEY_PRIORITY, priority);
    Crashlytics.setString(CRASHLYTICS_KEY_TAG, tag);
    Crashlytics.setString(CRASHLYTICS_KEY_MESSAGE, message);

    if (t == null) {
        Crashlytics.logException(new Exception(message));
    } else {
        if(!TextUtils.isEmpty(message)){
            Crashlytics.log(priority, tag, message);
        }
        Crashlytics.logException(t);
    }
}
}

然而,即使来自 DebugTree,生成的标记也是BaseActivity因为它确实来自BaseActivity但是我想知道是否有一种方法可以获得扩展 BaseActivity 的类的名称

4

3 回答 3

9

根据杰克沃顿的说法:

tag除非您tag(String)在日志站点调用或从其扩展DebugTree(对于生产日志记录不应这样做),否则该值为 null。

因此,您需要Timber.tag([class name])在每次调用之前添加。

github.com/JakeWharton/timber/issues/122

于 2016-09-14T18:02:42.993 回答
2

如果你想在发布 apk 中显示/添加标签,有一个 hack。而不是使用Timber.Tree()useTimber.DebugTree()这将允许您在每个日志中显示标签,如下所示:

class ReleaseTree : Timber.DebugTree() {

    override fun log(priority: Int, tag: String?, message: String, throwable: Throwable?) {
        // Don't log VERBOSE and DEBUG
        if (priority == Log.VERBOSE || priority == Log.DEBUG) {
            return
        }

        Log.println(priority, "Test->$tag", message)

    }
}

这样,您还可以将自定义标签添加为每个日志的前缀。

于 2019-03-06T10:22:37.493 回答
1

I did something like this to get rid of the problem:

    public static class ReleaseTree extends Timber.Tree {

    private static final int MAX_LOG_LENGTH = 4000;
    private static final int MAX_TAG_LENGTH = 23;
    private static final int CALL_STACK_INDEX = 6;
    private static final Pattern ANONYMOUS_CLASS = Pattern.compile("(\\$\\d+)+$");

    @SuppressLint("LogNotTimber")
    @Override
    protected void log(int priority, @Nullable String tag, @NotNull String message, @Nullable Throwable t) {
        if (priority != Log.ERROR) {
            return;
        }

        String newTag = getTag(tag);
        if (message.length() < MAX_LOG_LENGTH) {
            Log.println(priority, newTag, message);
            return;
        }

        // Split by line, then ensure each line can fit into Log's maximum length.
        for (int i = 0, length = message.length(); i < length; i++) {
            int newline = message.indexOf('\n', i);
            newline = newline != -1 ? newline : length;
            do {
                int end = Math.min(newline, i + MAX_LOG_LENGTH);
                String part = message.substring(i, end);
                Log.println(priority, newTag, part);
                i = end;
            } while (i < newline);
        }
    }

    private String getTag(String tag) {
        if (tag != null) {
            return tag;
        }

        // DO NOT switch this to Thread.getCurrentThread().getStackTrace(). The test will pass
        // because Robolectric runs them on the JVM but on Android the elements are different.
        StackTraceElement[] stackTrace = new Throwable().getStackTrace();
        if (stackTrace.length <= CALL_STACK_INDEX) {
            throw new IllegalStateException(
                    "Synthetic stacktrace didn't have enough elements: are you using proguard?");
        }
        return createStackElementTag(stackTrace[CALL_STACK_INDEX]);
    }

    @Nullable
    protected String createStackElementTag(@NotNull StackTraceElement element) {
        String tag = element.getClassName();
        Matcher m = ANONYMOUS_CLASS.matcher(tag);
        if (m.find()) {
            tag = m.replaceAll("");
        }
        tag = tag.substring(tag.lastIndexOf('.') + 1);
        // Tag length limit was removed in API 24.
        if (tag.length() <= MAX_TAG_LENGTH || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return tag;
        }
        return tag.substring(0, MAX_TAG_LENGTH);
    }
}

It's nearly like the implementation of the DebugTree, except that it logs only errors and since error rate should be low we don't have too much overhead ;P

In this case we didn't use reflection in order to find the tag name, but some smart usage of a Throwable instance. For some useful information, you can have a look here.

于 2021-09-14T19:22:05.480 回答