change(tracing) : change how tracing is configured (ui and logic)
This commit is contained in:
parent
fd3b99765d
commit
7d27e6581b
38 changed files with 220 additions and 886 deletions
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright 2022-2024 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.api.tracing
|
||||
|
||||
/**
|
||||
* Log levels for tracing in the SDK.
|
||||
*/
|
||||
enum class LogLevel {
|
||||
ERROR,
|
||||
WARN,
|
||||
INFO,
|
||||
DEBUG,
|
||||
TRACE,
|
||||
}
|
||||
|
|
@ -8,7 +8,8 @@
|
|||
package io.element.android.libraries.matrix.api.tracing
|
||||
|
||||
data class TracingConfiguration(
|
||||
val filterConfiguration: TracingFilterConfiguration,
|
||||
val logLevel: LogLevel,
|
||||
val extraTargets: List<String>,
|
||||
val writesToLogcat: Boolean,
|
||||
val writesToFilesConfiguration: WriteToFilesConfiguration,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,102 +0,0 @@
|
|||
/*
|
||||
* Copyright 2022-2024 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.api.tracing
|
||||
|
||||
data class TracingFilterConfiguration(
|
||||
val overrides: Map<Target, LogLevel> = emptyMap(),
|
||||
) {
|
||||
private val defaultLogLevel = LogLevel.INFO
|
||||
|
||||
// Order should matters
|
||||
private val targetsToLogLevel: Map<Target, LogLevel> = mapOf(
|
||||
Target.HYPER to LogLevel.WARN,
|
||||
Target.MATRIX_SDK_CRYPTO to LogLevel.DEBUG,
|
||||
Target.MATRIX_SDK_CRYPTO_ACCOUNT to LogLevel.TRACE,
|
||||
Target.MATRIX_SDK_HTTP_CLIENT to LogLevel.DEBUG,
|
||||
Target.MATRIX_SDK_SLIDING_SYNC to LogLevel.INFO,
|
||||
Target.MATRIX_SDK_BASE_SLIDING_SYNC to LogLevel.INFO,
|
||||
Target.MATRIX_SDK_UI_TIMELINE to LogLevel.INFO,
|
||||
Target.MATRIX_SDK_BASE_CLIENT to LogLevel.TRACE,
|
||||
// To debug OIDC logouts
|
||||
Target.MATRIX_SDK_OIDC to LogLevel.TRACE,
|
||||
)
|
||||
|
||||
fun getLogLevel(target: Target): LogLevel {
|
||||
return overrides[target] ?: targetsToLogLevel[target] ?: defaultLogLevel
|
||||
}
|
||||
|
||||
val filter: String
|
||||
get() {
|
||||
val fullMap = Target.entries.associateWith {
|
||||
overrides[it] ?: targetsToLogLevel[it] ?: defaultLogLevel
|
||||
}
|
||||
return fullMap.map {
|
||||
if (it.key.filter.isEmpty()) {
|
||||
it.value.filter
|
||||
} else {
|
||||
"${it.key.filter}=${it.value.filter}"
|
||||
}
|
||||
}.joinToString(separator = ",")
|
||||
}
|
||||
}
|
||||
|
||||
enum class Target(open val filter: String) {
|
||||
// COMMON(""),
|
||||
ELEMENT("elementx"),
|
||||
HYPER("hyper"),
|
||||
MATRIX_SDK_FFI("matrix_sdk_ffi"),
|
||||
MATRIX_SDK_UNIFFI_API("matrix_sdk_ffi::uniffi_api"),
|
||||
MATRIX_SDK_CRYPTO("matrix_sdk_crypto"),
|
||||
MATRIX_SDK_CRYPTO_ACCOUNT("matrix_sdk_crypto::olm::account"),
|
||||
MATRIX_SDK("matrix_sdk"),
|
||||
MATRIX_SDK_HTTP_CLIENT("matrix_sdk::http_client"),
|
||||
MATRIX_SDK_CLIENT("matrix_sdk::client"),
|
||||
MATRIX_SDK_OIDC("matrix_sdk::oidc"),
|
||||
MATRIX_SDK_SEND_QUEUE("matrix_sdk::send_queue"),
|
||||
MATRIX_SDK_SLIDING_SYNC("matrix_sdk::sliding_sync"),
|
||||
MATRIX_SDK_BASE_SLIDING_SYNC("matrix_sdk_base::sliding_sync"),
|
||||
MATRIX_SDK_UI_TIMELINE("matrix_sdk_ui::timeline"),
|
||||
MATRIX_SDK_BASE_READ_RECEIPTS("matrix_sdk_base::read_receipts"),
|
||||
MATRIX_SDK_BASE_CLIENT("matrix_sdk_base"),
|
||||
}
|
||||
|
||||
enum class LogLevel(open val filter: String) {
|
||||
ERROR("error"),
|
||||
WARN("warn"),
|
||||
INFO("info"),
|
||||
DEBUG("debug"),
|
||||
TRACE("trace"),
|
||||
}
|
||||
|
||||
object TracingFilterConfigurations {
|
||||
val release = TracingFilterConfiguration(
|
||||
overrides = mapOf(
|
||||
Target.ELEMENT to LogLevel.DEBUG
|
||||
),
|
||||
)
|
||||
val nightly = TracingFilterConfiguration(
|
||||
overrides = mapOf(
|
||||
Target.ELEMENT to LogLevel.TRACE,
|
||||
),
|
||||
)
|
||||
val debug = TracingFilterConfiguration(
|
||||
overrides = mapOf(
|
||||
Target.ELEMENT to LogLevel.TRACE
|
||||
)
|
||||
)
|
||||
|
||||
/**
|
||||
* Use this method to create a custom configuration where all targets will have the same log level.
|
||||
*/
|
||||
fun custom(logLevel: LogLevel) = TracingFilterConfiguration(overrides = Target.entries.associateWith { logLevel })
|
||||
|
||||
/**
|
||||
* Use this method to override the log level of specific targets.
|
||||
*/
|
||||
fun custom(overrides: Map<Target, LogLevel>) = TracingFilterConfiguration(overrides)
|
||||
}
|
||||
|
|
@ -11,5 +11,5 @@ import timber.log.Timber
|
|||
|
||||
interface TracingService {
|
||||
fun setupTracing(tracingConfiguration: TracingConfiguration)
|
||||
fun createTimberTree(): Timber.Tree
|
||||
fun createTimberTree(target: String): Timber.Tree
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* Copyright 2024 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.di
|
||||
|
||||
import com.squareup.anvil.annotations.ContributesTo
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.core.meta.BuildType
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.matrix.api.tracing.TracingFilterConfiguration
|
||||
import io.element.android.libraries.matrix.api.tracing.TracingFilterConfigurations
|
||||
|
||||
@Module
|
||||
@ContributesTo(AppScope::class)
|
||||
object TracingMatrixModule {
|
||||
@Provides
|
||||
fun providesTracingFilterConfiguration(buildMeta: BuildMeta): TracingFilterConfiguration {
|
||||
return when (buildMeta.buildType) {
|
||||
BuildType.DEBUG -> TracingFilterConfigurations.debug
|
||||
BuildType.NIGHTLY -> TracingFilterConfigurations.nightly
|
||||
BuildType.RELEASE -> TracingFilterConfigurations.release
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ package io.element.android.libraries.matrix.impl.tracing
|
|||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.matrix.api.tracing.LogLevel
|
||||
import io.element.android.libraries.matrix.api.tracing.TracingConfiguration
|
||||
import io.element.android.libraries.matrix.api.tracing.TracingService
|
||||
import io.element.android.libraries.matrix.api.tracing.WriteToFilesConfiguration
|
||||
|
|
@ -20,21 +21,28 @@ import javax.inject.Inject
|
|||
@ContributesBinding(AppScope::class)
|
||||
class RustTracingService @Inject constructor(private val buildMeta: BuildMeta) : TracingService {
|
||||
override fun setupTracing(tracingConfiguration: TracingConfiguration) {
|
||||
/*
|
||||
val filter = tracingConfiguration.filterConfiguration
|
||||
val rustTracingConfiguration = org.matrix.rustcomponents.sdk.TracingConfiguration(
|
||||
filter = tracingConfiguration.filterConfiguration.filter,
|
||||
writeToStdoutOrSystem = tracingConfiguration.writesToLogcat,
|
||||
logLevel = tracingConfiguration.logLevel.toRustLogLevel(),
|
||||
extraTargets = tracingConfiguration.extraTargets,
|
||||
writeToFiles = tracingConfiguration.writesToFilesConfiguration.toTracingFileConfiguration(),
|
||||
)
|
||||
org.matrix.rustcomponents.sdk.setupTracing(rustTracingConfiguration)
|
||||
Timber.v("Tracing config filter = $filter: ${filter.filter}")
|
||||
|
||||
*/
|
||||
Timber.d("setupTracing: $rustTracingConfiguration")
|
||||
}
|
||||
|
||||
override fun createTimberTree(): Timber.Tree {
|
||||
return RustTracingTree(retrieveFromStackTrace = buildMeta.isDebuggable)
|
||||
override fun createTimberTree(target: String): Timber.Tree {
|
||||
return RustTracingTree(target = target, retrieveFromStackTrace = buildMeta.isDebuggable)
|
||||
}
|
||||
}
|
||||
|
||||
private fun LogLevel.toRustLogLevel(): org.matrix.rustcomponents.sdk.LogLevel {
|
||||
return when (this) {
|
||||
LogLevel.ERROR -> org.matrix.rustcomponents.sdk.LogLevel.ERROR
|
||||
LogLevel.WARN -> org.matrix.rustcomponents.sdk.LogLevel.WARN
|
||||
LogLevel.INFO -> org.matrix.rustcomponents.sdk.LogLevel.INFO
|
||||
LogLevel.DEBUG -> org.matrix.rustcomponents.sdk.LogLevel.DEBUG
|
||||
LogLevel.TRACE -> org.matrix.rustcomponents.sdk.LogLevel.TRACE
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
package io.element.android.libraries.matrix.impl.tracing
|
||||
|
||||
import android.util.Log
|
||||
import io.element.android.libraries.matrix.api.tracing.Target
|
||||
import org.matrix.rustcomponents.sdk.LogLevel
|
||||
import org.matrix.rustcomponents.sdk.logEvent
|
||||
import timber.log.Timber
|
||||
|
|
@ -26,7 +25,10 @@ private val fqcnIgnore = listOf(
|
|||
/**
|
||||
* A Timber tree that passes logs to the Rust SDK.
|
||||
*/
|
||||
internal class RustTracingTree(private val retrieveFromStackTrace: Boolean) : Timber.Tree() {
|
||||
internal class RustTracingTree(
|
||||
private val target: String,
|
||||
private val retrieveFromStackTrace: Boolean,
|
||||
) : Timber.Tree() {
|
||||
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
||||
val location = if (retrieveFromStackTrace) {
|
||||
getLogEventLocationFromStackTrace()
|
||||
|
|
@ -38,7 +40,7 @@ internal class RustTracingTree(private val retrieveFromStackTrace: Boolean) : Ti
|
|||
file = location.file,
|
||||
line = location.line,
|
||||
level = logLevel,
|
||||
target = Target.ELEMENT.filter,
|
||||
target = target,
|
||||
message = if (tag != null) "[$tag] $message" else message,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* Copyright 2024 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.di
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.core.meta.BuildType
|
||||
import io.element.android.libraries.matrix.api.tracing.TracingFilterConfigurations
|
||||
import io.element.android.libraries.matrix.test.core.aBuildMeta
|
||||
import org.junit.Test
|
||||
|
||||
class TracingMatrixModuleTest {
|
||||
@Test
|
||||
fun `providesTracingFilterConfiguration returns debug config for debug build`() {
|
||||
assertThat(TracingMatrixModule.providesTracingFilterConfiguration(aBuildMeta(BuildType.DEBUG)))
|
||||
.isEqualTo(TracingFilterConfigurations.debug)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `providesTracingFilterConfiguration returns nightly config for nightly build`() {
|
||||
assertThat(TracingMatrixModule.providesTracingFilterConfiguration(aBuildMeta(BuildType.NIGHTLY)))
|
||||
.isEqualTo(TracingFilterConfigurations.nightly)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `providesTracingFilterConfiguration returns release config for release build`() {
|
||||
assertThat(TracingMatrixModule.providesTracingFilterConfiguration(aBuildMeta(BuildType.RELEASE)))
|
||||
.isEqualTo(TracingFilterConfigurations.release)
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
package io.element.android.libraries.preferences.api.store
|
||||
|
||||
import io.element.android.libraries.matrix.api.tracing.LogLevel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface AppPreferencesStore {
|
||||
|
|
@ -25,5 +26,8 @@ interface AppPreferencesStore {
|
|||
suspend fun setHideImagesAndVideos(value: Boolean)
|
||||
fun doesHideImagesAndVideosFlow(): Flow<Boolean>
|
||||
|
||||
suspend fun setTracingLogLevel(logLevel: LogLevel)
|
||||
fun getTracingLogLevelFlow(): Flow<LogLevel>
|
||||
|
||||
suspend fun reset()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import io.element.android.libraries.core.meta.BuildMeta
|
|||
import io.element.android.libraries.core.meta.BuildType
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
import io.element.android.libraries.matrix.api.tracing.LogLevel
|
||||
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
|
@ -31,6 +32,7 @@ private val customElementCallBaseUrlKey = stringPreferencesKey("elementCallBaseU
|
|||
private val themeKey = stringPreferencesKey("theme")
|
||||
private val simplifiedSlidingSyncKey = booleanPreferencesKey("useSimplifiedSlidingSync")
|
||||
private val hideImagesAndVideosKey = booleanPreferencesKey("hideImagesAndVideos")
|
||||
private val logLevelKey = stringPreferencesKey("logLevel")
|
||||
|
||||
@ContributesBinding(AppScope::class)
|
||||
class DefaultAppPreferencesStore @Inject constructor(
|
||||
|
|
@ -104,7 +106,27 @@ class DefaultAppPreferencesStore @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun setTracingLogLevel(logLevel: LogLevel) {
|
||||
store.edit { prefs ->
|
||||
prefs[logLevelKey] = logLevel.name
|
||||
}
|
||||
}
|
||||
|
||||
override fun getTracingLogLevelFlow(): Flow<LogLevel> {
|
||||
return store.data.map { prefs ->
|
||||
prefs[logLevelKey]?.let { LogLevel.valueOf(it) } ?: buildMeta.defaultLogLevel()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun reset() {
|
||||
store.edit { it.clear() }
|
||||
}
|
||||
}
|
||||
|
||||
private fun BuildMeta.defaultLogLevel(): LogLevel {
|
||||
return when (buildType) {
|
||||
BuildType.DEBUG -> LogLevel.TRACE
|
||||
BuildType.NIGHTLY -> LogLevel.DEBUG
|
||||
BuildType.RELEASE -> LogLevel.INFO
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
package io.element.android.libraries.preferences.test
|
||||
|
||||
import io.element.android.libraries.matrix.api.tracing.LogLevel
|
||||
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
@ -16,13 +17,15 @@ class InMemoryAppPreferencesStore(
|
|||
hideImagesAndVideos: Boolean = false,
|
||||
customElementCallBaseUrl: String? = null,
|
||||
theme: String? = null,
|
||||
simplifiedSlidingSyncEnabled: Boolean = false
|
||||
simplifiedSlidingSyncEnabled: Boolean = false,
|
||||
logLevel: LogLevel = LogLevel.INFO,
|
||||
) : AppPreferencesStore {
|
||||
private val isDeveloperModeEnabled = MutableStateFlow(isDeveloperModeEnabled)
|
||||
private val hideImagesAndVideos = MutableStateFlow(hideImagesAndVideos)
|
||||
private val customElementCallBaseUrl = MutableStateFlow(customElementCallBaseUrl)
|
||||
private val theme = MutableStateFlow(theme)
|
||||
private val simplifiedSlidingSyncEnabled = MutableStateFlow(simplifiedSlidingSyncEnabled)
|
||||
private val logLevel = MutableStateFlow(logLevel)
|
||||
|
||||
override suspend fun setDeveloperModeEnabled(enabled: Boolean) {
|
||||
isDeveloperModeEnabled.value = enabled
|
||||
|
|
@ -64,6 +67,14 @@ class InMemoryAppPreferencesStore(
|
|||
return hideImagesAndVideos
|
||||
}
|
||||
|
||||
override suspend fun setTracingLogLevel(logLevel: LogLevel) {
|
||||
this.logLevel.value = logLevel
|
||||
}
|
||||
|
||||
override fun getTracingLogLevelFlow(): Flow<LogLevel> {
|
||||
return logLevel
|
||||
}
|
||||
|
||||
override suspend fun reset() {
|
||||
// No op
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue