Skip to content

ljacomet/logging-capabilities

Repository files navigation

Logging Capabilities Gradle Plugin

⚠️
This plugin has been merged with the GradleX jvm-dependency-conflict-resolution plugin. Please update to that other plugin and report issues there. I will follow up on the existing issues here and move the relevant ones to the new plugin.

Ever seen this infamous Slf4J warning?

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:.../slf4j-log4j12-1.7.29.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:.../logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]

Ever wondered how to make sure all your dependencies' logging ends up in your Log4J 2 configuration?

Then this plugin is for you!

It is built on the Gradle capabilities feature, to detect and optionally select a Java logger implementation so that it is enforced at build time!

Plugin application and compatibility

plugins {
  id("dev.jacomet.logging-capabilities") version "0.11.0"
}

Have a look at the documentation on the plugin portal for alternate or DSL specific syntax.

Gradle version Available feature

Gradle 5.0+

The detection part is available

Gradle 6.0+

The configuration part is available

Gradle 8.0+

All features available, requires version 0.11.0 or above of the plugin

Detection of invalid logging configurations

Upon application, this plugin defines a set of component metadata rules that add capabilities to relevant logging related dependencies. The added capabilities and impacted modules can be found in the table below:

Capability Impacted modules Comment

slf4j-impl

org.slf4j:slf4j-simple, org.slf4j:slf4j-log4j12, org.slf4j:slf4j-jcl, org.slf4j:slf4j-jdk14, ch.qos.logback:logback-classic, org.apache.logging.log4j:log4j-slf4j-impl, org.apache.logging.log4j:log4j-slf4j2-impl

Represents an Slf4J binding

log4j2-impl

org.apache.logging.log4j:log4j-slf4j-impl, org.apache.logging.log4j:log4j-slf4j2-impl, org.apache.logging.log4j:log4j-core

Represents the native Log4J 2 implementation or delegation to Slf4J

log4j2-vs-slf4j

org.apache.logging.log4j:log4j-slf4j-impl, org.apache.logging.log4j:log4j-to-slf4j

Represents the Slf4J / Log4J 2 relationship: which one delegates to the other

slf4j-vs-log4j

org.slf4j:log4j-over-slf4j, org.slf4j:slf4j-log4j12

Represents the Slf4J / Log4J 1.2 relationship: either Slf4J intercepts or binds to Log4J

slf4j-vs-log4j2-log4j

org.slf4j:log4j-over-slf4j, org.apache.logging.log4j:log4j-1.2-api, log4j:log4j

Represents the available Log4J implementation: native, with Slf4J or with Log4J 2

slf4j-vs-jul

org.slf4j:jul-to-slf4j, org.slf4j:slf4j-jdk14

Represents the Slf4J / java.util.logging relationship: either Slf4 intercepts or binds to JUL

slf4j-vs-log4j2-jul

org.slf4j:jul-to-slf4j, org.apache.logging.log4j:log4j-jul

Represents JUL replacement: either with Slf4J or with Log4J 2

commons-logging-impl

commons-logging:commons-logging, org.slf4j:jcl-over-slf4j, org.springframework:spring-jcl

Represents Apache Commons Logging implementation: native or Slf4J

slf4j-vs-jcl

org.slf4j:jcl-over-slf4j, org.slf4j:slf4j-jcl

Represents the Slf4J / Apache Commons Logging relationship: either Slf4J intercepts or binds to commons-logging

slf4j-vs-log4j2-jcl

org.slf4j:jcl-over-slf4j, org.apache.logging.log4j:log4j-jcl

Represents the Slf4J or Log4J 2 interception of commons-logging

💡
All capabilities are in the group dev.jacomet.logging

With the set of capabilities defined above, all configuration resolutions in Gradle will fail if conflicting modules are found in the graph.

Alignment of logging libraries

In addition to the capability setting and conflict detection, the plugin also registers alignment rules for Slf4J and Log4J 2 modules.

Due to a bug in Gradle versions [5.2, 6.2[, alignment is disabled by default for these versions. Users with Gradle [6.0, 6.2[ can opt back in with loggingCapabilities.enableAlignment(). Note that enabling alignment for these versions may cause some capabilities conflict to remain undetected. See this issue for details.

Expressing preference over a logging solution

The plugin also contributes a project extension that allows to configure which logging solution to use in a declarative fashion. This solution is based on APIs introduced in Gradle 6.0.

The extension is accessed as follows:

// Assuming the plugin has been applied
loggingCapabilities {
    // Configuration goes here
}
💡
The different configuration options documented below do not add dependencies. Make sure to have the expected dependency in your graph, either as a direct or transitive one.

The plugin first provides a number of high-level, one stop solutions, for selecting a logging solution:

Method Documentation Required dependency

enforceLogback()
enforceLogback(String configurationName)

This will configure all capabilities to resolve in favour of LOGBack and route all alternative logging solutions through Slf4J.

ch.qos.logback:logback-classic

enforceLog4J2()
enforceLog4J2(String configurationName)

This will configure all capabilities to resolve in favour of Log4J 2 and route all alternative logging solutions through Log4J 2.

org.apache.logging.log4j:log4j-slf4j-impl

enforceSlf4JSimple()
enforceSlf4JSimple(String configurationName)

This will configure all capabilities to resolve in favour of Slf4J simple and route all alternative logging solutions through Slf4J.

org.slf4j:slf4j-simple

💡
The method without parameter will apply the setup to all dependency configuration, while the other one will limit the setup to the specified dependency configuration.

If you want a finer grained control, the plugin provides lower level entry points for solving the different logging capability conflicts:

Method Accepted parameter values Documentation

selectSlf4JBinding(Object notation)

Value must be an Slf4J binding implementation known by the plugin: org.slf4j:slf4j-simple, org.slf4j:slf4j-log4j12, org.slf4j:slf4j-jcl, org.slf4j:slf4j-jdk14, ch.qos.logback:logback-classic or org.apache.logging.log4j:log4j-slf4j-impl

Configures the provided Slf4J binding for selection, configuring related capabilities if needed

selectSlf4JBinding(String configurationName, Object notation)

A dependency configuration name, that canBeResolved=true
A notation as above

Configures the provided Slf4J binding for selection, configuring related capabilities if needed, only for the provided dependency configuration

selectLog4J12Implementation(Object notation)

Value must be a Log4J 1.2 implementation known by the plugin: org.slf4j:log4j-over-slf4j, org.apache.logging.log4j:log4j-1.2-api, log4:log4j or org.slf4j:slf4j-log4j12

Configures the provided Log4J 1.2 implementation for selection, configuring related capabilities if needed

selectLog4J12Implementation(String configurationName, Object notation)

A dependency configuration name, that canBeResolved=true
A notation as above

Configures the provided Log4J 1.2 implementation for selection, configuring related capabilities if needed, only for the provided dependency configuration

selectJulDelegation(Object notation)

Value must be a java.util.logging interceptor or binding known by the plugin: org.slf4j:jul-to-slf4j, org.slf4j:slf4j-jdk14 or org.apache.logging.log4j:log4j-jul

Configures the provided JUL integration of binding for selection, configuring related capabilities if needed

selectJulDelegation(String configurationName, Object notation)

A dependency configuration name, that canBeResolved=true
A notation as above

Configures the provided JUL integration for selection, configuring related capabilities if needed, only for the provided dependency configuration

selectJCLImplementation(Object notation)

Value must be a Apache Commons Logging interceptor or binding known by the plugin: org.slf4j:jcl-over-slf4j, commons-logging:commons-logging, org.slf4j:slf4j-jcl or org.apache.logging.log4j:log4j-jcl

Configures the provided commons logging interceptor or binding for selection, configuring related capabilities if needed

selectJCLImplementation(String configurationName, Object notation)

A dependency configuration name, that canBeResolved=true
A notation as above

Configures the provided commons logging interceptor or binding for selection, configuring related capabilities if needed, only for the provided dependency configuration

selectSlf4JLog4J2Interaction(Object notation)

Value must be a Log4J 2 module for Slf4J interaction known by the plugin: org.apache.logging.log4j:log4j-to-slf4j or org.apache.logging.log4j:log4j-slf4j-impl

Configures the Log4J 2 / Slf4J integration, configuring related capabilities if needed

selectSlf4JLog4J2Interaction(Sting configurationName, Object notation)

A dependency configuration name, that canBeResolved=true
A notation as above

Configures the Log4J 2 / Slf4J integration, configuring related capabilities if needed, only for the provided dependency configuration

💡
Notations above are those accepted by DependencyHandler.create(notation) in Gradle that resolves to an ExternalDependency. Most often this is a group:name:version String.

Building and reporting issues

You will need a JDK 8+ to build this project.

⚠️
This build is configured to publish build scans always.

Use the GitHub issue tracker for reporting bugs and feature requests.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •