Merge pull request #4860 from element-hq/feature/bma/extractLogs

Small cleanup around log tag.
This commit is contained in:
Benoit Marty 2025-06-11 17:36:24 +02:00 committed by GitHub
commit 2fabc71efc
2 changed files with 24 additions and 22 deletions

View file

@ -8,12 +8,12 @@
package io.element.android.libraries.matrix.impl package io.element.android.libraries.matrix.impl
import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.core.log.logger.LoggerTag
import io.element.android.libraries.matrix.impl.mapper.toSessionData import io.element.android.libraries.matrix.impl.mapper.toSessionData
import io.element.android.libraries.matrix.impl.paths.getSessionPaths import io.element.android.libraries.matrix.impl.paths.getSessionPaths
import io.element.android.libraries.matrix.impl.util.anonymizedTokens import io.element.android.libraries.matrix.impl.util.anonymizedTokens
import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.api.SessionStore
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.matrix.rustcomponents.sdk.ClientDelegate import org.matrix.rustcomponents.sdk.ClientDelegate
import org.matrix.rustcomponents.sdk.ClientSessionDelegate import org.matrix.rustcomponents.sdk.ClientSessionDelegate
@ -22,6 +22,8 @@ import timber.log.Timber
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
private val loggerTag = LoggerTag("RustClientSessionDelegate")
/** /**
* This class is responsible for handling the session data for the Rust SDK. * This class is responsible for handling the session data for the Rust SDK.
* *
@ -29,14 +31,11 @@ import java.util.concurrent.atomic.AtomicBoolean
* *
* IMPORTANT: you must set the [client] property as soon as possible so [didReceiveAuthError] can work properly. * IMPORTANT: you must set the [client] property as soon as possible so [didReceiveAuthError] can work properly.
*/ */
@OptIn(ExperimentalCoroutinesApi::class)
class RustClientSessionDelegate( class RustClientSessionDelegate(
private val sessionStore: SessionStore, private val sessionStore: SessionStore,
private val appCoroutineScope: CoroutineScope, private val appCoroutineScope: CoroutineScope,
coroutineDispatchers: CoroutineDispatchers, coroutineDispatchers: CoroutineDispatchers,
) : ClientSessionDelegate, ClientDelegate { ) : ClientSessionDelegate, ClientDelegate {
private val clientLog = Timber.tag("$this")
// Used to ensure several calls to `didReceiveAuthError` don't trigger multiple logouts // Used to ensure several calls to `didReceiveAuthError` don't trigger multiple logouts
private val isLoggingOut = AtomicBoolean(false) private val isLoggingOut = AtomicBoolean(false)
@ -64,7 +63,7 @@ class RustClientSessionDelegate(
appCoroutineScope.launch(updateTokensDispatcher) { appCoroutineScope.launch(updateTokensDispatcher) {
val existingData = sessionStore.getSession(session.userId) ?: return@launch val existingData = sessionStore.getSession(session.userId) ?: return@launch
val (anonymizedAccessToken, anonymizedRefreshToken) = session.anonymizedTokens() val (anonymizedAccessToken, anonymizedRefreshToken) = session.anonymizedTokens()
clientLog.d( Timber.tag(loggerTag.value).d(
"Saving new session data with token: access token '$anonymizedAccessToken' and refresh token '$anonymizedRefreshToken'. " + "Saving new session data with token: access token '$anonymizedAccessToken' and refresh token '$anonymizedRefreshToken'. " +
"Was token valid: ${existingData.isTokenValid}" "Was token valid: ${existingData.isTokenValid}"
) )
@ -75,29 +74,29 @@ class RustClientSessionDelegate(
sessionPaths = existingData.getSessionPaths(), sessionPaths = existingData.getSessionPaths(),
) )
sessionStore.updateData(newData) sessionStore.updateData(newData)
clientLog.d("Saved new session data with access token: '$anonymizedAccessToken'.") Timber.tag(loggerTag.value).d("Saved new session data with access token: '$anonymizedAccessToken'.")
}.invokeOnCompletion { }.invokeOnCompletion {
if (it != null) { if (it != null) {
clientLog.e(it, "Failed to save new session data.") Timber.tag(loggerTag.value).e(it, "Failed to save new session data.")
} }
} }
} }
override fun didReceiveAuthError(isSoftLogout: Boolean) { override fun didReceiveAuthError(isSoftLogout: Boolean) {
clientLog.w("didReceiveAuthError(isSoftLogout=$isSoftLogout)") Timber.tag(loggerTag.value).w("didReceiveAuthError(isSoftLogout=$isSoftLogout)")
if (isLoggingOut.getAndSet(true).not()) { if (isLoggingOut.getAndSet(true).not()) {
clientLog.v("didReceiveAuthError -> do the cleanup") Timber.tag(loggerTag.value).v("didReceiveAuthError -> do the cleanup")
// TODO handle isSoftLogout parameter. // TODO handle isSoftLogout parameter.
appCoroutineScope.launch(updateTokensDispatcher) { appCoroutineScope.launch(updateTokensDispatcher) {
val currentClient = client.get() val currentClient = client.get()
if (currentClient == null) { if (currentClient == null) {
clientLog.w("didReceiveAuthError -> no client, exiting") Timber.tag(loggerTag.value).w("didReceiveAuthError -> no client, exiting")
isLoggingOut.set(false) isLoggingOut.set(false)
return@launch return@launch
} }
val existingData = sessionStore.getSession(currentClient.sessionId.value) val existingData = sessionStore.getSession(currentClient.sessionId.value)
val (anonymizedAccessToken, anonymizedRefreshToken) = existingData.anonymizedTokens() val (anonymizedAccessToken, anonymizedRefreshToken) = existingData.anonymizedTokens()
clientLog.d( Timber.tag(loggerTag.value).d(
"Removing session data with access token '$anonymizedAccessToken' " + "Removing session data with access token '$anonymizedAccessToken' " +
"and refresh token '$anonymizedRefreshToken'." "and refresh token '$anonymizedRefreshToken'."
) )
@ -105,18 +104,18 @@ class RustClientSessionDelegate(
// Set isTokenValid to false // Set isTokenValid to false
val newData = existingData.copy(isTokenValid = false) val newData = existingData.copy(isTokenValid = false)
sessionStore.updateData(newData) sessionStore.updateData(newData)
clientLog.d("Invalidated session data with access token: '$anonymizedAccessToken'.") Timber.tag(loggerTag.value).d("Invalidated session data with access token: '$anonymizedAccessToken'.")
} else { } else {
clientLog.d("No session data found.") Timber.tag(loggerTag.value).d("No session data found.")
} }
currentClient.logout(userInitiated = false, ignoreSdkError = true) currentClient.logout(userInitiated = false, ignoreSdkError = true)
}.invokeOnCompletion { }.invokeOnCompletion {
if (it != null) { if (it != null) {
clientLog.e(it, "Failed to remove session data.") Timber.tag(loggerTag.value).e(it, "Failed to remove session data.")
} }
} }
} else { } else {
clientLog.v("didReceiveAuthError -> already cleaning up") Timber.tag(loggerTag.value).v("didReceiveAuthError -> already cleaning up")
} }
} }

