From 5da6b710c4e058df96493b6bd93afb021bd3271d Mon Sep 17 00:00:00 2001 From: Vladimir Petrakovich Date: Tue, 6 Apr 2021 15:10:36 +0300 Subject: [PATCH 1/3] add contract to withLoggingContext() --- build.gradle | 4 ++++ .../ru/kontur/kinfra/logging/LoggingContext.kt | 13 +++++++++++++ .../ru/kontur/kinfra/logging/LoggingContextTests.kt | 9 +++++++++ 3 files changed, 26 insertions(+) diff --git a/build.gradle b/build.gradle index 7ffbcee..c480310 100644 --- a/build.gradle +++ b/build.gradle @@ -41,6 +41,10 @@ dependencies { } } +tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile) { + kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn" +} + jar { manifest.attributes "Automatic-Module-Name": "ru.kontur.kinfra.logging" } diff --git a/src/main/kotlin/ru/kontur/kinfra/logging/LoggingContext.kt b/src/main/kotlin/ru/kontur/kinfra/logging/LoggingContext.kt index 69b40cb..1dac249 100644 --- a/src/main/kotlin/ru/kontur/kinfra/logging/LoggingContext.kt +++ b/src/main/kotlin/ru/kontur/kinfra/logging/LoggingContext.kt @@ -1,9 +1,14 @@ +@file:OptIn(ExperimentalContracts::class) + package ru.kontur.kinfra.logging import kotlinx.coroutines.ThreadContextElement import ru.kontur.kinfra.logging.LoggingContext.Element import ru.kontur.kinfra.logging.decor.MessageDecor import ru.kontur.kinfra.logging.impl.ContextElementSet +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract import kotlin.coroutines.CoroutineContext /** @@ -252,6 +257,10 @@ sealed class LoggingContext : CoroutineContext.Element { */ // crossinline disallows suspending inline fun withLoggingContext(key: String, value: Any, crossinline block: () -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + val oldContext = addContext(key, value) return try { block() @@ -267,6 +276,10 @@ inline fun withLoggingContext(key: String, value: Any, crossinline block: () */ // crossinline disallows suspending inline fun withLoggingContext(context: LoggingContext, crossinline block: () -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + val oldContext = replaceContext(context) return try { block() diff --git a/src/test/kotlin/ru/kontur/kinfra/logging/LoggingContextTests.kt b/src/test/kotlin/ru/kontur/kinfra/logging/LoggingContextTests.kt index e9b6cd8..e9f22ea 100644 --- a/src/test/kotlin/ru/kontur/kinfra/logging/LoggingContextTests.kt +++ b/src/test/kotlin/ru/kontur/kinfra/logging/LoggingContextTests.kt @@ -260,6 +260,15 @@ class LoggingContextTests { assertEquals("456", map["bar"]) } + @Test + fun withLoggingContext_has_callsInPlace_contract() { + val foo: String + withLoggingContext("key", "value") { + foo = "bar" + } + assertEquals("bar", foo) + } + private object DelegatingLoggerFactory : LoggerFactory.Wrapper() { public override var delegate: LoggerFactory by Delegates.notNull() } From f0b32b5b3945e2a71c9d195d991db9d655a11df8 Mon Sep 17 00:00:00 2001 From: Vladimir Petrakovich Date: Fri, 8 Oct 2021 11:06:59 +0300 Subject: [PATCH 2/3] fix error message --- README.md | 7 ++++--- build.gradle | 2 +- src/main/kotlin/ru/kontur/kinfra/logging/LoggingContext.kt | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4094bf2..9c572fa 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ It is a final class provided by the library, that has a bunch of convenient meth `LogLevel` is an enumeration describing the importance of a log message. There are 4 log levels: + * `DEBUG` Detailed messages that can help in debugging an application's subsystem. Such messages allow a developer to trace the execution path or figure out the current state of the system. @@ -60,12 +61,12 @@ Contexts are immutable and hierarchical. A nested context contains all elements ## Basic usage -In order to log messages, one should define a `Logger`: // todo: questionable +In order to log messages, one should define a `Logger`: ```kotlin val logger = Logger.currentClass() ``` This way, a `Logger` will be obtained from the default `LoggerFactory`. -The logger will be tied to the class declaring this property. +The logger will be named corresponding to the class or file declaring this property. There is a `Logger.log(level: LogLevel, error: Throwable? = null, messageBuilder: () -> String)` method that can be used for logging messages: @@ -135,7 +136,7 @@ Result: ``` It is incorrect to add to a context an element with a key that already present in the context. -Execution of the following code with lead to an `IllegalStateException`: +Execution of the following code with lead to an `IllegalArgumentException`: ```kotlin withLoggingContext("id", "foo") { withLoggingContext("id", "bar") diff --git a/build.gradle b/build.gradle index c480310..d76f71d 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ plugins { id 'maven-publish' id 'jacoco' id 'org.jetbrains.kotlin.jvm' version '1.4.21' - id 'ru.kontur.kinfra.presets' version '1.4' + id 'ru.kontur.kinfra.presets' version '1.5' id 'me.champeau.gradle.jmh' version '0.5.3' } diff --git a/src/main/kotlin/ru/kontur/kinfra/logging/LoggingContext.kt b/src/main/kotlin/ru/kontur/kinfra/logging/LoggingContext.kt index 1dac249..ae0f2b3 100644 --- a/src/main/kotlin/ru/kontur/kinfra/logging/LoggingContext.kt +++ b/src/main/kotlin/ru/kontur/kinfra/logging/LoggingContext.kt @@ -145,7 +145,7 @@ sealed class LoggingContext : CoroutineContext.Element { init { val currentValue = parent[element.key] require(currentValue == null) { - "Context already contains an element with key '$key'" + + "Context already contains an element with key '${element.key}'" + " (current value: '$currentValue', new value: '${element.value}')" } } From 66148d6db3f776e6464f8a340b7630283b75bc52 Mon Sep 17 00:00:00 2001 From: Vladimir Petrakovich Date: Fri, 8 Oct 2021 11:36:57 +0300 Subject: [PATCH 3/3] enable explicit api mode --- build.gradle | 6 +++- .../kinfra/logging/DefaultLoggerFactory.kt | 2 +- .../ru/kontur/kinfra/logging/LogLevel.kt | 4 +-- .../kotlin/ru/kontur/kinfra/logging/Logger.kt | 27 ++++++++------- .../ru/kontur/kinfra/logging/LoggerFactory.kt | 14 ++++---- .../kontur/kinfra/logging/LoggingContext.kt | 33 ++++++++++--------- .../kontur/kinfra/logging/MessageBuilder.kt | 4 +-- .../kinfra/logging/backend/CallerInfo.kt | 4 +-- .../kinfra/logging/backend/LoggerBackend.kt | 14 ++++---- .../logging/backend/LoggingAdditionalData.kt | 10 +++--- .../kinfra/logging/backend/LoggingRequest.kt | 16 ++++----- .../backend/slf4j/LoggingRequestMarker.kt | 10 +++--- .../logging/builtin/BuiltinLoggerFactory.kt | 3 +- .../logging/decor/DefaultMessageDecor.kt | 6 ++-- .../kinfra/logging/decor/MessageDecor.kt | 12 +++---- 15 files changed, 87 insertions(+), 78 deletions(-) diff --git a/build.gradle b/build.gradle index d76f71d..b3c9a52 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ plugins { id 'java-library' id 'maven-publish' id 'jacoco' - id 'org.jetbrains.kotlin.jvm' version '1.4.21' + id 'org.jetbrains.kotlin.jvm' version '1.4.32' id 'ru.kontur.kinfra.presets' version '1.5' id 'me.champeau.gradle.jmh' version '0.5.3' } @@ -41,6 +41,10 @@ dependencies { } } +kotlin { + explicitApi() +} + tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile) { kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn" } diff --git a/src/main/kotlin/ru/kontur/kinfra/logging/DefaultLoggerFactory.kt b/src/main/kotlin/ru/kontur/kinfra/logging/DefaultLoggerFactory.kt index 43ec392..d235c53 100644 --- a/src/main/kotlin/ru/kontur/kinfra/logging/DefaultLoggerFactory.kt +++ b/src/main/kotlin/ru/kontur/kinfra/logging/DefaultLoggerFactory.kt @@ -5,7 +5,7 @@ import ru.kontur.kinfra.logging.builtin.BuiltinLoggerFactory /** * Default [logger factory][LoggerFactory]. */ -object DefaultLoggerFactory : LoggerFactory.Wrapper() { +public object DefaultLoggerFactory : LoggerFactory.Wrapper() { /** * Actual factory in use. diff --git a/src/main/kotlin/ru/kontur/kinfra/logging/LogLevel.kt b/src/main/kotlin/ru/kontur/kinfra/logging/LogLevel.kt index f26ea93..3335b23 100644 --- a/src/main/kotlin/ru/kontur/kinfra/logging/LogLevel.kt +++ b/src/main/kotlin/ru/kontur/kinfra/logging/LogLevel.kt @@ -3,7 +3,7 @@ package ru.kontur.kinfra.logging /** * Importance level of a log message. */ -enum class LogLevel { +public enum class LogLevel { DEBUG, INFO, WARN, @@ -11,6 +11,6 @@ enum class LogLevel { ; // for user extensions - companion object + public companion object } diff --git a/src/main/kotlin/ru/kontur/kinfra/logging/Logger.kt b/src/main/kotlin/ru/kontur/kinfra/logging/Logger.kt index 9d463b6..9d245da 100644 --- a/src/main/kotlin/ru/kontur/kinfra/logging/Logger.kt +++ b/src/main/kotlin/ru/kontur/kinfra/logging/Logger.kt @@ -20,28 +20,28 @@ import kotlin.reflect.KClass * * [Logger.forName] obtains a logger with arbitrary name. * Use when none of the above is appropriate. */ -class Logger internal constructor( +public class Logger internal constructor( private val backend: LoggerBackend, private val factory: LoggerFactory ) { /** [Log][log] a message with [DEBUG][LogLevel.DEBUG] level. */ - inline fun debug(error: Throwable? = null, crossinline lazyMessage: MessageBuilder.() -> String) { + public inline fun debug(error: Throwable? = null, crossinline lazyMessage: MessageBuilder.() -> String) { log(LogLevel.DEBUG, error, lazyMessage) } /** [Log][log] a message with [INFO][LogLevel.INFO] level. */ - inline fun info(error: Throwable? = null, crossinline lazyMessage: MessageBuilder.() -> String) { + public inline fun info(error: Throwable? = null, crossinline lazyMessage: MessageBuilder.() -> String) { log(LogLevel.INFO, error, lazyMessage) } /** [Log][log] a message with [WARN][LogLevel.WARN] level. */ - inline fun warn(error: Throwable? = null, crossinline lazyMessage: MessageBuilder.() -> String) { + public inline fun warn(error: Throwable? = null, crossinline lazyMessage: MessageBuilder.() -> String) { log(LogLevel.WARN, error, lazyMessage) } /** [Log][log] a message with [ERROR][LogLevel.ERROR] level. */ - inline fun error(error: Throwable? = null, crossinline lazyMessage: MessageBuilder.() -> String) { + public inline fun error(error: Throwable? = null, crossinline lazyMessage: MessageBuilder.() -> String) { log(LogLevel.ERROR, error, lazyMessage) } @@ -52,8 +52,13 @@ class Logger internal constructor( * * @param error a [Throwable] that should be logged with the message */ - // crossinline disallows non-local returns in the lambda - inline fun log(level: LogLevel, error: Throwable? = null, crossinline lazyMessage: MessageBuilder.() -> String) { + public inline fun log( + level: LogLevel, + error: Throwable? = null, + // crossinline disallows non-local returns in the lambda + crossinline lazyMessage: MessageBuilder.() -> String + ) { + if (isEnabled(level)) { val messageBuilder = MessageBuilder.STUB val message = lazyMessage.invoke(messageBuilder) @@ -99,7 +104,7 @@ class Logger internal constructor( return "Logger(backend: $backend)" } - companion object { + public companion object { private val callerInfo = CallerInfo(facadeClassName = Logger::class.java.name) @@ -116,14 +121,14 @@ class Logger internal constructor( * * Note that [Logger.currentClass] would return a logger for `BaseClass`. */ - fun forClass(kClass: KClass<*>): Logger { + public fun forClass(kClass: KClass<*>): Logger { return DefaultLoggerFactory.getLogger(kClass) } /** * Obtains a [Logger] instance with a given [name] using default [LoggerFactory]. */ - fun forName(name: String): Logger { + public fun forName(name: String): Logger { return DefaultLoggerFactory.getLogger(name) } @@ -156,7 +161,7 @@ class Logger internal constructor( * ``` */ @Suppress("NOTHING_TO_INLINE") - inline fun currentClass(): Logger { + public inline fun currentClass(): Logger { return DefaultLoggerFactory.currentClassLogger() } diff --git a/src/main/kotlin/ru/kontur/kinfra/logging/LoggerFactory.kt b/src/main/kotlin/ru/kontur/kinfra/logging/LoggerFactory.kt index 7be0117..3c8707d 100644 --- a/src/main/kotlin/ru/kontur/kinfra/logging/LoggerFactory.kt +++ b/src/main/kotlin/ru/kontur/kinfra/logging/LoggerFactory.kt @@ -25,7 +25,7 @@ import kotlin.reflect.KClass * * * `getEmptyDecor()`: provides a [MessageDecor] to render context data in log messages. */ -abstract class LoggerFactory { +public abstract class LoggerFactory { /** * Obtains a [Logger] with a given [name]. @@ -34,7 +34,7 @@ abstract class LoggerFactory { * * This method is thread safe. Calls [getLoggerBackend] internally. */ - open fun getLogger(name: String): Logger { + public open fun getLogger(name: String): Logger { val backend = getLoggerBackend(name) return Logger(backend, this) } @@ -44,7 +44,7 @@ abstract class LoggerFactory { * * This method is thread safe. Calls [getLoggerBackend] internally. */ - fun getLogger(kClass: KClass<*>): Logger { + public open fun getLogger(kClass: KClass<*>): Logger { val name = requireNotNull(kClass.qualifiedName) { "Class $kClass does not have a fully qualified name" } @@ -73,18 +73,18 @@ abstract class LoggerFactory { * Custom wrapping factories should extend this class to properly implement * new methods that may be added in the future. */ - abstract class Wrapper : LoggerFactory() { + public abstract class Wrapper : LoggerFactory() { protected abstract val delegate: LoggerFactory override fun getLoggerBackend(name: String): LoggerBackend = delegate.getLoggerBackend(name) - override fun getEmptyDecor() = delegate.getEmptyDecor() + override fun getEmptyDecor(): MessageDecor = delegate.getEmptyDecor() } // for user extensions - companion object + public companion object } @@ -92,7 +92,7 @@ abstract class LoggerFactory { * Obtains [Logger] instance to use in the current class (that is the class calling this method). */ @Suppress("NOTHING_TO_INLINE") -inline fun LoggerFactory.currentClassLogger(): Logger { +public inline fun LoggerFactory.currentClassLogger(): Logger { /* * All internal callers of this function must be inline! * It is required for MethodHandles.lookup() to work correctly. diff --git a/src/main/kotlin/ru/kontur/kinfra/logging/LoggingContext.kt b/src/main/kotlin/ru/kontur/kinfra/logging/LoggingContext.kt index ae0f2b3..477987d 100644 --- a/src/main/kotlin/ru/kontur/kinfra/logging/LoggingContext.kt +++ b/src/main/kotlin/ru/kontur/kinfra/logging/LoggingContext.kt @@ -6,6 +6,7 @@ import kotlinx.coroutines.ThreadContextElement import ru.kontur.kinfra.logging.LoggingContext.Element import ru.kontur.kinfra.logging.decor.MessageDecor import ru.kontur.kinfra.logging.impl.ContextElementSet +import java.util.* import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract @@ -40,7 +41,7 @@ import kotlin.coroutines.CoroutineContext * * The context is immutable, adding new elements creates a new context. */ -sealed class LoggingContext : CoroutineContext.Element { +public sealed class LoggingContext : CoroutineContext.Element { final override val key: CoroutineContext.Key<*> get() = LoggingContext @@ -48,13 +49,13 @@ sealed class LoggingContext : CoroutineContext.Element { /** * Elements contained in this context. */ - abstract val elements: Collection + public abstract val elements: Collection /** * Returns [value][Element.value] of the context element having specified key. * If no such element is found, returns `null`. */ - abstract operator fun get(key: String): String? + public abstract operator fun get(key: String): String? /** * Obtains a decor instance based on specified [empty] decor to render data of this context. @@ -66,25 +67,25 @@ sealed class LoggingContext : CoroutineContext.Element { * * Iteration order of the map is the same as in [elements]. */ - abstract fun asMap(): Map + public abstract fun asMap(): Map /** * Returns `true` if the context is empty (contains no elements), `false` otherwise. */ - abstract fun isEmpty(): Boolean + public abstract fun isEmpty(): Boolean /** * Returns a context composed of this context and an element with specified [key] and [value]. * * This context must not contain an element with the same [key]. */ - fun with(key: String, value: Any): LoggingContext { + public fun with(key: String, value: Any): LoggingContext { val element = Element(key, value.toString()) return PopulatedContext(this, element) } @Deprecated("Logging contexts cannot be merged", level = DeprecationLevel.ERROR, replaceWith = ReplaceWith("other")) - operator fun plus(other: LoggingContext): CoroutineContext { + public operator fun plus(other: LoggingContext): CoroutineContext { return other } @@ -92,7 +93,7 @@ sealed class LoggingContext : CoroutineContext.Element { * A key-value pair that represents an aspect of context in which some code is executed. * For example, identifier of a user, operation or request. */ - class Element( + public class Element( override val key: String, override val value: String ) : Map.Entry { @@ -107,7 +108,7 @@ sealed class LoggingContext : CoroutineContext.Element { return key == other.key && value == other.value } - override fun hashCode() = 31 * key.hashCode() + value.hashCode() + override fun hashCode(): Int = Objects.hash(key, value) override fun toString(): String { return if (value.isNotEmpty()) "$key=$value" else key @@ -201,7 +202,7 @@ sealed class LoggingContext : CoroutineContext.Element { } override fun hashCode(): Int { - return element.hashCode() + parent.hashCode() + return Objects.hash(element, parent) } override fun toString(): String { @@ -215,20 +216,20 @@ sealed class LoggingContext : CoroutineContext.Element { } - companion object : CoroutineContext.Key { + public companion object : CoroutineContext.Key { /** * Empty context. This context has no elements. */ @JvmField - val EMPTY: LoggingContext = EmptyContext + public val EMPTY: LoggingContext = EmptyContext private val threadLocal = ThreadLocal() /** * Returns [LoggingContext] of the current thread or coroutine. */ - fun current(): LoggingContext { + public fun current(): LoggingContext { return threadLocal.get() ?: EMPTY } @@ -242,7 +243,7 @@ sealed class LoggingContext : CoroutineContext.Element { * @see LoggingContext.current * @see LoggingContext.with */ - fun with(key: String, value: Any): LoggingContext { + public fun with(key: String, value: Any): LoggingContext { return current().with(key, value) } @@ -256,7 +257,7 @@ sealed class LoggingContext : CoroutineContext.Element { * In suspending code, use `withContext(LoggingContext.with(key,value)) { ... }` instead. */ // crossinline disallows suspending -inline fun withLoggingContext(key: String, value: Any, crossinline block: () -> R): R { +public inline fun withLoggingContext(key: String, value: Any, crossinline block: () -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -275,7 +276,7 @@ inline fun withLoggingContext(key: String, value: Any, crossinline block: () * In suspending code, use `withContext(LoggingContext.with(key,value)) { ... }` instead. */ // crossinline disallows suspending -inline fun withLoggingContext(context: LoggingContext, crossinline block: () -> R): R { +public inline fun withLoggingContext(context: LoggingContext, crossinline block: () -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } diff --git a/src/main/kotlin/ru/kontur/kinfra/logging/MessageBuilder.kt b/src/main/kotlin/ru/kontur/kinfra/logging/MessageBuilder.kt index c407a1a..77627d6 100644 --- a/src/main/kotlin/ru/kontur/kinfra/logging/MessageBuilder.kt +++ b/src/main/kotlin/ru/kontur/kinfra/logging/MessageBuilder.kt @@ -5,7 +5,7 @@ package ru.kontur.kinfra.logging * * It is a future extension point without any functionality for now. */ -abstract class MessageBuilder private constructor() { +public abstract class MessageBuilder private constructor() { /* * Implementation considerations: * Beware that adding ANY public members to this class @@ -15,7 +15,7 @@ abstract class MessageBuilder private constructor() { private class StubImpl : MessageBuilder() - companion object { + public companion object { @PublishedApi @JvmField diff --git a/src/main/kotlin/ru/kontur/kinfra/logging/backend/CallerInfo.kt b/src/main/kotlin/ru/kontur/kinfra/logging/backend/CallerInfo.kt index c7d610c..d9b5993 100644 --- a/src/main/kotlin/ru/kontur/kinfra/logging/backend/CallerInfo.kt +++ b/src/main/kotlin/ru/kontur/kinfra/logging/backend/CallerInfo.kt @@ -1,6 +1,6 @@ package ru.kontur.kinfra.logging.backend -class CallerInfo( +public class CallerInfo( /** * The fully qualified name of the facade class called by user code. * @@ -19,5 +19,5 @@ class CallerInfo( * At least one frame in some method of the class named [facadeClassName] must be on the stack * when the [LoggerBackend.log] is called. */ - val facadeClassName: String + public val facadeClassName: String ) diff --git a/src/main/kotlin/ru/kontur/kinfra/logging/backend/LoggerBackend.kt b/src/main/kotlin/ru/kontur/kinfra/logging/backend/LoggerBackend.kt index 8f46abc..b32f44d 100644 --- a/src/main/kotlin/ru/kontur/kinfra/logging/backend/LoggerBackend.kt +++ b/src/main/kotlin/ru/kontur/kinfra/logging/backend/LoggerBackend.kt @@ -12,7 +12,7 @@ import ru.kontur.kinfra.logging.LoggingContext * In order to use custom LoggerBackend one should create custom [LoggerFactory] and return * the backend from [LoggerFactory.getLoggerBackend] method. */ -interface LoggerBackend { +public interface LoggerBackend { /** * Determines if a message with a given [level] should be logged. @@ -21,33 +21,33 @@ interface LoggerBackend { * * Implementation may use [LoggingContext.current] to make a decision. */ - fun isEnabled(level: LogLevel): Boolean + public fun isEnabled(level: LogLevel): Boolean /** * Log a message. * * Implementation should not do additional filtering here, but do it in [isEnabled]. */ - fun log(request: LoggingRequest) + public fun log(request: LoggingRequest) /** * Implementation that do nothing. */ - object Nop : LoggerBackend { + public object Nop : LoggerBackend { /** * Returns `false`. */ - override fun isEnabled(level: LogLevel) = false + override fun isEnabled(level: LogLevel): Boolean = false /** * Does nothing. */ - override fun log(request: LoggingRequest) = Unit + override fun log(request: LoggingRequest) {} } // for user extensions - companion object + public companion object } diff --git a/src/main/kotlin/ru/kontur/kinfra/logging/backend/LoggingAdditionalData.kt b/src/main/kotlin/ru/kontur/kinfra/logging/backend/LoggingAdditionalData.kt index 07b452c..2e26837 100644 --- a/src/main/kotlin/ru/kontur/kinfra/logging/backend/LoggingAdditionalData.kt +++ b/src/main/kotlin/ru/kontur/kinfra/logging/backend/LoggingAdditionalData.kt @@ -3,19 +3,19 @@ package ru.kontur.kinfra.logging.backend /** * Additional data of a log event that accompanies a text message. */ -class LoggingAdditionalData( - val throwable: Throwable? = null +public class LoggingAdditionalData( + public val throwable: Throwable? = null ) { - override fun toString() = buildString { + override fun toString(): String = buildString { append("{") throwable?.let { append("throwable=$it") } append("}") } - companion object { + public companion object { - val NONE = LoggingAdditionalData() + public val NONE: LoggingAdditionalData = LoggingAdditionalData() } diff --git a/src/main/kotlin/ru/kontur/kinfra/logging/backend/LoggingRequest.kt b/src/main/kotlin/ru/kontur/kinfra/logging/backend/LoggingRequest.kt index 6245269..f7c025e 100644 --- a/src/main/kotlin/ru/kontur/kinfra/logging/backend/LoggingRequest.kt +++ b/src/main/kotlin/ru/kontur/kinfra/logging/backend/LoggingRequest.kt @@ -15,19 +15,19 @@ import ru.kontur.kinfra.logging.decor.MessageDecor * @property decor a decor containing context data * @property caller information about caller for location aware logging */ -class LoggingRequest( - val level: LogLevel, - val message: String, - val additionalData: LoggingAdditionalData, - val context: LoggingContext, - val decor: MessageDecor, - val caller: CallerInfo +public class LoggingRequest( + public val level: LogLevel, + public val message: String, + public val additionalData: LoggingAdditionalData, + public val context: LoggingContext, + public val decor: MessageDecor, + public val caller: CallerInfo ) { /** * The [message] decorated with [decor]. */ - val decoratedMessage: String + public val decoratedMessage: String get() = decor.decorate(message) override fun toString(): String { diff --git a/src/main/kotlin/ru/kontur/kinfra/logging/backend/slf4j/LoggingRequestMarker.kt b/src/main/kotlin/ru/kontur/kinfra/logging/backend/slf4j/LoggingRequestMarker.kt index 7eec29c..68d3f2d 100644 --- a/src/main/kotlin/ru/kontur/kinfra/logging/backend/slf4j/LoggingRequestMarker.kt +++ b/src/main/kotlin/ru/kontur/kinfra/logging/backend/slf4j/LoggingRequestMarker.kt @@ -9,19 +9,19 @@ import ru.kontur.kinfra.logging.backend.LoggingRequest * * Note that it does not survive serialization. */ -class LoggingRequestMarker private constructor( - val request: LoggingRequest, +public class LoggingRequestMarker private constructor( + public val request: LoggingRequest, private val delegate: Marker ) : Marker by delegate { - constructor(request: LoggingRequest) : this(request, MarkerFactory.getDetachedMarker(NAME)) + public constructor(request: LoggingRequest) : this(request, MarkerFactory.getDetachedMarker(NAME)) // Serialize a plain marker without non-serializable LoggingRequest private fun writeReplace(): Any = delegate - companion object { + public companion object { - const val NAME = "LoggingRequest" + public const val NAME: String = "LoggingRequest" } diff --git a/src/main/kotlin/ru/kontur/kinfra/logging/builtin/BuiltinLoggerFactory.kt b/src/main/kotlin/ru/kontur/kinfra/logging/builtin/BuiltinLoggerFactory.kt index 973ad74..f3955f0 100644 --- a/src/main/kotlin/ru/kontur/kinfra/logging/builtin/BuiltinLoggerFactory.kt +++ b/src/main/kotlin/ru/kontur/kinfra/logging/builtin/BuiltinLoggerFactory.kt @@ -3,9 +3,8 @@ package ru.kontur.kinfra.logging.builtin import ru.kontur.kinfra.logging.LoggerFactory import ru.kontur.kinfra.logging.backend.LoggerBackend import ru.kontur.kinfra.logging.backend.slf4j.Slf4jBackend -import ru.kontur.kinfra.logging.decor.MessageDecor import ru.kontur.kinfra.logging.decor.DefaultMessageDecor -import kotlin.reflect.KClass +import ru.kontur.kinfra.logging.decor.MessageDecor /** * Default logger factory that built into the library. diff --git a/src/main/kotlin/ru/kontur/kinfra/logging/decor/DefaultMessageDecor.kt b/src/main/kotlin/ru/kontur/kinfra/logging/decor/DefaultMessageDecor.kt index dfed3f5..b94aeaf 100644 --- a/src/main/kotlin/ru/kontur/kinfra/logging/decor/DefaultMessageDecor.kt +++ b/src/main/kotlin/ru/kontur/kinfra/logging/decor/DefaultMessageDecor.kt @@ -12,7 +12,7 @@ import ru.kontur.kinfra.logging.LoggingContext * * Context elements with empty values are ignored. */ -class DefaultMessageDecor private constructor( +public class DefaultMessageDecor private constructor( private val prefix: String ) : MessageDecor { @@ -30,10 +30,10 @@ class DefaultMessageDecor private constructor( } } - companion object { + public companion object { @JvmField - val EMPTY = DefaultMessageDecor("") + public val EMPTY: DefaultMessageDecor = DefaultMessageDecor("") } diff --git a/src/main/kotlin/ru/kontur/kinfra/logging/decor/MessageDecor.kt b/src/main/kotlin/ru/kontur/kinfra/logging/decor/MessageDecor.kt index ac39e0f..a2397e2 100644 --- a/src/main/kotlin/ru/kontur/kinfra/logging/decor/MessageDecor.kt +++ b/src/main/kotlin/ru/kontur/kinfra/logging/decor/MessageDecor.kt @@ -10,26 +10,26 @@ import ru.kontur.kinfra.logging.LoggingContext * * Implementation must be immutable. */ -interface MessageDecor { +public interface MessageDecor { /** * Decorate the [message]. */ - fun decorate(message: String): String + public fun decorate(message: String): String /** * Add an element to this decor. */ - fun plusElement(element: LoggingContext.Element): MessageDecor + public fun plusElement(element: LoggingContext.Element): MessageDecor /** * A [MessageDecor] that does not decorate messages in any way. */ - object Nop : MessageDecor { + public object Nop : MessageDecor { - override fun decorate(message: String) = message + override fun decorate(message: String): String = message - override fun plusElement(element: LoggingContext.Element) = this + override fun plusElement(element: LoggingContext.Element): Nop = this }