【问题标题】:Tag is null when using Timber使用 Timber 时标签为空
【发布时间】:2016-11-16 16:59:30
【问题描述】:

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

【问题讨论】:

    标签: android android-log timber-android


    【解决方案1】:

    根据杰克·沃顿的说法:

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

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

    github.com/JakeWharton/timber/issues/122

    【讨论】:

      【解决方案2】:

      如果你想在发布 apk 中显示/添加标签,有一个 hack。不要使用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)
      
          }
      }
      

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

      【讨论】:

      • 请注意,Jake Wharton(图书馆作者)警告不要这样做,因为“它非常慢”
      【解决方案3】:

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

          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 实例进行了一些巧妙的使用。一些有用的信息,你可以看看here

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-04-20
        • 1970-01-01
        • 1970-01-01
        • 2016-01-03
        • 2021-08-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多