View file

@ -10,6 +10,7 @@ package io.element.android.libraries.pushproviders.unifiedpush
import com.squareup.anvil.annotations.ContributesBinding import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.core.data.tryOrNull import io.element.android.libraries.core.data.tryOrNull
import io.element.android.libraries.core.log.logger.LoggerTag
import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.AppScope
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import retrofit2.HttpException import retrofit2.HttpException
@ -29,6 +30,8 @@ interface UnifiedPushGatewayResolver {
suspend fun getGateway(endpoint: String): UnifiedPushGatewayResolverResult suspend fun getGateway(endpoint: String): UnifiedPushGatewayResolverResult
} }
private val loggerTag = LoggerTag("DefaultUnifiedPushGatewayResolver")
@ContributesBinding(AppScope::class) @ContributesBinding(AppScope::class)
class DefaultUnifiedPushGatewayResolver @Inject constructor( class DefaultUnifiedPushGatewayResolver @Inject constructor(
private val unifiedPushApiFactory: UnifiedPushApiFactory, private val unifiedPushApiFactory: UnifiedPushApiFactory,
@ -36,36 +39,36 @@ class DefaultUnifiedPushGatewayResolver @Inject constructor(
) : UnifiedPushGatewayResolver { ) : UnifiedPushGatewayResolver {
override suspend fun getGateway(endpoint: String): UnifiedPushGatewayResolverResult { override suspend fun getGateway(endpoint: String): UnifiedPushGatewayResolverResult {
val url = tryOrNull( val url = tryOrNull(
onException = { Timber.tag("DefaultUnifiedPushGatewayResolver").d(it, "Cannot parse endpoint as an URL") } onException = { Timber.tag(loggerTag.value).d(it, "Cannot parse endpoint as an URL") }
) { ) {
URL(endpoint) URL(endpoint)
} }
return if (url == null) { return if (url == null) {
Timber.tag("DefaultUnifiedPushGatewayResolver").d("ErrorInvalidUrl") Timber.tag(loggerTag.value).d("ErrorInvalidUrl")
UnifiedPushGatewayResolverResult.ErrorInvalidUrl UnifiedPushGatewayResolverResult.ErrorInvalidUrl
} else { } else {
val port = if (url.port != -1) ":${url.port}" else "" val port = if (url.port != -1) ":${url.port}" else ""
val customBase = "${url.protocol}://${url.host}$port" val customBase = "${url.protocol}://${url.host}$port"
val customUrl = "$customBase/_matrix/push/v1/notify" val customUrl = "$customBase/_matrix/push/v1/notify"
Timber.tag("DefaultUnifiedPushGatewayResolver").i("Testing $customUrl") Timber.tag(loggerTag.value).i("Testing $customUrl")
return withContext(coroutineDispatchers.io) { return withContext(coroutineDispatchers.io) {
val api = unifiedPushApiFactory.create(customBase) val api = unifiedPushApiFactory.create(customBase)
try { try {
val discoveryResponse = api.discover() val discoveryResponse = api.discover()
if (discoveryResponse.unifiedpush.gateway == "matrix") { if (discoveryResponse.unifiedpush.gateway == "matrix") {
Timber.tag("DefaultUnifiedPushGatewayResolver").d("The endpoint seems to be a valid UnifiedPush gateway") Timber.tag(loggerTag.value).d("The endpoint seems to be a valid UnifiedPush gateway")
UnifiedPushGatewayResolverResult.Success(customUrl) UnifiedPushGatewayResolverResult.Success(customUrl)
} else { } else {
// The endpoint returned a 200 OK but didn't promote an actual matrix gateway, which means it doesn't have any // The endpoint returned a 200 OK but didn't promote an actual matrix gateway, which means it doesn't have any
Timber.tag("DefaultUnifiedPushGatewayResolver").w("The endpoint does not seem to be a valid UnifiedPush gateway, using fallback") Timber.tag(loggerTag.value).w("The endpoint does not seem to be a valid UnifiedPush gateway, using fallback")
UnifiedPushGatewayResolverResult.NoMatrixGateway UnifiedPushGatewayResolverResult.NoMatrixGateway
} }
} catch (throwable: Throwable) { } catch (throwable: Throwable) {
if ((throwable as? HttpException)?.code() == HttpURLConnection.HTTP_NOT_FOUND) { if ((throwable as? HttpException)?.code() == HttpURLConnection.HTTP_NOT_FOUND) {
Timber.tag("DefaultUnifiedPushGatewayResolver").i("Checking for UnifiedPush endpoint yielded 404, using fallback") Timber.tag(loggerTag.value).i("Checking for UnifiedPush endpoint yielded 404, using fallback")
UnifiedPushGatewayResolverResult.NoMatrixGateway UnifiedPushGatewayResolverResult.NoMatrixGateway
} else { } else {
Timber.tag("DefaultUnifiedPushGatewayResolver").e(throwable, "Error checking for UnifiedPush endpoint") Timber.tag(loggerTag.value).e(throwable, "Error checking for UnifiedPush endpoint")
UnifiedPushGatewayResolverResult.Error(customUrl) UnifiedPushGatewayResolverResult.Error(customUrl)
} }
} }