From afc090bc03451b325e9b8b6a8af325282dac2eed Mon Sep 17 00:00:00 2001 From: George Smyrnaios Date: Sat, 19 Oct 2024 15:45:31 +0200 Subject: [PATCH] Refactor logging and tracing implementations Introduce a `TracingEvent` interface and `SimpleConsoleTracingAppender` for tracing support, while refactoring `LoggingEvent` into an interface and renaming ConsoleAppender to `SimpleConsoleLoggingAppender`. This update also includes making the `Appender` interface generic, restructuring `Logger` and `RootLogger` for better logging and tracing separation, and revising tests to incorporate tracing functionality. --- .../io/github/smyrgeorge/log4k/Appender.kt | 4 +- .../io/github/smyrgeorge/log4k/Logger.kt | 57 ++++++----- .../github/smyrgeorge/log4k/LoggerFactory.kt | 12 ++- .../github/smyrgeorge/log4k/LoggingEvent.kt | 20 ++-- .../io/github/smyrgeorge/log4k/RootLogger.kt | 67 +++++++++---- .../github/smyrgeorge/log4k/TracingEvent.kt | 98 +++++++++++++++++++ .../log4k/appenders/BatchAppender.kt | 5 +- .../log4k/appenders/FlowAppender.kt | 11 +-- .../smyrgeorge/log4k/impl/SimpleLogger.kt | 16 ++- .../log4k/impl/SimpleLoggerFactory.kt | 8 +- .../log4k/impl/SimpleLoggingEvent.kt | 16 +++ ...der.kt => SimpleConsoleLoggingAppender.kt} | 2 +- .../appenders/SimpleConsoleTracingAppender.kt | 14 +++ .../log4k/impl/registry/AppenderRegistry.kt | 16 +++ .../{ => impl}/registry/LoggerRegistry.kt | 2 +- .../log4k/registry/AppenderRegistry.kt | 17 ---- .../io/github/smyrgeorge/log4k/MainTests.kt | 18 +++- 17 files changed, 286 insertions(+), 97 deletions(-) create mode 100644 log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/TracingEvent.kt create mode 100644 log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/SimpleLoggingEvent.kt rename log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/appenders/{ConsoleAppender.kt => SimpleConsoleLoggingAppender.kt} (94%) create mode 100644 log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/appenders/SimpleConsoleTracingAppender.kt create mode 100644 log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/registry/AppenderRegistry.kt rename log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/{ => impl}/registry/LoggerRegistry.kt (96%) delete mode 100644 log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/registry/AppenderRegistry.kt diff --git a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/Appender.kt b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/Appender.kt index 110f3e89..c0e67a21 100644 --- a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/Appender.kt +++ b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/Appender.kt @@ -1,6 +1,6 @@ package io.github.smyrgeorge.log4k -interface Appender { +interface Appender { val name: String - fun append(event: LoggingEvent) + fun append(event: T) } \ No newline at end of file diff --git a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/Logger.kt b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/Logger.kt index edbac62a..518e89ed 100644 --- a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/Logger.kt +++ b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/Logger.kt @@ -1,38 +1,25 @@ package io.github.smyrgeorge.log4k -import kotlinx.datetime.Clock import kotlin.reflect.KClass -@Suppress("unused", "MemberVisibilityCanBePrivate", "ConvertSecondaryConstructorToPrimary") -abstract class Logger { - val name: String +@Suppress("unused", "MemberVisibilityCanBePrivate") +abstract class Logger( + val name: String, private var level: Level - private var levelBeforeMute: Level - - constructor(name: String, level: Level) { - this.name = name - this.level = level - this.levelBeforeMute = level - } +) { + private var levelBeforeMute: Level = level private fun log(level: Level, msg: String, args: Array) = log(level, msg, null, args) private fun log(level: Level, msg: String, throwable: Throwable?, args: Array) { if (!level.shouldLog()) return - val event = LoggingEvent( - level = level, - message = msg, - logger = name, - arguments = args, - timestamp = Clock.System.now(), - thread = null, - throwable = throwable - ) - + val event = toLoggingEvent(level, msg, throwable, args) RootLogger.log(event) } + abstract fun toLoggingEvent(level: Level, msg: String, throwable: Throwable?, args: Array): LoggingEvent + private fun Level.shouldLog(): Boolean = ordinal >= level.ordinal @@ -50,6 +37,30 @@ abstract class Logger { levelBeforeMute = level } + fun span(name: String, parent: String? = null): TracingEvent.Span = + TracingEvent.Span(RootLogger.Tracing.id(), name, level, parent, this) + + inline fun span(name: String, parent: String? = null, f: (TracingEvent.Span) -> T): T { + val span = span(name, parent) + return try { + f(span) + } finally { + span.end() + } + } + + fun span(id: String, name: String, parent: String? = null): TracingEvent.Span = + TracingEvent.Span(id, name, level, parent, this) + + inline fun span(id: String, name: String, parent: String? = null, f: (TracingEvent.Span) -> T): T { + val span = span(id, name, parent) + return try { + f(span) + } finally { + span.end() + } + } + fun trace(f: () -> String): Unit = if (Level.TRACE.shouldLog()) trace(f()) else Unit fun trace(msg: String, vararg args: Any?): Unit = log(Level.TRACE, msg, args) fun debug(f: () -> String): Unit = if (Level.DEBUG.shouldLog()) debug(f()) else Unit @@ -64,7 +75,7 @@ abstract class Logger { fun error(msg: String?, t: Throwable, vararg args: Any?): Unit = log(Level.ERROR, msg ?: "", t, args) companion object { - fun of(name: String): Logger = RootLogger.factory.getLogger(name) - fun of(clazz: KClass<*>): Logger = RootLogger.factory.getLogger(clazz) + fun of(name: String): Logger = RootLogger.Logging.factory.get(name) + fun of(clazz: KClass<*>): Logger = RootLogger.Logging.factory.get(clazz) } } \ No newline at end of file diff --git a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/LoggerFactory.kt b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/LoggerFactory.kt index 9bf3ac9d..67c4e6a2 100644 --- a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/LoggerFactory.kt +++ b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/LoggerFactory.kt @@ -3,8 +3,14 @@ package io.github.smyrgeorge.log4k import io.github.smyrgeorge.log4k.impl.extensions.toName import kotlin.reflect.KClass -@Suppress("unused") interface LoggerFactory { - fun getLogger(clazz: KClass<*>): Logger = getLogger(clazz.toName()) - fun getLogger(name: String): Logger + fun create(name: String): Logger + fun get(clazz: KClass<*>): Logger = get(clazz.toName()) + fun get(name: String): Logger { + val existing = RootLogger.Logging.loggers.get(name) + if (existing != null) return existing + return create(name).also { + RootLogger.Logging.loggers.register(it) + } + } } \ No newline at end of file diff --git a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/LoggingEvent.kt b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/LoggingEvent.kt index f184be07..23b890f7 100644 --- a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/LoggingEvent.kt +++ b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/LoggingEvent.kt @@ -2,13 +2,13 @@ package io.github.smyrgeorge.log4k import kotlinx.datetime.Instant -class LoggingEvent( - var id: Long = 0, - val level: Level, - val logger: String, - val message: String, - val arguments: Array, - val timestamp: Instant, - val thread: String? = null, - val throwable: Throwable? = null, -) \ No newline at end of file +interface LoggingEvent { + var id: Long + val level: Level + val timestamp: Instant + val logger: String + val message: String + val arguments: Array + val thread: String? + val throwable: Throwable? +} \ No newline at end of file diff --git a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/RootLogger.kt b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/RootLogger.kt index f2881562..adb2c338 100644 --- a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/RootLogger.kt +++ b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/RootLogger.kt @@ -1,10 +1,10 @@ package io.github.smyrgeorge.log4k import io.github.smyrgeorge.log4k.impl.SimpleLoggerFactory -import io.github.smyrgeorge.log4k.impl.appenders.ConsoleAppender +import io.github.smyrgeorge.log4k.impl.appenders.SimpleConsoleLoggingAppender import io.github.smyrgeorge.log4k.impl.extensions.forEachParallel -import io.github.smyrgeorge.log4k.registry.AppenderRegistry -import io.github.smyrgeorge.log4k.registry.LoggerRegistry +import io.github.smyrgeorge.log4k.impl.registry.AppenderRegistry +import io.github.smyrgeorge.log4k.impl.registry.LoggerRegistry import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.IO @@ -12,39 +12,70 @@ import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.consumeEach import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock +import kotlinx.datetime.Clock import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext @Suppress("MemberVisibilityCanBePrivate") object RootLogger { - private val events: Channel = + val level: Level = Level.INFO + + private val logs: Channel = Channel(capacity = Channel.UNLIMITED) - val level: Level = Level.INFO - val factory = SimpleLoggerFactory() - val loggers = LoggerRegistry() - val appenders = AppenderRegistry() + private val traces: Channel = + Channel(capacity = Channel.UNLIMITED) + + object Logging { + private var idx: Long = 0 + fun id(): Long = ++idx + val factory = SimpleLoggerFactory() + val loggers = LoggerRegistry() + val appenders = AppenderRegistry() + fun register(appender: Appender) = appenders.register(appender) + } + + object Tracing { + private var idx: Long = 0 + var prefix: String = "span" + fun id(): String = runBlocking { "$prefix-${Clock.System.now().epochSeconds}-${idx()}" } + private val mutex = Mutex() + private suspend fun idx(): Long = mutex.withLock { ++idx } + val appenders = AppenderRegistry() + fun register(appender: Appender) = appenders.register(appender) + } init { - register(ConsoleAppender()) + Logging.register(SimpleConsoleLoggingAppender()) - // Start consuming the logging queue. + // Start consuming the Logging queue. LoggerScope.launch(Dispatchers.IO) { - events.consumeEach { event -> - event.id = nextIdx() - appenders.all().forEachParallel { it.append(event) } + logs.consumeEach { event -> + event.id = Logging.id() + Logging.appenders.all().forEachParallel { it.append(event) } } } - } - fun log(event: LoggingEvent) = runBlocking { events.send(event) } - fun register(appender: Appender) = appenders.register(appender) + // Start consuming the Tracing queue. + TracerScope.launch(Dispatchers.IO) { + traces.consumeEach { event -> + Tracing.appenders.all().forEachParallel { it.append(event) } + } + } + } - private var idx: Long = 0 - private fun nextIdx(): Long = ++idx + fun log(event: LoggingEvent) = runBlocking { logs.send(event) } + fun trace(event: TracingEvent) = runBlocking { traces.send(event) } private object LoggerScope : CoroutineScope { override val coroutineContext: CoroutineContext get() = EmptyCoroutineContext } + + private object TracerScope : CoroutineScope { + override val coroutineContext: CoroutineContext + get() = EmptyCoroutineContext + } } \ No newline at end of file diff --git a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/TracingEvent.kt b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/TracingEvent.kt new file mode 100644 index 00000000..8d77e824 --- /dev/null +++ b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/TracingEvent.kt @@ -0,0 +1,98 @@ +package io.github.smyrgeorge.log4k + +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock +import kotlinx.datetime.Clock +import kotlinx.datetime.Instant + +interface TracingEvent { + val id: String + val level: Level + val timestamp: Instant + val tracer: String + val thread: String? + + class Span( + val id: String, + val name: String, + val level: Level, + parent: String? = null, + val logger: Logger, + ) { + private val mutex = Mutex() + private var idx: Int = 0 + private var closed: Boolean = false + private fun idx(): Int = ++idx + + init { + val event = Start( + id = id, + name = name, + level = level, + tracer = logger.name, + parent = parent, + ) + RootLogger.trace(event) + } + + fun event(msg: String, vararg args: Any?): Unit = withLock { + // If already ended, return. + if (closed) return@withLock + val event = Event( + id = "$id-${idx()}", + spanId = id, + level = level, + tracer = logger.name, + message = msg, + arguments = args, + timestamp = Clock.System.now() + ) + RootLogger.trace(event) + } + + fun end(): Unit = withLock { + // If already ended, return. + if (closed) return@withLock + closed = true + + val event = End( + id = id, + level = level, + tracer = logger.name, + ) + RootLogger.trace(event) + } + + private fun withLock(f: () -> Unit) = runBlocking { mutex.withLock { f() } } + + class Event( + override val id: String, + val spanId: String, + override val level: Level, + override val tracer: String, + val message: String, + val arguments: Array, + override val timestamp: Instant = Clock.System.now(), + override val thread: String? = null + ) : TracingEvent + + class Start( + override var id: String, + val name: String, + override val level: Level, + override val tracer: String, + val parent: String?, + override val timestamp: Instant = Clock.System.now(), + override val thread: String? = null, + ) : TracingEvent + + class End( + override var id: String, + override val level: Level, + override val tracer: String, + override val timestamp: Instant = Clock.System.now(), + override val thread: String? = null, + ) : TracingEvent + } +} \ No newline at end of file diff --git a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/appenders/BatchAppender.kt b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/appenders/BatchAppender.kt index c33cd792..1eb38eb4 100644 --- a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/appenders/BatchAppender.kt +++ b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/appenders/BatchAppender.kt @@ -1,13 +1,12 @@ package io.github.smyrgeorge.log4k.appenders -import io.github.smyrgeorge.log4k.LoggingEvent import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.chunked @Suppress("unused") -abstract class BatchAppender(private val size: Int) : FlowAppender>() { +abstract class BatchAppender(private val size: Int) : FlowAppender, T>() { @OptIn(ExperimentalCoroutinesApi::class) - override fun setup(flow: Flow): Flow> = + override fun setup(flow: Flow): Flow> = flow.chunked(size) } \ No newline at end of file diff --git a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/appenders/FlowAppender.kt b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/appenders/FlowAppender.kt index 7f2ddc46..e8c346a6 100644 --- a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/appenders/FlowAppender.kt +++ b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/appenders/FlowAppender.kt @@ -2,7 +2,6 @@ package io.github.smyrgeorge.log4k.appenders import io.github.smyrgeorge.log4k.Appender import io.github.smyrgeorge.log4k.Logger -import io.github.smyrgeorge.log4k.LoggingEvent import io.github.smyrgeorge.log4k.impl.extensions.toName import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -19,9 +18,9 @@ import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext @Suppress("unused") -abstract class FlowAppender : Appender { +abstract class FlowAppender : Appender { private val log = Logger.of(this::class) - private val logs: Channel = Channel(capacity = Channel.UNLIMITED) + private val logs: Channel = Channel(capacity = Channel.UNLIMITED) @Suppress("UNCHECKED_CAST") private var flow: Flow = logs.receiveAsFlow().flowOn(Dispatchers.IO) as Flow @@ -29,17 +28,17 @@ abstract class FlowAppender : Appender { init { FlowAppenderScope().launch(Dispatchers.IO) { @Suppress("UNCHECKED_CAST") - flow = setup(this@FlowAppender.flow as Flow) + flow = setup(this@FlowAppender.flow as Flow) flow.onEach { event -> runCatching { append(event) } }.launchIn(this) } } final override val name: String = this::class.toName() - final override fun append(event: LoggingEvent) { + final override fun append(event: E) { runBlocking { logs.send(event) } } - abstract fun setup(flow: Flow): Flow + abstract fun setup(flow: Flow): Flow abstract suspend fun append(event: T) private class FlowAppenderScope : CoroutineScope { diff --git a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/SimpleLogger.kt b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/SimpleLogger.kt index 9c10c96b..000b5947 100644 --- a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/SimpleLogger.kt +++ b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/SimpleLogger.kt @@ -2,5 +2,19 @@ package io.github.smyrgeorge.log4k.impl import io.github.smyrgeorge.log4k.Level import io.github.smyrgeorge.log4k.Logger +import io.github.smyrgeorge.log4k.LoggingEvent +import kotlinx.datetime.Clock -class SimpleLogger(name: String, level: Level) : Logger(name, level) \ No newline at end of file +class SimpleLogger(name: String, level: Level) : Logger(name, level) { + override fun toLoggingEvent(level: Level, msg: String, throwable: Throwable?, args: Array): LoggingEvent { + return SimpleLoggingEvent( + level = level, + timestamp = Clock.System.now(), + logger = name, + message = msg, + arguments = args, + thread = null, + throwable = throwable + ) + } +} \ No newline at end of file diff --git a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/SimpleLoggerFactory.kt b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/SimpleLoggerFactory.kt index c10ea193..8271f0d3 100644 --- a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/SimpleLoggerFactory.kt +++ b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/SimpleLoggerFactory.kt @@ -5,11 +5,5 @@ import io.github.smyrgeorge.log4k.LoggerFactory import io.github.smyrgeorge.log4k.RootLogger class SimpleLoggerFactory : LoggerFactory { - override fun getLogger(name: String): Logger { - val existing = RootLogger.loggers.get(name) - if (existing != null) return existing - return SimpleLogger(name, RootLogger.level).also { - RootLogger.loggers.register(it) - } - } + override fun create(name: String): Logger = SimpleLogger(name, RootLogger.level) } \ No newline at end of file diff --git a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/SimpleLoggingEvent.kt b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/SimpleLoggingEvent.kt new file mode 100644 index 00000000..d8af5690 --- /dev/null +++ b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/SimpleLoggingEvent.kt @@ -0,0 +1,16 @@ +package io.github.smyrgeorge.log4k.impl + +import io.github.smyrgeorge.log4k.Level +import io.github.smyrgeorge.log4k.LoggingEvent +import kotlinx.datetime.Instant + +class SimpleLoggingEvent( + override var id: Long = 0, + override val level: Level, + override val timestamp: Instant, + override val logger: String, + override val message: String, + override val arguments: Array, + override val thread: String? = null, + override val throwable: Throwable? = null, +) : LoggingEvent \ No newline at end of file diff --git a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/appenders/ConsoleAppender.kt b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/appenders/SimpleConsoleLoggingAppender.kt similarity index 94% rename from log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/appenders/ConsoleAppender.kt rename to log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/appenders/SimpleConsoleLoggingAppender.kt index 0402a9ba..548d3a29 100644 --- a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/appenders/ConsoleAppender.kt +++ b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/appenders/SimpleConsoleLoggingAppender.kt @@ -5,7 +5,7 @@ import io.github.smyrgeorge.log4k.LoggingEvent import io.github.smyrgeorge.log4k.impl.extensions.format import io.github.smyrgeorge.log4k.impl.extensions.toName -class ConsoleAppender : Appender { +class SimpleConsoleLoggingAppender : Appender { override val name: String = this::class.toName() override fun append(event: LoggingEvent) { print(event.format()) diff --git a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/appenders/SimpleConsoleTracingAppender.kt b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/appenders/SimpleConsoleTracingAppender.kt new file mode 100644 index 00000000..23062533 --- /dev/null +++ b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/appenders/SimpleConsoleTracingAppender.kt @@ -0,0 +1,14 @@ +package io.github.smyrgeorge.log4k.impl.appenders + +import io.github.smyrgeorge.log4k.Appender +import io.github.smyrgeorge.log4k.LoggingEvent +import io.github.smyrgeorge.log4k.TracingEvent +import io.github.smyrgeorge.log4k.impl.extensions.format +import io.github.smyrgeorge.log4k.impl.extensions.toName + +class SimpleConsoleTracingAppender : Appender { + override val name: String = this::class.toName() + override fun append(event: TracingEvent) { + println("[${event.id}]:: ${event.timestamp}") + } +} \ No newline at end of file diff --git a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/registry/AppenderRegistry.kt b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/registry/AppenderRegistry.kt new file mode 100644 index 00000000..3ab968e5 --- /dev/null +++ b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/registry/AppenderRegistry.kt @@ -0,0 +1,16 @@ +package io.github.smyrgeorge.log4k.impl.registry + +import io.github.smyrgeorge.log4k.Appender +import io.github.smyrgeorge.log4k.impl.extensions.witLock +import kotlinx.coroutines.sync.Mutex + +@Suppress("unused") +class AppenderRegistry { + private val mutex = Mutex() + private val appenders = mutableListOf>() + fun all(): List> = mutex.witLock { appenders.toList() } + fun get(name: String): Appender? = mutex.witLock { appenders.find { it.name == name } } + fun register(appender: Appender) = mutex.witLock { appenders.add(appender) } + fun unregister(name: String) = mutex.witLock { appenders.removeAll { it.name == name } } + fun unregisterAll() = mutex.witLock { appenders.clear() } +} \ No newline at end of file diff --git a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/registry/LoggerRegistry.kt b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/registry/LoggerRegistry.kt similarity index 96% rename from log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/registry/LoggerRegistry.kt rename to log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/registry/LoggerRegistry.kt index 0dbbcfab..d626fcf7 100644 --- a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/registry/LoggerRegistry.kt +++ b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/impl/registry/LoggerRegistry.kt @@ -1,4 +1,4 @@ -package io.github.smyrgeorge.log4k.registry +package io.github.smyrgeorge.log4k.impl.registry import io.github.smyrgeorge.log4k.Level import io.github.smyrgeorge.log4k.Logger diff --git a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/registry/AppenderRegistry.kt b/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/registry/AppenderRegistry.kt deleted file mode 100644 index 24560d41..00000000 --- a/log4k/src/commonMain/kotlin/io/github/smyrgeorge/log4k/registry/AppenderRegistry.kt +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.smyrgeorge.log4k.registry - -import io.github.smyrgeorge.log4k.Appender -import io.github.smyrgeorge.log4k.impl.extensions.witLock -import kotlinx.coroutines.sync.Mutex - -@Suppress("unused") -class AppenderRegistry { - private val mutex = Mutex() - - private val appenders = mutableListOf() - fun all(): List = mutex.witLock { appenders.toList() } - fun get(name: String): Appender? = mutex.witLock { appenders.find { it.name == name } } - fun register(appender: Appender) = mutex.witLock { appenders.add(appender) } - fun unregister(name: String) = mutex.witLock { appenders.removeAll { it.name == name } } - fun unregisterAll() = mutex.witLock { appenders.clear() } -} \ No newline at end of file diff --git a/log4k/src/commonTest/kotlin/io/github/smyrgeorge/log4k/MainTests.kt b/log4k/src/commonTest/kotlin/io/github/smyrgeorge/log4k/MainTests.kt index 9aeae84d..1e49cb7c 100644 --- a/log4k/src/commonTest/kotlin/io/github/smyrgeorge/log4k/MainTests.kt +++ b/log4k/src/commonTest/kotlin/io/github/smyrgeorge/log4k/MainTests.kt @@ -1,13 +1,14 @@ package io.github.smyrgeorge.log4k import io.github.smyrgeorge.log4k.appenders.BatchAppender +import io.github.smyrgeorge.log4k.impl.appenders.SimpleConsoleTracingAppender import kotlinx.coroutines.delay import kotlinx.coroutines.runBlocking import kotlin.test.Test class MainTests { - class MyBatchAppender(size: Int) : BatchAppender(size) { + class MyBatchAppender(size: Int) : BatchAppender(size) { override suspend fun append(event: List) { // E.g. send batch over http. println(event.joinToString { it.message }) @@ -21,9 +22,9 @@ class MainTests { log.debug("ignore") log.debug { "ignore + ${5}" } // Will be evaluated only if DEBUG logs are enabled. log.info("this is a test") - RootLogger.loggers.mute("io.github.smyrgeorge.log4k.MainTests") + RootLogger.Logging.loggers.mute("io.github.smyrgeorge.log4k.MainTests") log.info("this is a test with 1 arg: {}", "hello") - RootLogger.loggers.unmute(this::class) + log.unmute() log.info("this is a test with 1 arg: {}", "hello") try { @@ -36,15 +37,22 @@ class MainTests { } runBlocking { - delay(2000) val appender = MyBatchAppender(5) - RootLogger.appenders.register(appender) + RootLogger.Logging.appenders.register(appender) repeat(10) { log.info("$it") delay(500) } + delay(1000) + + RootLogger.Tracing.register(SimpleConsoleTracingAppender()) + log.span("test") { + it.event("this is a test event") + it.event("this is a test event") + } + delay(2000) } }