diff --git a/kotlin-logging-common/src/main/kotlin/mu/KLogger.kt b/kotlin-logging-common/src/main/kotlin/mu/KLogger.kt index 95b16aaa..f96212aa 100644 --- a/kotlin-logging-common/src/main/kotlin/mu/KLogger.kt +++ b/kotlin-logging-common/src/main/kotlin/mu/KLogger.kt @@ -104,4 +104,30 @@ expect interface KLogger { * Lazy add a log message with a marker and throwable payload if isErrorEnabled is true */ fun error(marker: Marker?, t: Throwable?, msg: () -> Any?) + + /** + * Add a log message with all the supplied parameters along with method name + */ + fun entry(vararg argArray: Any) + + /** + * Add log message indicating exit of a method + */ + fun exit() + + /** + * Add a log message with the return value of a method + */ + fun exit(retval: T): T where T : Any + + /** + * Add a log message indicating an exception will be thrown along with the stack trace. + */ + fun throwing(throwable: T): T where T : Throwable + + /** + * Add a log message indicating an exception is caught along with the stack trace. + */ + fun catching(throwable: T) where T : Throwable + } diff --git a/kotlin-logging-js/src/main/kotlin/mu/KLogger.kt b/kotlin-logging-js/src/main/kotlin/mu/KLogger.kt index 045b8f8f..c3fe943d 100644 --- a/kotlin-logging-js/src/main/kotlin/mu/KLogger.kt +++ b/kotlin-logging-js/src/main/kotlin/mu/KLogger.kt @@ -105,4 +105,28 @@ actual interface KLogger { */ actual fun error(marker: Marker?, t: Throwable?, msg: () -> Any?) + /** + * Add a log message with all the supplied parameters along with method name + */ + actual fun entry(vararg argArray: Any) + + /** + * Add log message indicating exit of a method + */ + actual fun exit() + + /** + * Add a log message with the return value of a method + */ + actual fun exit(retval: T): T where T : Any + + /** + * Add a log message indicating an exception will be thrown along with the stack trace. + */ + actual fun throwing(throwable: T): T where T : Throwable + + /** + * Add a log message indicating an exception is caught along with the stack trace. + */ + actual fun catching(throwable: T) where T : Throwable } diff --git a/kotlin-logging-js/src/main/kotlin/mu/internal/KLoggerJS.kt b/kotlin-logging-js/src/main/kotlin/mu/internal/KLoggerJS.kt index f46fded2..387e892a 100644 --- a/kotlin-logging-js/src/main/kotlin/mu/internal/KLoggerJS.kt +++ b/kotlin-logging-js/src/main/kotlin/mu/internal/KLoggerJS.kt @@ -4,16 +4,12 @@ import mu.KLogger import mu.KotlinLoggingConfiguration.APPENDER import mu.KotlinLoggingConfiguration.FORMATTER import mu.KotlinLoggingLevel -import mu.KotlinLoggingLevel.DEBUG -import mu.KotlinLoggingLevel.ERROR -import mu.KotlinLoggingLevel.INFO -import mu.KotlinLoggingLevel.TRACE -import mu.KotlinLoggingLevel.WARN +import mu.KotlinLoggingLevel.* import mu.Marker import mu.isLoggingEnabled internal class KLoggerJS( - private val loggerName: String + private val loggerName: String ) : KLogger { override fun trace(msg: () -> Any?) = TRACE.logIfEnabled(msg, APPENDER::trace) @@ -80,4 +76,25 @@ internal class KLoggerJS( } } + override fun entry(vararg argArray: Any) { + TRACE.logIfEnabled({ "entry($argArray)" }, APPENDER::trace) + } + + override fun exit() { + TRACE.logIfEnabled({ "exit()" }, APPENDER::trace) + } + + override fun exit(retval: T): T { + TRACE.logIfEnabled({ "exut($retval)" }, APPENDER::trace) + return retval + } + + override fun throwing(throwable: T): T { + ERROR.logIfEnabled({ "throwing($throwable" }, throwable, APPENDER::error) + return throwable + } + + override fun catching(throwable: T) { + ERROR.logIfEnabled({ "catching($throwable" }, throwable, APPENDER::error) + } } diff --git a/kotlin-logging-jvm/src/main/kotlin/mu/KLogger.kt b/kotlin-logging-jvm/src/main/kotlin/mu/KLogger.kt index c1b6acc3..16bd1df6 100644 --- a/kotlin-logging-jvm/src/main/kotlin/mu/KLogger.kt +++ b/kotlin-logging-jvm/src/main/kotlin/mu/KLogger.kt @@ -114,4 +114,28 @@ actual interface KLogger : Logger { */ actual fun error(marker: Marker?, t: Throwable?, msg: () -> Any?) + /** + * Add a log message with all the supplied parameters along with method name + */ + actual fun entry(vararg argArray: Any) + + /** + * Add log message indicating exit of a method + */ + actual fun exit() + + /** + * Add a log message with the return value of a method + */ + actual fun exit(retval: T): T where T : Any + + /** + * Add a log message indicating an exception will be thrown along with the stack trace. + */ + actual fun throwing(throwable: T): T where T : Throwable + + /** + * Add a log message indicating an exception is caught along with the stack trace. + */ + actual fun catching(throwable: T) where T : Throwable } diff --git a/kotlin-logging-jvm/src/main/kotlin/mu/internal/LocationAwareKLogger.kt b/kotlin-logging-jvm/src/main/kotlin/mu/internal/LocationAwareKLogger.kt index be7708ef..6c34237a 100644 --- a/kotlin-logging-jvm/src/main/kotlin/mu/internal/LocationAwareKLogger.kt +++ b/kotlin-logging-jvm/src/main/kotlin/mu/internal/LocationAwareKLogger.kt @@ -1,6 +1,7 @@ package mu.internal import mu.KLogger +import mu.KMarkerFactory import org.slf4j.Logger import org.slf4j.Marker import org.slf4j.helpers.MessageFormatter @@ -13,6 +14,13 @@ import org.slf4j.spi.LocationAwareLogger internal class LocationAwareKLogger(override val underlyingLogger: LocationAwareLogger) : KLogger, Logger by underlyingLogger { private val fqcn: String = LocationAwareKLogger::class.java.name + private val ENTRY = KMarkerFactory.getMarker("ENTRY") + private val EXIT = KMarkerFactory.getMarker("EXIT") + + private val THROWING = KMarkerFactory.getMarker("THROWING") + private val CATCHING = KMarkerFactory.getMarker("CATCHING") + private val EXITONLY = "exit" + private val EXITMESSAGE = "exit with ({})" override fun trace(msg: String?) { if (!underlyingLogger.isTraceEnabled) @@ -613,4 +621,49 @@ internal class LocationAwareKLogger(override val underlyingLogger: LocationAware override fun error(marker: Marker?, t: Throwable?, msg: () -> Any?) { if (isErrorEnabled) error(marker, msg.toStringSafe(), t) } + + override fun catching(throwable: T) { + if (underlyingLogger.isErrorEnabled) { + underlyingLogger.log(CATCHING, fqcn, LocationAwareLogger.ERROR_INT, "catching", null, throwable) + } + } + + override fun entry(vararg argArray: Any) { + if (underlyingLogger.isTraceEnabled(ENTRY)) { + val tp = MessageFormatter.arrayFormat(buildMessagePattern(argArray.size), argArray) + underlyingLogger.log(ENTRY, fqcn, LocationAwareLogger.TRACE_INT, tp.message, null, null); + } + } + + override fun exit() { + if (underlyingLogger.isTraceEnabled(EXIT)) { + underlyingLogger.log(EXIT, fqcn, LocationAwareLogger.TRACE_INT, EXITONLY, null, null) + } + } + + override fun exit(retval: T): T { + if (underlyingLogger.isTraceEnabled(EXIT)) { + val tp = MessageFormatter.format(EXITMESSAGE, retval) + underlyingLogger.log(EXIT, fqcn, LocationAwareLogger.TRACE_INT, tp.message, arrayOf(retval), tp.throwable) + } + return retval + } + + override fun throwing(throwable: T): T { + underlyingLogger.log(THROWING, fqcn, LocationAwareLogger.ERROR_INT, "throwing", null, throwable) + throw throwable + } + + private fun buildMessagePattern(len: Int): String { + val sb = StringBuilder() + sb.append(" entry with (") + for (i in 0 until len) { + sb.append("{}") + if (i != len - 1) + sb.append(", ") + } + sb.append(')') + return sb.toString() + } + } diff --git a/kotlin-logging-jvm/src/main/kotlin/mu/internal/LocationIgnorantKLogger.kt b/kotlin-logging-jvm/src/main/kotlin/mu/internal/LocationIgnorantKLogger.kt index 05846b34..a9788d24 100644 --- a/kotlin-logging-jvm/src/main/kotlin/mu/internal/LocationIgnorantKLogger.kt +++ b/kotlin-logging-jvm/src/main/kotlin/mu/internal/LocationIgnorantKLogger.kt @@ -152,4 +152,35 @@ internal class LocationIgnorantKLogger(override val underlyingLogger: Logger) override fun error(marker: Marker?, t: Throwable?, msg: () -> Any?) { if (isErrorEnabled) error(marker, msg.toStringSafe(), t) } + override inline fun entry(vararg argArray: Any) { + if (underlyingLogger.isTraceEnabled) { + underlyingLogger.trace("entry({})", argArray) + } + } + + override inline fun exit() { + if (underlyingLogger.isTraceEnabled) { + underlyingLogger.trace("exit") + } + } + + override inline fun exit(retval: T): T { + if (underlyingLogger.isTraceEnabled) { + underlyingLogger.trace("exit({}}", retval) + } + return retval + } + + override inline fun throwing(throwable: T): T { + if (underlyingLogger.isErrorEnabled) { + underlyingLogger.error("throwing($throwable)", throwable) + } + return throwable + } + + override inline fun catching(throwable: T) { + if (underlyingLogger.isErrorEnabled) { + underlyingLogger.error("catching($throwable)", throwable) + } + } } diff --git a/kotlin-logging-jvm/src/test/kotlin/mu/ClassWithLoggingForLocationTesting.kt b/kotlin-logging-jvm/src/test/kotlin/mu/ClassWithLoggingForLocationTesting.kt index 7093b151..9f77a3b6 100644 --- a/kotlin-logging-jvm/src/test/kotlin/mu/ClassWithLoggingForLocationTesting.kt +++ b/kotlin-logging-jvm/src/test/kotlin/mu/ClassWithLoggingForLocationTesting.kt @@ -14,4 +14,10 @@ class ClassWithLoggingForLocationTesting { fun logNull() { logger.info(null) } + + fun logEntry() { + logger.entry(1, 2) + logger.info("log entry body") + logger.exit(2) + } } diff --git a/kotlin-logging-jvm/src/test/kotlin/mu/LoggingWithLocationTest.kt b/kotlin-logging-jvm/src/test/kotlin/mu/LoggingWithLocationTest.kt index 4a76f3bd..692cd80e 100644 --- a/kotlin-logging-jvm/src/test/kotlin/mu/LoggingWithLocationTest.kt +++ b/kotlin-logging-jvm/src/test/kotlin/mu/LoggingWithLocationTest.kt @@ -33,6 +33,13 @@ class LoggingWithLocationTest { ClassWithLoggingForLocationTesting().logNull() Assert.assertEquals("INFO ClassWithLoggingForLocationTesting.logNull(15) - null", appenderWithWriter.writer.toString().trim()) } + @Test + fun testNullLoggingWithLocationEntryExit() { + ClassWithLoggingForLocationTesting().logEntry() + Assert.assertEquals("TRACE ClassWithLoggingForLocationTesting.logEntry(19) - entry with (1, 2)\n" + + "INFO ClassWithLoggingForLocationTesting.logEntry(20) - log entry body\n" + + "TRACE ClassWithLoggingForLocationTesting.logEntry(21) - exit with (2)", appenderWithWriter.writer.toString().trim()) + } }