Fix tracing configuration in debug and nightlies (#3019)

* Fix tracing configuration in debug and nightlies:

- Debug will now write the logs to disk too.
- Nightly will be able to customise tracing filters.
- Improved the configure tracing and bug report screens.

* Update screenshots

* Add changelog

---------

Co-authored-by: ElementBot <benoitm+elementbot@element.io>
This commit is contained in:
Jorge Martin Espinosa 2024-06-12 12:20:43 +02:00 committed by GitHub
parent 9bbe6828f1
commit 54845866a6
9 changed files with 101 additions and 36 deletions

View file

@ -22,7 +22,9 @@ import androidx.preference.PreferenceManager
import androidx.startup.Initializer import androidx.startup.Initializer
import io.element.android.features.preferences.impl.developer.tracing.SharedPreferencesTracingConfigurationStore import io.element.android.features.preferences.impl.developer.tracing.SharedPreferencesTracingConfigurationStore
import io.element.android.features.preferences.impl.developer.tracing.TargetLogLevelMapBuilder import io.element.android.features.preferences.impl.developer.tracing.TargetLogLevelMapBuilder
import io.element.android.features.rageshake.api.reporter.BugReporter
import io.element.android.libraries.architecture.bindings import io.element.android.libraries.architecture.bindings
import io.element.android.libraries.core.meta.BuildType
import io.element.android.libraries.matrix.api.tracing.TracingConfiguration import io.element.android.libraries.matrix.api.tracing.TracingConfiguration
import io.element.android.libraries.matrix.api.tracing.TracingFilterConfigurations import io.element.android.libraries.matrix.api.tracing.TracingFilterConfigurations
import io.element.android.libraries.matrix.api.tracing.WriteToFilesConfiguration import io.element.android.libraries.matrix.api.tracing.WriteToFilesConfiguration
@ -36,31 +38,27 @@ class TracingInitializer : Initializer<Unit> {
val tracingService = appBindings.tracingService() val tracingService = appBindings.tracingService()
val bugReporter = appBindings.bugReporter() val bugReporter = appBindings.bugReporter()
Timber.plant(tracingService.createTimberTree()) Timber.plant(tracingService.createTimberTree())
val tracingConfiguration = if (BuildConfig.DEBUG) { val tracingConfiguration = if (BuildConfig.BUILD_TYPE == BuildType.RELEASE.name) {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
val store = SharedPreferencesTracingConfigurationStore(prefs)
val builder = TargetLogLevelMapBuilder(store)
TracingConfiguration( TracingConfiguration(
filterConfiguration = TracingFilterConfigurations.custom(builder.getCurrentMap()), filterConfiguration = TracingFilterConfigurations.release,
writesToLogcat = true, writesToLogcat = false,
writesToFilesConfiguration = WriteToFilesConfiguration.Disabled writesToFilesConfiguration = defaultWriteToDiskConfiguration(bugReporter),
) )
} else { } else {
val config = if (BuildConfig.BUILD_TYPE == "nightly") { val prefs = PreferenceManager.getDefaultSharedPreferences(context)
TracingFilterConfigurations.nightly val store = SharedPreferencesTracingConfigurationStore(prefs)
} else { val builder = TargetLogLevelMapBuilder(
TracingFilterConfigurations.release tracingConfigurationStore = store,
} defaultConfig = if (BuildConfig.BUILD_TYPE == BuildType.NIGHTLY.name) {
TracingFilterConfigurations.nightly
} else {
TracingFilterConfigurations.debug
}
)
TracingConfiguration( TracingConfiguration(
filterConfiguration = config, filterConfiguration = TracingFilterConfigurations.custom(builder.getCurrentMap()),
writesToLogcat = false, writesToLogcat = BuildConfig.DEBUG,
writesToFilesConfiguration = WriteToFilesConfiguration.Enabled( writesToFilesConfiguration = defaultWriteToDiskConfiguration(bugReporter),
directory = bugReporter.logDirectory().absolutePath,
filenamePrefix = "logs",
filenameSuffix = null,
// Keep a minimum of 1 week of log files.
numberOfFiles = 7 * 24,
)
) )
} }
bugReporter.setCurrentTracingFilter(tracingConfiguration.filterConfiguration.filter) bugReporter.setCurrentTracingFilter(tracingConfiguration.filterConfiguration.filter)
@ -69,5 +67,15 @@ class TracingInitializer : Initializer<Unit> {
Os.setenv("RUST_BACKTRACE", "1", true) Os.setenv("RUST_BACKTRACE", "1", true)
} }
private fun defaultWriteToDiskConfiguration(bugReporter: BugReporter): WriteToFilesConfiguration.Enabled {
return WriteToFilesConfiguration.Enabled(
directory = bugReporter.logDirectory().absolutePath,
filenamePrefix = "logs",
filenameSuffix = null,
// Keep a minimum of 1 week of log files.
numberOfFiles = 7 * 24,
)
}
override fun dependencies(): List<Class<out Initializer<*>>> = mutableListOf() override fun dependencies(): List<Class<out Initializer<*>>> = mutableListOf()
} }

5
changelog.d/3016.bugfix Normal file
View file

@ -0,0 +1,5 @@
Fix tracing configuration in debug and nightlies:
- Debug will now write the logs to disk too.
- Nightly will be able to customise tracing filters.
- Improved the configure tracing and bug report screens.

View file

@ -16,6 +16,7 @@
package io.element.android.features.preferences.impl.developer.tracing package io.element.android.features.preferences.impl.developer.tracing
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsets
@ -48,6 +49,7 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.aliasScreenTitle import io.element.android.libraries.designsystem.theme.aliasScreenTitle
import io.element.android.libraries.designsystem.theme.components.DropdownMenu import io.element.android.libraries.designsystem.theme.components.DropdownMenu
import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem
import io.element.android.libraries.designsystem.theme.components.HorizontalDivider
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.IconButton import io.element.android.libraries.designsystem.theme.components.IconButton
import io.element.android.libraries.designsystem.theme.components.ListItem import io.element.android.libraries.designsystem.theme.components.ListItem
@ -124,15 +126,17 @@ fun ConfigureTracingView(
.consumeWindowInsets(it) .consumeWindowInsets(it)
.verticalScroll(state = rememberScrollState()) .verticalScroll(state = rememberScrollState())
) { ) {
CrateListContent(state)
ListItem( ListItem(
headlineContent = { headlineContent = {
Text( Text(
text = "Kill and restart the app for the change to take effect.", modifier = Modifier.clickable { Runtime.getRuntime().exit(0) },
text = "Tap here to kill the app and apply the changes. You'll have to re-open the app manually.",
style = ElementTheme.typography.fontHeadingSmMedium, style = ElementTheme.typography.fontHeadingSmMedium,
) )
}, },
) )
HorizontalDivider()
CrateListContent(state)
} }
} }
) )

View file

@ -18,14 +18,13 @@ package io.element.android.features.preferences.impl.developer.tracing
import io.element.android.libraries.matrix.api.tracing.LogLevel import io.element.android.libraries.matrix.api.tracing.LogLevel
import io.element.android.libraries.matrix.api.tracing.Target import io.element.android.libraries.matrix.api.tracing.Target
import io.element.android.libraries.matrix.api.tracing.TracingFilterConfigurations import io.element.android.libraries.matrix.api.tracing.TracingFilterConfiguration
import javax.inject.Inject import javax.inject.Inject
class TargetLogLevelMapBuilder @Inject constructor( class TargetLogLevelMapBuilder @Inject constructor(
private val tracingConfigurationStore: TracingConfigurationStore, private val tracingConfigurationStore: TracingConfigurationStore,
private val defaultConfig: TracingFilterConfiguration,
) { ) {
private val defaultConfig = TracingFilterConfigurations.debug
fun getDefaultMap(): Map<Target, LogLevel> { fun getDefaultMap(): Map<Target, LogLevel> {
return Target.entries.associateWith { target -> return Target.entries.associateWith { target ->
defaultConfig.getLogLevel(target) defaultConfig.getLogLevel(target)

View file

@ -22,6 +22,7 @@ import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.tracing.LogLevel import io.element.android.libraries.matrix.api.tracing.LogLevel
import io.element.android.libraries.matrix.api.tracing.Target import io.element.android.libraries.matrix.api.tracing.Target
import io.element.android.libraries.matrix.api.tracing.TracingFilterConfigurations
import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.waitForPredicate import io.element.android.tests.testutils.waitForPredicate
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
@ -37,7 +38,7 @@ class ConfigureTracingPresenterTest {
val store = InMemoryTracingConfigurationStore() val store = InMemoryTracingConfigurationStore()
val presenter = ConfigureTracingPresenter( val presenter = ConfigureTracingPresenter(
store, store,
TargetLogLevelMapBuilder(store), TargetLogLevelMapBuilder(store, TracingFilterConfigurations.debug),
) )
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
presenter.present() presenter.present()
@ -54,7 +55,7 @@ class ConfigureTracingPresenterTest {
store.givenLogLevel(LogLevel.ERROR) store.givenLogLevel(LogLevel.ERROR)
val presenter = ConfigureTracingPresenter( val presenter = ConfigureTracingPresenter(
store, store,
TargetLogLevelMapBuilder(store), TargetLogLevelMapBuilder(store, TracingFilterConfigurations.debug),
) )
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
presenter.present() presenter.present()
@ -70,7 +71,7 @@ class ConfigureTracingPresenterTest {
val store = InMemoryTracingConfigurationStore() val store = InMemoryTracingConfigurationStore()
val presenter = ConfigureTracingPresenter( val presenter = ConfigureTracingPresenter(
store, store,
TargetLogLevelMapBuilder(store), TargetLogLevelMapBuilder(store, TracingFilterConfigurations.debug),
) )
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
presenter.present() presenter.present()
@ -89,7 +90,7 @@ class ConfigureTracingPresenterTest {
val store = InMemoryTracingConfigurationStore() val store = InMemoryTracingConfigurationStore()
val presenter = ConfigureTracingPresenter( val presenter = ConfigureTracingPresenter(
store, store,
TargetLogLevelMapBuilder(store), TargetLogLevelMapBuilder(store, TracingFilterConfigurations.debug),
) )
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
presenter.present() presenter.present()

View file

@ -21,6 +21,7 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@ -28,6 +29,8 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.text.input.KeyboardCapitalization
@ -51,6 +54,7 @@ import io.element.android.libraries.designsystem.preview.debugPlaceholderBackgro
import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.OutlinedTextField import io.element.android.libraries.designsystem.theme.components.OutlinedTextField
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.onTabOrEnterKeyFocusNext
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@Composable @Composable
@ -68,6 +72,7 @@ fun BugReportView(
title = stringResource(id = CommonStrings.common_report_a_problem), title = stringResource(id = CommonStrings.common_report_a_problem),
onBackClick = onBackClick onBackClick = onBackClick
) { ) {
val keyboardController = LocalSoftwareKeyboardController.current
val isFormEnabled = state.sending !is AsyncAction.Loading val isFormEnabled = state.sending !is AsyncAction.Loading
var descriptionFieldState by textFieldState( var descriptionFieldState by textFieldState(
stateValue = state.formState.description stateValue = state.formState.description
@ -76,7 +81,8 @@ fun BugReportView(
PreferenceRow { PreferenceRow {
OutlinedTextField( OutlinedTextField(
value = descriptionFieldState, value = descriptionFieldState,
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth()
.onTabOrEnterKeyFocusNext(LocalFocusManager.current),
enabled = isFormEnabled, enabled = isFormEnabled,
label = { label = {
Text(text = stringResource(id = R.string.screen_bug_report_editor_placeholder)) Text(text = stringResource(id = R.string.screen_bug_report_editor_placeholder))
@ -91,8 +97,11 @@ fun BugReportView(
keyboardOptions = KeyboardOptions( keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.Sentences, capitalization = KeyboardCapitalization.Sentences,
keyboardType = KeyboardType.Text, keyboardType = KeyboardType.Text,
imeAction = ImeAction.Next imeAction = ImeAction.Next,
), ),
keyboardActions = KeyboardActions(onNext = {
keyboardController?.hide()
}),
minLines = 3, minLines = 3,
isError = state.isDescriptionInError, isError = state.isDescriptionInError,
) )

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2024 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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
}
}
}

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:958e7d5c11e25cfc4936299e743c2d5a3fd3edfa79b8d89f6d426aa3978a503d oid sha256:fe4b464a9962ad28f50e0f5d3de149c7d0ceedc60c01ab1ac733556d15de7079
size 32802 size 38637

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:4eaa277cbed0296a58ef6282ea9cd92739d363cd7e57fdac96f6ca1d7eaa15f4 oid sha256:a7366935aa7e4b5d4da7760a2f492dffc7c8b9e6d2d574c7bbd7fe5ae830be7f
size 31669 size 37200