-
Notifications
You must be signed in to change notification settings - Fork 45
Description
Kermit version: 2.0.8
Hello, I noticed that when I call Logger.a with added LogcatWriter, it will print the log to Logcat with ERROR severity instead of the expected ASSERT. I found out that this is actually a common issue in many libraries including Timber or Pluto and that's because this is actually a bug in the Logcat itself. LogcatWriter uses Log.wtf for Severity.Assert. This seems ok, because Log.wtf's documentation says: "The error will always be logged at level ASSERT with the call stack.", but when you call it, it uses ERROR and when you look at the source code it looks like this:
static int wtf(int logId, @Nullable String tag, @Nullable String msg, @Nullable Throwable tr,
boolean localStack, boolean system) {
TerribleFailure what = new TerribleFailure(msg, tr);
// Only mark this as ERROR, do not use ASSERT since that should be
// reserved for cases where the system is guaranteed to abort.
// The onTerribleFailure call does not always cause a crash.
int bytes = printlns(logId, ERROR, tag, msg, localStack ? what : tr);
sWtfHandler.onTerribleFailure(tag, what, system);
return bytes;
}
It actually always uses ERROR intentionally, even though it is against the method contract.
The other issue with Log.wtf is that it might possibly terminate your process under some conditions, which is not something I would personally expect when I call Kermit's Logger.a that should just log the message with Severity.Assert. For example Timber has Timber.wtf, which clearly indicates that it delegates the call to Log.wtf, so you can expect that, but for plain assert logs, I would like to just log with Severity.Assert and not potentially terminate the app.
I would suggest to fix this by logging Log.ASSERT directly using Log.println(Log.ASSERT, "tag", "message"). Not only this logs severity properly, but it does not execute the onTerribleFailure logic that might terminate the app.
The only problem is with Throwable overload. When you want to log the Throwable as well, there is no println overload accepting Throwable. However, this can be solved by serializing the stack trace and appending it to the message. The result looks exactly the same as using wtf method with Throwable.
Example:
Log.wtf("wtf tag", "wtf message", Throwable("wtf throwable"))
Log.println(
Log.ASSERT,
"assert tag",
"assert message\n${Log.getStackTraceString(Throwable("assert throwable"))}",
)
looks like this in Android Studio's Logcat:
