Log4j Kotlin API provides a Kotlin-friendly interface to log against the Log4j API. The minimum requirements are Java 8 and Kotlin 1.6.21.

This is just a logging API. Your application still needs to have a logging backend (e.g., Log4j) configured.

Dependencies

You need to have the org.apache.logging.log4j:log4j-api-kotlin dependency in your classpath:

<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-api-kotlin</artifactId>
  <version>1.4.0</version>
</dependency>

Java module name and OSGi Bundle-SymbolicName are set to org.apache.logging.log4j.api.kotlin.

Usage

You can start using the wrapper by extending from the provided Logging interface:

import org.apache.logging.log4j.kotlin.Logging

class MyClass: BaseClass, Logging {

  fun doStuff() {
    logger.info("Doing stuff")
  }

  fun doStuffWithUser(user: User) {
    logger.info { "Doing stuff with ${user.name}." }
  }

}

The Logging interface can also be mixed into object declarations, including companions. This is generally preferable over the previous approach as there is a single logger created for every instance of the class.

import org.apache.logging.log4j.kotlin.Logging

class MyClass: BaseClass {

  companion object : Logging

  // ...

}

Alternatively, a more traditional style can be used to instantiate a logger instance:

import org.apache.logging.log4j.kotlin

class MyClass: BaseClass {

  val logger = logger()

  // ...

}

The function logger() is an extension function on the Any type (or more specifically, any type T that extends Any).

Beginning in version 1.3.0, an extension property is also available on classes:

import org.apache.logging.log4j.kotlin.logger

class MyClass: BaseClass {

  fun doStuff() {
    logger.info("Hello, world!")
  }

}

Also added in version 1.3.0, the ThreadContext API has two facade objects provided: ContextMap and ContextStack.

import org.apache.logging.log4j.kotlin.ContextMap
import org.apache.logging.log4j.kotlin.ContextStack

ContextMap["key"] = "value"
assert(ContextMap["key"] == "value")
assert("key" in ContextMap)

ContextMap += "anotherKey" to "anotherValue"
ContextMap -= "key"

ContextStack.push("message")
assert(!ContextStack.empty)
assert(ContextStack.depth == 1)
val message = ContextStack.peek()
assert(message == ContextStack.pop())
assert(ContextStack.empty)

Parameter substitution

Unlike Java, Kotlin provides native functionality for string templates. However, using a string template still incurs the message construction cost if the logger level is not enabled. To avoid this, prefer passing a lambda which won’t be evaluated until necessary:

logger.debug { "Logging in user ${user.name} with birthday ${user.calcBirthday()}" }

Logger names

Most logging implementations use a hierarchical scheme for matching logger names with logging configuration.

In this scheme the logger name hierarchy is represented by . (dot) characters in the logger name, in a fashion very similar to the hierarchy used for Java/Kotlin package names. The Logger property added by the Logging interface follows this convention: the interface ensures the Logger is automatically named according to the class it is being used in.

The value returned when calling the logger() extension method depends on the receiver of the extension. When called within an object, the receiver is this and therefore the logger will again be named according to the class it is being used in. However, a logger named via another class can be obtained as well:

import org.apache.logging.log4j.kotlin

class MyClass: BaseClass {

  val logger = SomeOtherClass.logger()

  // ...

}

Explicitly Named Loggers

An explicitly-named logger may be obtained via the logger function that takes a name parameter:

import org.apache.logging.log4j.kotlin

class MyClass: BaseClass {

  val logger = logger("MyCustomLoggerName")

  // ...

}

This is also needed in scopes that do not have a this object, such as top-level functions.

Development

Log4j Kotlin API uses GitHub for source code management.

The project requires a Java compiler matching the [17,18) range and targets Java 8 and Kotlin 1.6.21.

You can build and verify sources using:

./mvnw verify

You can build and view the website as follows:

./mvnw -N site
python -m http.server -d target/site

Distribution

In accordance with the Apache Software Foundation’s release distribution policy and creation process, project artifacts are officially accessible from the following locations:

See the release instructions for details.

CycloneDX Software Bill of Materials (SBOM)

Starting with version 1.4.0, Log4j Kotlin API distributes CyclenoDX Software Bill of Materials (SBOM) along with each deployed artifact. This is streamlined by logging-parent, see its website for details.

Support

Please keep in mind that this project is intended for internal usage only. You can use GitHub Issues for feature requests and bug reports – not questions! See the Log4j support policy for details.

Security

If you have encountered an unlisted security vulnerability or other unexpected behaviour that has security impact, please report them privately to the Log4j security mailing list. See the Log4j Security page for further details.

Release Notes

1.4.0

Release date

2023-12-18

This minor release fixes incorrect coroutine context map and stack.

Added

  • Started generating CycloneDX SBOM with the recent update of logging-parent to version 10.2.0

Changed

  • Coroutine context is not cleared properly, only appended to (54)

  • Update org.apache.logging:logging-parent to version 10.2.0

  • Update org.apache.logging.log4j:log4j-bom to version 2.22.0 (52)

  • Update org.apache.logging:logging-parent to version 10.4.0 (53)

  • Update org.codehaus.mojo:build-helper-maven-plugin to version 3.5.0 (51)

  • Update org.codehaus.mojo:exec-maven-plugin to version 3.1.1 (50)

  • Update org.junit:junit-bom to version 5.10.1 (49)

1.3.0

Release date

2023-10-03

This minor release bumps the Kotlin baseline to 1.6.21 and contains various small improvements.

Added

  • Added an extension property for storing a cached logger (29)

  • Added facade APIs for manipulating the context map and stack (30)

  • Added missing catching and throwing API methods in KotlinLogger (32)

  • Added JPMS support and used org.apache.logging.log4j.api.kotlin for the module name (identical to OSGi Bundle-SymbolicName) of the log4j-api-kotlin artifact

Changed

  • Updated Log4j dependency to 2.20.0

  • Bumped logging-parent version to 10.1.1 and overhauled the entire project infrastructure to take advantage of its goodies (37)

  • Renamed OSGi Bundle-SymbolicName from org.apache.logging.log4j.kotlin to org.apache.logging.log4j.api.kotlin

  • Migrated tests to JUnit 5

  • Bumped Kotlin and Kotlin Extensions baseline to 1.6.21 and 1.6.4 respectively

  • Skipped deploying log4j-api-kotlin-benchmark and log4j-api-kotlin-sample modules

Removed

  • Stopped exporting KDoc to HTML

1.2.0

Release date

2021-12-20

This is the 3rd minor release of the project.

Changed

  • Update Kotlin baseline version to 1.3.72 (LOG4J2-3218)

1.1.0

Release date

2021-08-28

This is the 2nd minor release of the project.

Added

  • Support MDCs with Kotlin coroutines (LOG4J2-2433)

  • Support suspend functions in supplier lambdas (LOG4J2-2518)

Changed

  • Update Kotlin baseline version to 1.3.72 (LOG4J2-2843)

1.0.0

Release date

2018-11-03

This is the first major release of the project.

Added

Changed

Release instructions

Log4j Kotlin API employs the CI/CD foundation provided by the logging-parent. You can simply use its release instructions.

License

Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See NOTICE.txt distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0.

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.