Sentry <> Timber integration: Missing `TimberTag` tag
Integration
sentry-android
Build System
Gradle
AGP Version
8.6.0
Proguard
Enabled
Sentry Version
7.4.0
Timber Version
5.0.1
Steps to Reproduce
- Report issue like so
Timber.tag("MyTag").w(throwable, "Something went wrong")(It's possible that it might be working forTimber.e()) - Open Sentry dashboard and locate the aforementioned issue
Expected Result
In the list of tags we should see TimberTag tag with the valueMyTag
As mentioned by the changelog, TimberTag is supported from version 5.7.2 onwards
Support for Timber.tag has been brought back in version 5.7.2.
Actual Result
When checking tags you can notice that TimberTag tag is missing completely. See attached screenshot with what I mean by tag
@gent-ahmeti thanks for opening this up! We'll have a look into this. Could also share the version of Timber you're using?
Hi @markushi , we are using Timber version 5.0.1. I'll update the description to have this version too
@gent-ahmeti thank you! Could you also share some more details on how you adapted it for the usage with Coroutines? Timber itself utilizes ThreadLocal for tags which could cause troubles with Coroutines:
https://github.com/JakeWharton/timber/blob/beb8051248164a74b264d30427f633aaf4bda841/timber/src/main/java/timber/log/Timber.kt#L19-L23
Looks like we are catching the "tag" before we launch the coroutine. See abbreviated code:
private val pendingTag = ThreadLocal<String?>()
private fun retrieveTag(): String? {
val tag = pendingTag.get()
if (tag != null) {
this.pendingTag.remove()
}
return tag
}
private fun logWithSentry(
priority: Int,
throwable: Throwable?,
message: String?,
vararg args: Any?
) {
val tag = retrieveTag()
// ...
captureEvent(level, tag, sentryMessage, throwable)
// ...
}
// ...
private fun captureEvent(
sentryLevel: SentryLevel,
tag: String?,
msg: Message,
throwable: Throwable?
) {
if (isLoggable(sentryLevel, minEventLevel)) {
val sentryEvent = SentryEvent().apply {
// ...
tag?.let {
setTag("TimberTag", it)
}
// ...
}
// ...
coroutineScope.launch(AppDispatchers.computation) {
Sentry.captureEvent(sentryEvent)
}
}
}
@gent-ahmeti awesome, thanks for sharing! This should give us enough context to reproduce the issue. I'll keep you posted about any updates!
Long overdue update: We're currently blocked by the internal ThreadLocal usage within Timber itself, as it's not exposing any APIs to provide ways to make the tag value coroutine-aware. Blocked by: https://github.com/JakeWharton/timber/issues/565
@gent-ahmeti Could you share a few code snippets on how you're using Timber.tag() within your codebase? As outlined here Timber.tag() should be immediately followed by a .log() call, otherwise you could run into coroutine related issues.
E.g. the following wouldn't work:
Timber.tag("example-tag")
try {
// ... suspend fun(), e.g. io bound
} catch (e: Exception) {
Timber.error(...)
}
Hi @markushi thanks for the updates. We always use it in a chain like so:
Timber.tag(TAG).e(exception)
// or
Timber.tag(TAG).w(exception)