Skip to content

Commit

Permalink
Allow supplying org.slf4j.Marker directly
Browse files Browse the repository at this point in the history
this fixes oshai#360
  • Loading branch information
mlewe committed Apr 1, 2024
1 parent 41dcc10 commit 9173fc0
Show file tree
Hide file tree
Showing 3 changed files with 238 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package io.github.oshai.kotlinlogging.slf4j

import io.github.oshai.kotlinlogging.KLogger
import io.github.oshai.kotlinlogging.KotlinLogging
import io.github.oshai.kotlinlogging.Level
import io.github.oshai.kotlinlogging.Marker
import io.github.oshai.kotlinlogging.*
import io.github.oshai.kotlinlogging.internal.toStringSafe
import io.github.oshai.kotlinlogging.slf4j.internal.Slf4jLoggerFactory
import io.github.oshai.kotlinlogging.slf4j.internal.Slf4jMarker
import org.slf4j.Logger
import org.slf4j.MarkerFactory

public fun Marker.toSlf4j(): org.slf4j.Marker = MarkerFactory.getMarker(this.getName())
public fun Marker.toSlf4j(): org.slf4j.Marker =
when (this) {
is Slf4jMarker -> marker
else -> MarkerFactory.getMarker(getName())
}

public fun org.slf4j.Marker.toKotlinLogging(): Marker = Slf4jMarker(this)

public fun Level.toSlf4j(): org.slf4j.event.Level =
when (this) {
Expand All @@ -25,3 +30,150 @@ public fun KotlinLogging.logger(underlyingLogger: Logger): KLogger =
Slf4jLoggerFactory.wrapJLogger(underlyingLogger)

public fun Logger.toKLogger(): KLogger = KotlinLogging.logger(this)

/** Lazy add a log message if isTraceEnabled is true */
public fun KLogger.trace(
throwable: Throwable? = null,
marker: org.slf4j.Marker?,
message: () -> Any?
): Unit =
at(Level.TRACE, marker) {
this.message = message.toStringSafe()
this.cause = throwable
}

/** Lazy add a log message if isDebugEnabled is true */
public fun KLogger.debug(
throwable: Throwable? = null,
marker: org.slf4j.Marker?,
message: () -> Any?
): Unit =
at(Level.DEBUG, marker) {
this.message = message.toStringSafe()
this.cause = throwable
}

/** Lazy add a log message if isInfoEnabled is true */
public fun KLogger.info(
throwable: Throwable? = null,
marker: org.slf4j.Marker?,
message: () -> Any?
): Unit =
at(Level.INFO, marker) {
this.message = message.toStringSafe()
this.cause = throwable
}

/** Lazy add a log message if isWarnEnabled is true */
public fun KLogger.warn(
throwable: Throwable? = null,
marker: org.slf4j.Marker?,
message: () -> Any?
): Unit =
at(Level.WARN, marker) {
this.message = message.toStringSafe()
this.cause = throwable
}

/** Lazy add a log message if isErrorEnabled is true */
public fun KLogger.error(
throwable: Throwable? = null,
marker: org.slf4j.Marker?,
message: () -> Any?
): Unit =
at(Level.ERROR, marker) {
this.message = message.toStringSafe()
this.cause = throwable
}

/** Lazy add a log message with throwable payload if isTraceEnabled is true */
public fun KLogger.atTrace(
marker: org.slf4j.Marker?,
block: KLoggingEventBuilder.() -> Unit
): Unit = at(Level.TRACE, marker, block)

/** Lazy add a log message with throwable payload if isDebugEnabled is true */
public fun KLogger.atDebug(
marker: org.slf4j.Marker?,
block: KLoggingEventBuilder.() -> Unit
): Unit = at(Level.DEBUG, marker, block)

/** Lazy add a log message with throwable payload if isInfoEnabled is true */
public fun KLogger.atInfo(marker: org.slf4j.Marker?, block: KLoggingEventBuilder.() -> Unit): Unit =
at(Level.INFO, marker, block)

/** Lazy add a log message with throwable payload if isWarnEnabled is true */
public fun KLogger.atWarn(marker: org.slf4j.Marker?, block: KLoggingEventBuilder.() -> Unit): Unit =
at(Level.WARN, marker, block)

/** Lazy add a log message with throwable payload if isErrorEnabled is true */
public fun KLogger.atError(
marker: org.slf4j.Marker?,
block: KLoggingEventBuilder.() -> Unit
): Unit = at(Level.ERROR, marker, block)

/** Lazy add a log message if level enabled */
public fun KLogger.at(
level: Level,
marker: org.slf4j.Marker? = null,
block: KLoggingEventBuilder.() -> Unit
) {
at(level, marker?.toKotlinLogging(), block)
}

/**
* Similar to [.isTraceEnabled] method except that the marker data is also taken into account.
*
* @param marker The marker data to take into consideration
* @return True if this Logger is enabled for the TRACE level, false otherwise.
*/
public fun KLogger.isTraceEnabled(marker: org.slf4j.Marker? = null): Boolean =
isLoggingEnabledFor(Level.TRACE, marker)

/**
* Similar to [.isDebugEnabled] method except that the marker data is also taken into account.
*
* @param marker The marker data to take into consideration
* @return True if this Logger is enabled for the DEBUG level, false otherwise.
*/
public fun KLogger.isDebugEnabled(marker: org.slf4j.Marker? = null): Boolean =
isLoggingEnabledFor(Level.DEBUG, marker)

/**
* Similar to [.isInfoEnabled] method except that the marker data is also taken into consideration.
*
* @param marker The marker data to take into consideration
* @return true if this Logger is enabled for the INFO level, false otherwise.
*/
public fun KLogger.isInfoEnabled(marker: org.slf4j.Marker? = null): Boolean =
isLoggingEnabledFor(Level.INFO, marker)

/**
* Similar to [.isWarnEnabled] method except that the marker data is also taken into consideration.
*
* @param marker The marker data to take into consideration
* @return True if this Logger is enabled for the WARN level, false otherwise.
*/
public fun KLogger.isWarnEnabled(marker: org.slf4j.Marker? = null): Boolean =
isLoggingEnabledFor(Level.WARN, marker)

/**
* Similar to [.isErrorEnabled] method except that the marker data is also taken into consideration.
*
* @param marker The marker data to take into consideration
* @return True if this Logger is enabled for the ERROR level, false otherwise.
*/
public fun KLogger.isErrorEnabled(marker: org.slf4j.Marker? = null): Boolean =
isLoggingEnabledFor(Level.ERROR, marker)

/**
* Similar to [.isLoggingOff] method except that the marker data is also taken into consideration.
*
* @param marker The marker data to take into consideration
* @return True if this Logger is set to the OFF level, false otherwise.
*/
public fun KLogger.isLoggingOff(marker: org.slf4j.Marker? = null): Boolean =
!isLoggingEnabledFor(Level.ERROR, marker)

public fun KLogger.isLoggingEnabledFor(level: Level, marker: org.slf4j.Marker? = null): Boolean =
isLoggingEnabledFor(level, marker?.toKotlinLogging())
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.github.oshai.kotlinlogging.slf4j.internal

import io.github.oshai.kotlinlogging.Marker

@JvmInline
internal value class Slf4jMarker(val marker: org.slf4j.Marker) : Marker, org.slf4j.Marker by marker
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package io.github.oshai.kotlinlogging.slf4j

import io.github.oshai.kotlinlogging.KotlinLogging
import io.github.oshai.kotlinlogging.addAppender
import io.github.oshai.kotlinlogging.removeAppender
import kotlin.test.assertEquals
import org.apache.logging.log4j.core.Appender
import org.apache.logging.log4j.core.LogEvent
import org.apache.logging.log4j.core.appender.NullAppender
import org.apache.logging.slf4j.Log4jMarker
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test

private val logger = KotlinLogging.logger {}

private class TestAppender(
val appender: Appender = NullAppender.createAppender("testAppender"),
var lastEvent: LogEvent? = null,
) : Appender by appender {
override fun append(event: LogEvent) {
lastEvent = event.toImmutable()
appender.append(event)
}
}

class Slf4jMarkerTest {

private val testAppender = TestAppender()

@BeforeEach
fun setupAppender() {
addAppender(testAppender)
}

@AfterEach
fun removeAppender() {
removeAppender(testAppender)
}

@Test
fun `a slf4j Marker can be directly supplied to the logger`() {

val log4jMarker =
object : org.apache.logging.log4j.Marker {
override fun addParents(
vararg markers: org.apache.logging.log4j.Marker?
): org.apache.logging.log4j.Marker = TODO("Not yet implemented")

override fun getName(): String = "foo"

override fun getParents(): Array<org.apache.logging.log4j.Marker> =
TODO("Not yet implemented")

override fun hasParents(): Boolean = false

override fun isInstanceOf(m: org.apache.logging.log4j.Marker?): Boolean = false

override fun isInstanceOf(name: String?): Boolean = false

override fun remove(marker: org.apache.logging.log4j.Marker?): Boolean =
TODO("Not yet implemented")

override fun setParents(
vararg markers: org.apache.logging.log4j.Marker?
): org.apache.logging.log4j.Marker = TODO("Not yet implemented")
}

val slf4jMarker = Log4jMarker(null, log4jMarker)

logger.atError(slf4jMarker) { message = "bar" }

assertEquals(testAppender.lastEvent?.marker, log4jMarker)
}
}

0 comments on commit 9173fc0

Please sign in to comment.