使用Timber时,标签为空。

10
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的类的名称。

3个回答

11
根据Jake Wharton所说:

除非在日志记录网站调用(String)或从DebugTree扩展(在生产日志记录中不应该这样做),否则tag为空。

因此,在每次调用之前需要添加Timber.tag([class name])
请参阅github.com/JakeWharton/timber/issues/122

3

如果你想在发布版的apk中显示/添加标签,有一个小技巧。不要使用 Timber.Tree(),而是使用 Timber.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)

    }
}

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

2
请注意,Jake Wharton(库的作者)警告不要这样做,因为“它非常慢”。 - Tim

1

我做了类似这样的事情来解决这个问题:

    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);
    }
}

这几乎就像实现DebugTree一样,只是它仅记录错误,并且由于错误率应该很低,所以我们没有太多的开销;P

在这种情况下,我们没有使用反射来查找标记名称,而是利用了Throwable实例的某些智能用法。有关一些有用的信息,您可以在这里查看。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接