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!
plugins {
id("dev.jacomet.logging-capabilities") version "0.9.0"
}
Have a look at the documentation on the plugin portal for alternate or DSL specific syntax.
Gradle version | Available feature |
---|---|
Gradle 4.7+ |
The detection part is available |
Gradle 6.0+ |
The configuration part is available |
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 |
---|---|---|
|
|
Represents an Slf4J binding |
|
|
Represents the Slf4J / Log4J 2 relationship: which one delegates to the other |
|
|
Represents the Slf4J / Log4J 1.2 relationship: either Slf4J intercepts or binds to Log4J |
|
|
Represents the available Log4J implementation: native, with Slf4J or with Log4J 2 |
|
|
Represents the Slf4J / |
|
|
Represents JUL replacement: either with Slf4J or with Log4J 2 |
|
|
Represents Apache Commons Logging implementation: native or Slf4J |
|
|
Represents the Slf4J / Apache Commons Logging relationship: either Slf4J intercepts or binds to |
|
|
Represents the Slf4J or Log4J 2 interception of |
💡
|
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.
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.
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 |
---|---|---|
|
This will configure all capabilities to resolve in favour of LOGBack and route all alternative logging solutions through Slf4J. |
|
|
This will configure all capabilities to resolve in favour of Log4J 2 and route all alternative logging solutions through Log4J 2. |
|
|
This will configure all capabilities to resolve in favour of Slf4J simple and route all alternative logging solutions through Slf4J. |
|
💡
|
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 |
---|---|---|
|
Value must be an Slf4J binding implementation known by the plugin: |
Configures the provided Slf4J binding for selection, configuring related capabilities if needed |
|
A dependency configuration name, that |
Configures the provided Slf4J binding for selection, configuring related capabilities if needed, only for the provided dependency configuration |
|
Value must be a Log4J 1.2 implementation known by the plugin: |
Configures the provided Log4J 1.2 implementation for selection, configuring related capabilities if needed |
|
A dependency configuration name, that |
Configures the provided Log4J 1.2 implementation for selection, configuring related capabilities if needed, only for the provided dependency configuration |
|
Value must be a |
Configures the provided JUL integration of binding for selection, configuring related capabilities if needed |
|
A dependency configuration name, that |
Configures the provided JUL integration for selection, configuring related capabilities if needed, only for the provided dependency configuration |
|
Value must be a Apache Commons Logging interceptor or binding known by the plugin: |
Configures the provided commons logging interceptor or binding for selection, configuring related capabilities if needed |
|
A dependency configuration name, that |
Configures the provided commons logging interceptor or binding for selection, configuring related capabilities if needed, only for the provided dependency configuration |
|
Value must be a Log4J 2 module for Slf4J interaction known by the plugin: |
Configures the Log4J 2 / Slf4J integration, configuring related capabilities if needed |
|
A dependency configuration name, that |
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 .
|