Skip to content
This repository has been archived by the owner on Nov 12, 2024. It is now read-only.

Add developer log screen #1506

Merged
merged 2 commits into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ object SettingsScreen : TiviScreen(name = "Settings()")
@CommonParcelize
object DevSettingsScreen : TiviScreen(name = "DevelopmentSettings()")

@CommonParcelize
object DevLogScreen : TiviScreen(name = "DevelopmentLog()")

@CommonParcelize
data class UrlScreen(val url: String) : TiviScreen(name = "UrlScreen()") {
override val arguments get() = mapOf("url" to url)
Expand Down
10 changes: 10 additions & 0 deletions core/logging/api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,13 @@
plugins {
id("app.tivi.kotlin.multiplatform")
}

kotlin {
sourceSets {
val commonMain by getting {
dependencies {
api(libs.kotlin.coroutines.core)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@
package app.tivi.util

interface Logger {

fun setup(debugMode: Boolean) = Unit

fun setUserId(id: String) = Unit

/** Log a verbose exception and a message with optional format args. */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2023, Christopher Banes and the Tivi project contributors
// SPDX-License-Identifier: Apache-2.0

package app.tivi.util

import kotlinx.coroutines.flow.StateFlow

interface RecordingLogger : Logger {
val buffer: StateFlow<List<LogMessage>>
}

enum class Severity {
Verbose,
Debug,
Info,
Warn,
Error,
Assert,
}

class LogMessage(
val severity: Severity,
message: () -> String,
val throwable: Throwable?,
) {
val message: String by lazy { message() }
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ import me.tatarka.inject.annotations.Provides
actual interface LoggerPlatformComponent {
@ApplicationScope
@Provides
fun provideLogger(): Logger = TimberLogger
fun provideLogger(
timberLogger: TimberLogger,
recordingLogger: RecordingLogger,
): Logger = CompositeLogger(timberLogger, recordingLogger)

@Provides
@IntoSet
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,20 @@ package app.tivi.util

import android.os.Build
import android.util.Log
import app.tivi.app.ApplicationInfo
import app.tivi.app.Flavor
import co.touchlab.crashkios.crashlytics.CrashlyticsKotlin
import me.tatarka.inject.annotations.Inject
import timber.log.Timber

internal object TimberLogger : Logger {
override fun setup(debugMode: Boolean) {
if (debugMode) {
@Inject
class TimberLogger(applicationInfo: ApplicationInfo) : Logger {

init {
if (applicationInfo.debugBuild || applicationInfo.flavor == Flavor.Qa) {
Timber.plant(TiviDebugTree())
}

try {
Timber.plant(CrashlyticsTree())
} catch (e: IllegalStateException) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@

package app.tivi.util

internal fun CompositeLogger(vararg loggers: Logger): Logger = CompositeLogger(loggers = loggers)
internal fun CompositeLogger(
vararg loggers: Logger?,
): Logger = CompositeLogger(loggers = loggers.filterNotNull())

private class CompositeLogger(
private val loggers: Array<out Logger>,
private val loggers: Collection<Logger>,
) : Logger {
override fun setup(debugMode: Boolean) {
loggers.forEach { it.setup(debugMode) }
}

override fun setUserId(id: String) {
loggers.forEach { it.setUserId(id) }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,22 @@

package app.tivi.util

import app.tivi.app.ApplicationInfo
import app.tivi.app.Flavor
import co.touchlab.kermit.Logger as Kermit
import co.touchlab.kermit.Severity

internal object KermitLogger : Logger {
override fun setup(debugMode: Boolean) {
Kermit.setMinSeverity(if (debugMode) Severity.Debug else Severity.Error)
import me.tatarka.inject.annotations.Inject

@Inject
class KermitLogger(applicationInfo: ApplicationInfo) : Logger {
init {
Kermit.setMinSeverity(
when {
applicationInfo.debugBuild -> Severity.Debug
applicationInfo.flavor == Flavor.Qa -> Severity.Debug
else -> Severity.Error
},
)
}

override fun v(throwable: Throwable?, message: () -> String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@

package app.tivi.util

import app.tivi.appinitializers.AppInitializer
import me.tatarka.inject.annotations.IntoSet
import app.tivi.inject.ApplicationScope
import me.tatarka.inject.annotations.Provides

expect interface LoggerPlatformComponent

interface LoggerComponent : LoggerPlatformComponent {
@ApplicationScope
@Provides
@IntoSet
fun provideLoggerInitializer(bind: LoggerInitializer): AppInitializer = bind
fun bindRecordingLogger(): RecordingLogger = RecordingLoggerImpl()
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright 2023, Christopher Banes and the Tivi project contributors
// SPDX-License-Identifier: Apache-2.0

package app.tivi.util

import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow

internal class RecordingLoggerImpl(
private val bufferSize: Int = 50,
) : RecordingLogger {

private val logs = ArrayDeque<LogMessage>(bufferSize)
private val _buffer = MutableStateFlow<List<LogMessage>>(logs)

override val buffer get() = _buffer.asStateFlow()

override fun v(throwable: Throwable?, message: () -> String) {
addLog(LogMessage(Severity.Verbose, message, throwable))
}

override fun d(throwable: Throwable?, message: () -> String) {
addLog(LogMessage(Severity.Debug, message, throwable))
}

override fun i(throwable: Throwable?, message: () -> String) {
addLog(LogMessage(Severity.Info, message, throwable))
}

override fun e(throwable: Throwable?, message: () -> String) {
addLog(LogMessage(Severity.Error, message, throwable))
}

override fun w(throwable: Throwable?, message: () -> String) {
addLog(LogMessage(Severity.Warn, message, throwable))
}

private fun addLog(logMessage: LogMessage) {
while (logs.size >= bufferSize) {
logs.removeFirst()
}
logs.add(logMessage)
_buffer.value = logs.toList()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import me.tatarka.inject.annotations.Provides
actual interface LoggerPlatformComponent {
@Provides
@ApplicationScope
fun provideLogger(): Logger = CompositeLogger(KermitLogger, CrashKIosLogger)
fun provideLogger(
kermitLogger: KermitLogger,
): Logger = CompositeLogger(kermitLogger, CrashKIosLogger)

@Provides
@IntoSet
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@

package app.tivi.util

import app.tivi.inject.ApplicationScope
import me.tatarka.inject.annotations.Provides

actual interface LoggerPlatformComponent {
@Provides
fun provideLogger(): Logger = KermitLogger
@ApplicationScope
fun provideLogger(
kermitLogger: KermitLogger,
recordingLogger: RecordingLogger,
): Logger = CompositeLogger(kermitLogger, recordingLogger)
}
5 changes: 3 additions & 2 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ include(
":tasks",
":domain",
":shared",
":ui:developer:log",
":ui:developer:settings",
":ui:discover",
":ui:episode:details",
":ui:episode:track",
Expand All @@ -115,8 +117,7 @@ include(
":ui:search",
":ui:show:details",
":ui:show:seasons",
":ui:settings:settings",
":ui:settings:developer",
":ui:settings",
":ui:library",
":ui:account",
":ui:upnext",
Expand Down
5 changes: 3 additions & 2 deletions shared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ kotlin {
api(projects.common.ui.compose)

api(projects.ui.account)
api(projects.ui.developer.log)
api(projects.ui.developer.settings)
api(projects.ui.discover)
api(projects.ui.episode.details)
api(projects.ui.episode.track)
Expand All @@ -44,8 +46,7 @@ kotlin {
api(projects.ui.show.details)
api(projects.ui.show.seasons)
api(projects.ui.root)
api(projects.ui.settings.settings)
api(projects.ui.settings.developer)
api(projects.ui.settings)
api(projects.ui.upnext)
}
}
Expand Down
2 changes: 2 additions & 0 deletions shared/src/commonMain/kotlin/app/tivi/inject/UiComponent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import app.tivi.account.AccountComponent
import app.tivi.common.ui.resources.Locales
import app.tivi.common.ui.resources.Strings
import app.tivi.common.ui.resources.TiviStrings
import app.tivi.developer.log.DevLogComponent
import app.tivi.episode.track.EpisodeTrackComponent
import app.tivi.episodedetails.EpisodeDetailsComponent
import app.tivi.home.discover.DiscoverComponent
Expand Down Expand Up @@ -37,6 +38,7 @@ interface UiComponent :
SearchComponent,
SettingsComponent,
DevSettingsComponent,
DevLogComponent,
ShowDetailsComponent,
ShowSeasonsComponent,
TrendingShowsComponent,
Expand Down
31 changes: 31 additions & 0 deletions ui/developer/log/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright 2023, Google LLC, Christopher Banes and the Tivi project contributors
// SPDX-License-Identifier: Apache-2.0


plugins {
id("app.tivi.android.library")
id("app.tivi.kotlin.multiplatform")
id("app.tivi.compose")
}

android {
namespace = "app.tivi.developer.log"
}

kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation(projects.core.base)
implementation(projects.core.logging.api)
implementation(projects.common.ui.compose)

api(projects.common.ui.screens)
api(libs.circuit.foundation)

implementation(compose.material3)
implementation(compose.animation)
}
}
}
}
Loading