musikr: start logging framework

This commit is contained in:
Alexander Capehart 2025-01-21 18:15:39 -07:00
parent b2073f2213
commit 0f034255af
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
7 changed files with 123 additions and 15 deletions

View file

@ -40,6 +40,7 @@ import org.oxycblt.musikr.Playlist
import org.oxycblt.musikr.Song import org.oxycblt.musikr.Song
import org.oxycblt.musikr.Storage import org.oxycblt.musikr.Storage
import org.oxycblt.musikr.cache.MutableSongCache import org.oxycblt.musikr.cache.MutableSongCache
import org.oxycblt.musikr.log.Logger
import org.oxycblt.musikr.playlist.db.StoredPlaylists import org.oxycblt.musikr.playlist.db.StoredPlaylists
import org.oxycblt.musikr.tag.interpret.Naming import org.oxycblt.musikr.tag.interpret.Naming
import org.oxycblt.musikr.tag.interpret.Separators import org.oxycblt.musikr.tag.interpret.Separators
@ -394,7 +395,8 @@ constructor(
val interpretation = Interpretation(nameFactory, separators) val interpretation = Interpretation(nameFactory, separators)
val result = val result =
Musikr.new(context, storage, interpretation).run(locations, ::emitIndexingProgress) Musikr.new(context, storage, interpretation, Logger.root())
.run(locations, ::emitIndexingProgress)
// Music loading completed, update the revision right now so we re-use this work // Music loading completed, update the revision right now so we re-use this work
// later. // later.
musicSettings.revision = newRevision musicSettings.revision = newRevision

View file

@ -19,6 +19,7 @@
package org.oxycblt.musikr package org.oxycblt.musikr
import android.content.Context import android.content.Context
import android.os.Build
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.buffer import kotlinx.coroutines.flow.buffer
@ -28,6 +29,7 @@ import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.onStart
import org.oxycblt.musikr.fs.MusicLocation import org.oxycblt.musikr.fs.MusicLocation
import org.oxycblt.musikr.log.Logger
import org.oxycblt.musikr.pipeline.Divert import org.oxycblt.musikr.pipeline.Divert
import org.oxycblt.musikr.pipeline.EvaluateStep import org.oxycblt.musikr.pipeline.EvaluateStep
import org.oxycblt.musikr.pipeline.ExploreStep import org.oxycblt.musikr.pipeline.ExploreStep
@ -68,18 +70,25 @@ interface Musikr {
* Create a new instance from the given configuration. * Create a new instance from the given configuration.
* *
* @param context The context to use for loading resources. * @param context The context to use for loading resources.
* @param logger The logger to use for logging events.
* @param storage Side-effect laden storage for use within the music loader **and** when * @param storage Side-effect laden storage for use within the music loader **and** when
* mutating [MutableLibrary]. You should take responsibility for managing their long-term * mutating [MutableLibrary]. You should take responsibility for managing their long-term
* state. * state.
* @param interpretation The configuration to use for interpreting certain vague tags. This * @param interpretation The configuration to use for interpreting certain vague tags. This
* should be configured by the user, if possible. * should be configured by the user, if possible.
*/ */
fun new(context: Context, storage: Storage, interpretation: Interpretation): Musikr = fun new(
context: Context,
storage: Storage,
interpretation: Interpretation,
logger: Logger
): Musikr =
MusikrImpl( MusikrImpl(
logger,
storage, storage,
ExploreStep.from(context, storage), ExploreStep.from(context, storage, logger),
ExtractStep.from(context, storage), ExtractStep.from(context, storage, logger),
EvaluateStep.new(storage, interpretation)) EvaluateStep.new(storage, interpretation, logger))
} }
} }
@ -116,6 +125,7 @@ sealed interface IndexingProgress {
} }
private class MusikrImpl( private class MusikrImpl(
private val logger: Logger,
private val storage: Storage, private val storage: Storage,
private val exploreStep: ExploreStep, private val exploreStep: ExploreStep,
private val extractStep: ExtractStep, private val extractStep: ExtractStep,
@ -125,6 +135,16 @@ private class MusikrImpl(
locations: List<MusicLocation>, locations: List<MusicLocation>,
onProgress: suspend (IndexingProgress) -> Unit onProgress: suspend (IndexingProgress) -> Unit
) = coroutineScope { ) = coroutineScope {
logger.d(
"musikr start.",
"hw:",
Build.MANUFACTURER,
Build.MODEL,
Build.SUPPORTED_ABIS.joinToString(" "),
"sw:",
Build.VERSION.SDK_INT,
Build.DISPLAY)
var exploredCount = 0 var exploredCount = 0
var extractedCount = 0 var extractedCount = 0
val explored = val explored =

View file

@ -0,0 +1,63 @@
/*
* Copyright (c) 2025 Auxio Project
* Logger.kt is part of Auxio.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.oxycblt.musikr.log
import android.util.Log
interface Logger {
fun v(vararg msgs: Any)
fun d(vararg msgs: Any)
fun w(vararg msgs: Any)
fun e(vararg msgs: Any)
fun primary(tag: String): Logger
fun secondary(tag: String): Logger
companion object {
fun root(): Logger = LoggerImpl("mskr", null)
}
}
private class LoggerImpl(private val primaryTag: String, private val secondaryTag: String?) :
Logger {
override fun v(vararg msgs: Any) {
Log.v(primaryTag, "[$secondaryTag] ${msgs.joinToString(" ")}")
}
override fun d(vararg msgs: Any) {
Log.d(primaryTag, "[$secondaryTag] ${msgs.joinToString(" ")}")
}
override fun w(vararg msgs: Any) {
Log.w(primaryTag, "[$secondaryTag] ${msgs.joinToString(" ")}")
}
override fun e(vararg msgs: Any) {
Log.e(primaryTag, "[$secondaryTag] ${msgs.joinToString(" ")}")
}
override fun primary(tag: String) = LoggerImpl("${primaryTag}.${tag}", secondaryTag)
override fun secondary(tag: String) =
LoggerImpl(primaryTag, secondaryTag?.let { "$it.$tag" } ?: tag)
}

View file

@ -30,6 +30,7 @@ import org.oxycblt.musikr.Interpretation
import org.oxycblt.musikr.MutableLibrary import org.oxycblt.musikr.MutableLibrary
import org.oxycblt.musikr.Storage import org.oxycblt.musikr.Storage
import org.oxycblt.musikr.graph.MusicGraph import org.oxycblt.musikr.graph.MusicGraph
import org.oxycblt.musikr.log.Logger
import org.oxycblt.musikr.model.LibraryFactory import org.oxycblt.musikr.model.LibraryFactory
import org.oxycblt.musikr.playlist.db.StoredPlaylists import org.oxycblt.musikr.playlist.db.StoredPlaylists
import org.oxycblt.musikr.playlist.interpret.PlaylistInterpreter import org.oxycblt.musikr.playlist.interpret.PlaylistInterpreter
@ -39,12 +40,13 @@ internal interface EvaluateStep {
suspend fun evaluate(complete: Flow<Complete>): MutableLibrary suspend fun evaluate(complete: Flow<Complete>): MutableLibrary
companion object { companion object {
fun new(storage: Storage, interpretation: Interpretation): EvaluateStep = fun new(storage: Storage, interpretation: Interpretation, logger: Logger): EvaluateStep =
EvaluateStepImpl( EvaluateStepImpl(
Interpreter.new(interpretation), Interpreter.new(interpretation),
PlaylistInterpreter.new(interpretation), PlaylistInterpreter.new(interpretation),
storage.storedPlaylists, storage.storedPlaylists,
LibraryFactory.new()) LibraryFactory.new(),
logger.primary("eval"))
} }
} }
@ -52,9 +54,11 @@ private class EvaluateStepImpl(
private val interpreter: Interpreter, private val interpreter: Interpreter,
private val playlistInterpreter: PlaylistInterpreter, private val playlistInterpreter: PlaylistInterpreter,
private val storedPlaylists: StoredPlaylists, private val storedPlaylists: StoredPlaylists,
private val libraryFactory: LibraryFactory private val libraryFactory: LibraryFactory,
private val logger: Logger
) : EvaluateStep { ) : EvaluateStep {
override suspend fun evaluate(complete: Flow<Complete>): MutableLibrary { override suspend fun evaluate(complete: Flow<Complete>): MutableLibrary {
logger.d("evaluate start.")
val filterFlow = val filterFlow =
complete.divert { complete.divert {
when (it) { when (it) {
@ -80,7 +84,9 @@ private class EvaluateStepImpl(
preSongs.onEach { graphBuilder.add(it) }, preSongs.onEach { graphBuilder.add(it) },
prePlaylists.onEach { graphBuilder.add(it) }) prePlaylists.onEach { graphBuilder.add(it) })
graphBuild.collect() graphBuild.collect()
logger.d("starting graph build")
val graph = graphBuilder.build() val graph = graphBuilder.build()
logger.d("graph build done, creating library")
return libraryFactory.create(graph, storedPlaylists, playlistInterpreter) return libraryFactory.create(graph, storedPlaylists, playlistInterpreter)
} }
} }

View file

@ -36,6 +36,7 @@ import org.oxycblt.musikr.cover.Covers
import org.oxycblt.musikr.cover.ObtainResult import org.oxycblt.musikr.cover.ObtainResult
import org.oxycblt.musikr.fs.MusicLocation import org.oxycblt.musikr.fs.MusicLocation
import org.oxycblt.musikr.fs.device.DeviceFS import org.oxycblt.musikr.fs.device.DeviceFS
import org.oxycblt.musikr.log.Logger
import org.oxycblt.musikr.playlist.db.StoredPlaylists import org.oxycblt.musikr.playlist.db.StoredPlaylists
import org.oxycblt.musikr.playlist.m3u.M3U import org.oxycblt.musikr.playlist.m3u.M3U
@ -43,9 +44,14 @@ internal interface ExploreStep {
fun explore(locations: List<MusicLocation>): Flow<Explored> fun explore(locations: List<MusicLocation>): Flow<Explored>
companion object { companion object {
fun from(context: Context, storage: Storage): ExploreStep = fun from(context: Context, storage: Storage, logger: Logger): ExploreStep =
ExploreStepImpl( ExploreStepImpl(
DeviceFS.from(context), storage.storedPlaylists, storage.cache, storage.covers) DeviceFS.from(context),
storage.storedPlaylists,
storage.cache,
storage.covers,
logger.primary("expl"),
)
} }
} }
@ -53,9 +59,11 @@ private class ExploreStepImpl(
private val deviceFS: DeviceFS, private val deviceFS: DeviceFS,
private val storedPlaylists: StoredPlaylists, private val storedPlaylists: StoredPlaylists,
private val songCache: SongCache, private val songCache: SongCache,
private val covers: Covers private val covers: Covers,
private val logger: Logger,
) : ExploreStep { ) : ExploreStep {
override fun explore(locations: List<MusicLocation>): Flow<Explored> { override fun explore(locations: List<MusicLocation>): Flow<Explored> {
logger.d("explore start.")
val audioFiles = val audioFiles =
deviceFS deviceFS
.explore(locations.asFlow()) .explore(locations.asFlow())

View file

@ -31,6 +31,7 @@ import org.oxycblt.musikr.Storage
import org.oxycblt.musikr.cache.CachedSong import org.oxycblt.musikr.cache.CachedSong
import org.oxycblt.musikr.cache.MutableSongCache import org.oxycblt.musikr.cache.MutableSongCache
import org.oxycblt.musikr.cover.MutableCovers import org.oxycblt.musikr.cover.MutableCovers
import org.oxycblt.musikr.log.Logger
import org.oxycblt.musikr.metadata.Metadata import org.oxycblt.musikr.metadata.Metadata
import org.oxycblt.musikr.metadata.MetadataExtractor import org.oxycblt.musikr.metadata.MetadataExtractor
import org.oxycblt.musikr.metadata.MetadataHandle import org.oxycblt.musikr.metadata.MetadataHandle
@ -40,9 +41,14 @@ internal interface ExtractStep {
fun extract(nodes: Flow<Explored.New>): Flow<Extracted> fun extract(nodes: Flow<Explored.New>): Flow<Extracted>
companion object { companion object {
fun from(context: Context, storage: Storage): ExtractStep = fun from(context: Context, storage: Storage, logger: Logger): ExtractStep =
ExtractStepImpl( ExtractStepImpl(
MetadataExtractor.new(context), TagParser.new(), storage.cache, storage.covers) MetadataExtractor.new(context),
TagParser.new(),
storage.cache,
storage.covers,
logger.primary("exct"),
)
} }
} }
@ -50,9 +56,12 @@ private class ExtractStepImpl(
private val metadataExtractor: MetadataExtractor, private val metadataExtractor: MetadataExtractor,
private val tagParser: TagParser, private val tagParser: TagParser,
private val cache: MutableSongCache, private val cache: MutableSongCache,
private val storedCovers: MutableCovers private val storedCovers: MutableCovers,
private val logger: Logger
) : ExtractStep { ) : ExtractStep {
override fun extract(nodes: Flow<Explored.New>): Flow<Extracted> { override fun extract(nodes: Flow<Explored.New>): Flow<Extracted> {
logger.d("extract start.")
val newSongs = nodes.filterIsInstance<NewSong>() val newSongs = nodes.filterIsInstance<NewSong>()
val handles = val handles =

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2024 Auxio Project * Copyright (c) 2024 Auxio Project
* TagInterpreter.kt is part of Auxio. * Interpreter.kt is part of Auxio.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by