Releases: hermannm/devlog-kotlin
Releases · hermannm/devlog-kotlin
v0.8.0
- Attach logging context to exceptions when they would escape the scope of
withLoggingContext
- Previously, when an exception was thrown inside a logging context scope, one would lose that logging context if the exception was logged further up the stack (which is typical). But unexpected exceptions is when we need this context the most! So now,
withLoggingContext
attaches its context fields to any encountered exception before re-throwing it up the stack, andLogger
includes these fields when the exception is logged.
- Previously, when an exception was thrown inside a logging context scope, one would lose that logging context if the exception was logged further up the stack (which is typical). But unexpected exceptions is when we need this context the most! So now,
- Allow log fields to overwrite logging context fields for a single log
- Previously, duplicate keys could appear in the log output if the same key was used on a single-log field as on a logging context field.
- Use Kotlin Contracts in
withLoggingContext
- This gives users more flexibility in what they can do in the given lambda.
- Breaking: Rename
ExceptionWithLogFields
toExceptionWithLoggingContext
, andHasLogFields
toHasLoggingContext
- This makes the naming of these classes more consistent with the
withLoggingContext
function.
- This makes the naming of these classes more consistent with the
- Breaking:
ExceptionWithLoggingContext
no longer implements theHasLoggingContext
interface- When it implemented this interface, it needlessly had to expose its
logFields
property, which should be an implementation detail.
- When it implemented this interface, it needlessly had to expose its
- Breaking: Rename
getLoggingContext
togetCopyOfLoggingContext
, change its return value to an opaqueLoggingContext
wrapper class, and add newwithLoggingContext
overload that accepts this newLoggingContext
type- This new name is more explicit about what the function does, and also avoids competing with
getLogger
for autocomplete. - The
LoggingContext
wrapper class enables some performance optimizations, since we no longer need to turn the logging context into aList
.
- This new name is more explicit about what the function does, and also avoids competing with
- Breaking: Use
Collection
instead ofList
in public APIs that accept or provide multiple log fieldsCollection
is a more flexible interface thanList
.
- Breaking: Change return type of
rawJson
function fromkotlinx.serialization.json.JsonElement
to customRawJson
wrapper type- This reduces the coupling of the library's API to
kotlinx.serialization
, while keeping the same serialization behavior. In the future, we may want to support e.g. Jackson serialization on the JVM, so this gives us more flexibility.
- This reduces the coupling of the library's API to
- Change how JSON fields in
withLoggingContext
are handled, to avoid internal implementation details leaking out- In the previous implementation, a key suffix was used to identify logging context fields with JSON values. But in certain log output configurations, this implementation detail could leak out. This implementation has now been reworked, both to avoid leaking implementation details and also to improve performance (by avoiding allocations).
- Minimize the amount of code in
inline
functions- Having a lot of code in
inline
functions increases code size (since that code is replicated wherever theinline
function is called), which can negatively affect perforamnce. The library now only includes the most necessary code ininline
blocks, delegating to normal functions where possible.
- Having a lot of code in
v0.7.0
v0.6.1
v0.6.0
- Change the
getLogger {}
function using a lambda parameter to a zero-argumentgetLogger()
function- This uses
MethodHandles.lookup().lookupClass()
, as recommended by SLF4J
- This uses
- Mark the
buildLog
lambda parameter on logger methods ascrossinline
- This prevents users from accidentally doing a non-local return inside the lambda, which would drop the log
- Improve documentation
v0.5.0
- Restructure library for Kotlin Multiplatform
- JVM is still the only supported platform as of now, but this lays the groundwork for supporting more platforms in the future
- Add another
getLogger
overload that takes aKClass
- Allow using
field
function with non-reified generics when passing a custom serializer - Rename
WithLogFields
interface to the more intuitiveHasLogFields
- Add JVM-specific optimization annotations where appropriate, to reduce overhead
- Improve documentation
- Host documentation on https://devlog-kotlin.hermannm.dev
v0.4.0
- Take
cause
exception as a normal argument onLogger
methods, instead of as a property onLogBuilder
- This makes the normal case of logging a message along with an exception more concise
- Use SLF4J's MDC for logging context instead of a custom thread-local
- This allows our logging context to also apply to logs by libraries that use SLF4J
- A new
LoggingContextJsonFieldWriter
is provided for Logback to enable JSON fields in MDC
- Rename
LogBuilder
methods to be more concise and intuitiveaddField
andaddRawJsonField
are now justfield
andrawJsonField
, like their top-level counterpartsaddPreconstructedField
is nowaddField
- Add
LogBuilder.addFields
method to make it easier to pass a list of pre-constructed fields - Add
ExecutorService.inheritLoggingContext
extension function to make it easier to inherit logging context in tasks submitted to anExecutorService
- Add more constructor overloads to
ExceptionWithLogFields
, to allow passing log fields with less boilerplate - Fix edge case of unquoted strings being allowed by
rawJsonField
- Improve documentation
v0.3.0
- Make library compatible with any SLF4J logger implementation (not just Logback)
- The library is still optimized for Logback, but it's now an optional dependency
- The dependency on
logstash-logback-encoder
has been dropped (we now use SLF4J'sKeyValuePair
instead of theSingleFieldAppendingMarker
fromlogstash-logback-encoder
)
- Replace
Logger
constructors withgetLogger
functions- Since there are so many classes named
Logger
in various libraries, callinggetLogger {}
instead ofLogger {}
makes it easier to auto-complete in your IDE
- Since there are so many classes named
- Add
getLoggingContext
function to allow passing logging context between threads - Improve performance of
withLoggingContext
by reducing array copies - Improve test coverage
- We now run integration tests for various SLF4J logger implementations, to make sure that the library works for implementations other than Logback
v0.2.1
- Allow setting
LogBuilder.cause
tonull
- This is useful when you have a cause exception that may or may not be
null
- This is useful when you have a cause exception that may or may not be
- Fix edge case in
LogBuilder.cause
setter that could throw an exception - Remove needlessly restrictive
jvmTarget
setting from Kotlin compiler config