-
-
Notifications
You must be signed in to change notification settings - Fork 116
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Logback backend for kotlin-logging (#452)
* Logback backend for kotlin-logging * Introduce internalCompilerData field * Populate caller information from compiler data, if available * Document that "internalCompilerData" field is not meant for public consumption * Improve naming and remove misleading JavaDoc. --------- Co-authored-by: Neeme Praks <[email protected]>
- Loading branch information
1 parent
c128ae4
commit 1f9ecdd
Showing
9 changed files
with
258 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
src/jvmMain/kotlin/io/github/oshai/kotlinlogging/logback/LogbackExtensions.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package io.github.oshai.kotlinlogging.logback | ||
|
||
import ch.qos.logback.classic.Level | ||
import ch.qos.logback.classic.spi.LogbackServiceProvider | ||
import io.github.oshai.kotlinlogging.Level.DEBUG | ||
import io.github.oshai.kotlinlogging.Level.ERROR | ||
import io.github.oshai.kotlinlogging.Level.INFO | ||
import io.github.oshai.kotlinlogging.Level.OFF | ||
import io.github.oshai.kotlinlogging.Level.TRACE | ||
import io.github.oshai.kotlinlogging.Level.WARN | ||
import io.github.oshai.kotlinlogging.Marker | ||
import io.github.oshai.kotlinlogging.slf4j.internal.Slf4jMarker | ||
|
||
public fun io.github.oshai.kotlinlogging.Level.toLogbackLevel(): Level { | ||
val logbackLevel: Level = | ||
when (this) { | ||
TRACE -> Level.TRACE | ||
DEBUG -> Level.DEBUG | ||
INFO -> Level.INFO | ||
WARN -> Level.WARN | ||
ERROR -> Level.ERROR | ||
OFF -> Level.OFF | ||
} | ||
return logbackLevel | ||
} | ||
|
||
public fun Marker.toLogback(logbackServiceProvider: LogbackServiceProvider): org.slf4j.Marker = | ||
when (this) { | ||
is Slf4jMarker -> marker | ||
else -> logbackServiceProvider.markerFactory.getMarker(getName()) | ||
} |
48 changes: 48 additions & 0 deletions
48
src/jvmMain/kotlin/io/github/oshai/kotlinlogging/logback/internal/LogbackLogEvent.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package io.github.oshai.kotlinlogging.logback.internal | ||
|
||
import ch.qos.logback.classic.Logger | ||
import ch.qos.logback.classic.spi.LoggingEvent | ||
import io.github.oshai.kotlinlogging.KLoggingEventBuilder | ||
import io.github.oshai.kotlinlogging.Level | ||
import io.github.oshai.kotlinlogging.logback.toLogbackLevel | ||
|
||
public class LogbackLogEvent( | ||
fqcn: String, | ||
logger: Logger, | ||
level: Level, | ||
private val kLoggingEvent: KLoggingEventBuilder, | ||
) : | ||
LoggingEvent( | ||
fqcn, | ||
logger, | ||
level.toLogbackLevel(), | ||
kLoggingEvent.internalCompilerData?.messageTemplate ?: kLoggingEvent.message, | ||
kLoggingEvent.cause, | ||
emptyArray(), | ||
) { | ||
|
||
override fun getFormattedMessage(): String? { | ||
return kLoggingEvent.message | ||
} | ||
|
||
override fun getCallerData(): Array<StackTraceElement> = | ||
if (kLoggingEvent.internalCompilerData?.fileName != null) { | ||
arrayOf( | ||
StackTraceElement( | ||
kLoggingEvent.internalCompilerData?.className, | ||
kLoggingEvent.internalCompilerData?.methodName, | ||
kLoggingEvent.internalCompilerData?.fileName, | ||
kLoggingEvent.internalCompilerData?.lineNumber ?: 0, | ||
) | ||
) | ||
} else { | ||
super.getCallerData() | ||
} | ||
|
||
override fun hasCallerData(): Boolean = | ||
if (kLoggingEvent.internalCompilerData?.fileName != null) { | ||
true | ||
} else { | ||
super.hasCallerData() | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
src/jvmMain/kotlin/io/github/oshai/kotlinlogging/logback/internal/LogbackLoggerFactory.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package io.github.oshai.kotlinlogging.logback.internal | ||
|
||
import ch.qos.logback.classic.Logger | ||
import ch.qos.logback.classic.LoggerContext | ||
import ch.qos.logback.classic.spi.LogbackServiceProvider | ||
import io.github.oshai.kotlinlogging.KLogger | ||
|
||
internal object LogbackLoggerFactory { | ||
|
||
private val logbackServiceProvider = createLogbackServiceProvider() | ||
|
||
private fun createLogbackServiceProvider(): LogbackServiceProvider { | ||
val logbackServiceProvider = LogbackServiceProvider() | ||
logbackServiceProvider.initialize() | ||
return logbackServiceProvider | ||
} | ||
|
||
/** Get a Logback logger by name. Logback relies on SLF4J logger factory */ | ||
internal fun logbackLogger(name: String): Logger = | ||
logbackServiceProvider.loggerFactory.getLogger(name) as Logger | ||
|
||
internal fun wrapLogbackLogger(logbackLogger: Logger): KLogger = | ||
LogbackLoggerWrapper(logbackLogger, logbackServiceProvider) | ||
|
||
fun getLoggerContext() = logbackServiceProvider.loggerFactory as LoggerContext | ||
} |
44 changes: 44 additions & 0 deletions
44
src/jvmMain/kotlin/io/github/oshai/kotlinlogging/logback/internal/LogbackLoggerWrapper.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package io.github.oshai.kotlinlogging.logback.internal | ||
|
||
import ch.qos.logback.classic.Logger | ||
import ch.qos.logback.classic.spi.LogbackServiceProvider | ||
import io.github.oshai.kotlinlogging.DelegatingKLogger | ||
import io.github.oshai.kotlinlogging.KLogger | ||
import io.github.oshai.kotlinlogging.KLoggingEventBuilder | ||
import io.github.oshai.kotlinlogging.Level | ||
import io.github.oshai.kotlinlogging.Marker | ||
import io.github.oshai.kotlinlogging.logback.toLogback | ||
import io.github.oshai.kotlinlogging.logback.toLogbackLevel | ||
import io.github.oshai.kotlinlogging.slf4j.internal.LocationAwareKLogger | ||
import org.slf4j.event.KeyValuePair | ||
|
||
internal class LogbackLoggerWrapper( | ||
override val underlyingLogger: Logger, | ||
private val logbackServiceProvider: LogbackServiceProvider, | ||
) : KLogger, DelegatingKLogger<Logger> { | ||
|
||
override val name: String | ||
get() = underlyingLogger.name | ||
|
||
private val fqcn: String = LocationAwareKLogger::class.java.name | ||
|
||
override fun at(level: Level, marker: Marker?, block: KLoggingEventBuilder.() -> Unit) { | ||
if (isLoggingEnabledFor(level, marker)) { | ||
KLoggingEventBuilder().apply(block).run { | ||
val logbackEvent = | ||
LogbackLogEvent( | ||
fqcn = fqcn, | ||
logger = underlyingLogger, | ||
level = level, | ||
kLoggingEvent = this, | ||
) | ||
marker?.toLogback(logbackServiceProvider)?.let { logbackEvent.addMarker(it) } | ||
payload?.forEach { (key, value) -> logbackEvent.addKeyValuePair(KeyValuePair(key, value)) } | ||
underlyingLogger.callAppenders(logbackEvent) | ||
} | ||
} | ||
} | ||
|
||
override fun isLoggingEnabledFor(level: Level, marker: Marker?) = | ||
underlyingLogger.isEnabledFor(marker?.toLogback(logbackServiceProvider), level.toLogbackLevel()) | ||
} |
89 changes: 89 additions & 0 deletions
89
...jvmTest/kotlin/io/github/oshai/kotlinlogging/logback/internal/LogbackLoggerWrapperTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package io.github.oshai.kotlinlogging.logback.internal | ||
|
||
import ch.qos.logback.classic.Level | ||
import ch.qos.logback.classic.Logger | ||
import ch.qos.logback.classic.encoder.PatternLayoutEncoder | ||
import ch.qos.logback.classic.spi.ILoggingEvent | ||
import ch.qos.logback.core.OutputStreamAppender | ||
import io.github.oshai.kotlinlogging.KLogger | ||
import io.github.oshai.kotlinlogging.KotlinLogging | ||
import java.io.ByteArrayOutputStream | ||
import org.junit.jupiter.api.AfterAll | ||
import org.junit.jupiter.api.Assertions.* | ||
import org.junit.jupiter.api.BeforeAll | ||
import org.junit.jupiter.api.Test | ||
|
||
class LogbackLoggerWrapperTest { | ||
|
||
companion object { | ||
private lateinit var logger: KLogger | ||
private lateinit var warnLogger: KLogger | ||
private lateinit var errorLogger: KLogger | ||
private lateinit var logOutputStream: ByteArrayOutputStream | ||
private lateinit var appender: OutputStreamAppender<ILoggingEvent> | ||
private lateinit var rootLogger: Logger | ||
|
||
@BeforeAll | ||
@JvmStatic | ||
fun init() { | ||
val loggerContext = LogbackLoggerFactory.getLoggerContext() | ||
loggerContext.reset() | ||
System.setProperty("kotlin-logging-to-logback", "true") | ||
|
||
val encoder = PatternLayoutEncoder() | ||
encoder.context = loggerContext | ||
encoder.pattern = "%-5p %c %marker - %m%n" | ||
encoder.charset = Charsets.UTF_8 | ||
encoder.start() | ||
|
||
logOutputStream = ByteArrayOutputStream() | ||
appender = OutputStreamAppender<ILoggingEvent>() | ||
appender.context = loggerContext | ||
appender.encoder = encoder | ||
appender.outputStream = logOutputStream | ||
appender.start() | ||
|
||
rootLogger = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME) | ||
rootLogger.addAppender(appender) | ||
rootLogger.level = Level.TRACE | ||
|
||
logger = KotlinLogging.logger {} | ||
warnLogger = KotlinLogging.logger("warnLogger") | ||
loggerContext.getLogger("warnLogger").level = Level.WARN | ||
errorLogger = KotlinLogging.logger("errorLogger") | ||
loggerContext.getLogger("errorLogger").level = Level.ERROR | ||
} | ||
|
||
@AfterAll | ||
@JvmStatic | ||
fun teardown() { | ||
System.clearProperty("kotlin-logging-to-logback") | ||
val loggerContext = LogbackLoggerFactory.getLoggerContext() | ||
loggerContext.reset() | ||
} | ||
} | ||
|
||
@Test | ||
fun testLogbackLogger() { | ||
assertTrue(logger is LogbackLoggerWrapper) | ||
assertTrue(warnLogger is LogbackLoggerWrapper) | ||
assertTrue(errorLogger is LogbackLoggerWrapper) | ||
logger.info { "simple logback info message" } | ||
warnLogger.warn { "simple logback warn message" } | ||
errorLogger.error { "simple logback error message" } | ||
val lines = | ||
logOutputStream | ||
.toByteArray() | ||
.toString(Charsets.UTF_8) | ||
.trim() | ||
.replace("\r", "\n") | ||
.replace("\n\n", "\n") | ||
.split("\n") | ||
assertEquals( | ||
"INFO io.github.oshai.kotlinlogging.logback.internal.LogbackLoggerWrapperTest - simple logback info message", | ||
lines[0], | ||
) | ||
assertEquals("WARN warnLogger - simple logback warn message", lines[1]) | ||
assertEquals("ERROR errorLogger - simple logback error message", lines[2]) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters