Skip to content

Support logback 1.6.x in the logback toolkit layouts - #837

Merged
wu-sheng merged 2 commits into
mainfrom
fix/logback-1.6-converter-registry
Oct 7, 2026
Merged

wu-sheng merged 2 commits into
mainfrom
fix/logback-1.6-converter-registry

Conversation

@wu-sheng

@wu-sheng wu-sheng commented Oct 6, 2026 •

Copy link
Copy Markdown
Member

Fix apache/skywalking#14120: the logback toolkit layouts fail on logback 1.6.x

  • Add a unit test to verify that the fix works.
  • Explain briefly why the bug exists and how to fix it.

Why the bug exists. TraceIdPatternLogbackLayout and TraceIdMDCPatternLogbackLayout registered %tid/%sw_ctx and %X/%mdc by writing to the static PatternLayout.defaultConverterMap in a static initializer. Logback 1.6.0 removed that deprecated field (release notes), so the layouts fail with NoSuchFieldError: defaultConverterMap. The module compiled against logback 1.2.3, so the build never noticed.

How it is fixed. A shared AbstractTraceIdPatternLogbackLayout registers the conversion words in the logging context's conversion rule registry (CoreConstants.PATTERN_RULE_REGISTRY) when the layout starts. The registry is replaced with an updated copy, never modified in place, and rules that already exist, such as user-defined <conversionRule>s, keep precedence.

  • Concurrency: layouts starting concurrently may be reading the registry, and they only ever see a map that no longer changes. The context monitor is held only for the copy, so concurrent layouts keep each other's words, even across class loaders.
  • No lock during start: the monitor is released before logback creates and starts the converters.
  • No needless copies: nothing is copied once the words are registered.
  • Logback 1.2.x to 1.5.12 read class names from this registry directly, 1.5.14+ adapts them into converter suppliers, and 1.6.5 still does. One toolkit artifact keeps supporting logback 1.2.x to 1.6.x, with no reflection.
  • Logback 1.5.13 is not supported. It changed the registry to hold suppliers, which logback reverted in 1.5.14 (qos-ch/logback#885, raised from Spring Boot). The doc explains this.
  • Existing logback.xml configurations keep working. The module now compiles against logback 1.6.5, so a future API removal fails the build instead of a user's application.

Behavior changes

  • Per-context registration. The words are now registered per logging context, when a layout starts, not JVM-wide when the class loads. Before, %tid also worked by chance in other encoders, such as a plain <encoder><pattern>, depending on configuration order and reloads. The doc and CHANGES now tell users to declare <conversionRule>s for that, which works on every logback version and also with older toolkit releases on logback 1.6.
  • Subclasses. A subclass of the layouts that remaps a word by overriding getDefaultConverterMap() no longer takes precedence on logback ≤1.5.12. Logback 1.6 removed that method, so subclasses now use the registerConverters(Map) hook.
  • Concurrent configuration on old logback. On logback ≤1.5.12, a <conversionRule> registered while a toolkit layout starts in another thread can be lost. From 1.5.14, logback keeps XML rules in a separate registry, so this cannot happen there. It is documented in the class javadoc.
  • Not a change: a layout started without setContext() already failed with a NullPointerException; it now reports an error and stays stopped.

Tests

  • LogbackVersionCompatibilityTest renders both layouts against logback 1.2.13, 1.3.16, 1.4.14, 1.5.12, 1.5.14, 1.5.38 and 1.6.5, each in an isolated class loader. With the old layouts it fails only on 1.6.5, with the reported NoSuchFieldError.

  • TraceIdPatternLogbackLayoutTest covers:

    • user rule precedence;
    • replacing the registry rather than modifying it;
    • two layouts in one context;
    • converters starting without the context monitor held;
    • the missing-context case.
  • New plugin test apm-toolkit-logback-scenario, the first one for the logback toolkit and its agent activation, in the JDK 17 workflow. It runs logback 1.2.13, 1.3.16, 1.4.14 and 1.5.38 with the released toolkit 9.7.0, continuing a fixed upstream trace. It asserts the exact trace ID and SkyWalking context rendered by both layouts, including behind an AsyncAppender, through the gRPC log reporter.

    • Locally, an agent without the async instrumentation fails it, and so does an agent without the converter activations.
    • Logback 1.6.x can be added once 9.8.0 is released (1.6.5,apm-toolkit.version=9.8.0). Locally, the scenario fails on 1.6.5 with 9.7.0 and passes on all five versions with this change.
  • If this pull request closes/resolves/fixes an existing issue, replace the issue number. Closes [Bug] Logback plugin not compatible with logback >= 1.6.0 skywalking#14120.

  • Update the CHANGES log.

Logback 1.6.0 removed PatternLayout.defaultConverterMap, which
TraceIdPatternLogbackLayout and TraceIdMDCPatternLogbackLayout wrote their
conversion words to in a static initializer, so both failed with
NoSuchFieldError: defaultConverterMap (apache/skywalking#14120).

The layouts now register their conversion words in the logging context's
conversion rule registry (CoreConstants.PATTERN_RULE_REGISTRY) when they
start, updating it in place as logback does for <conversionRule>. Logback
1.2.x to 1.6.x all read class names from that registry, so the same toolkit
artifact keeps working on older logback. Logback 1.5.13 is not supported
because of an upstream regression fixed in 1.5.14 (qos-ch/logback#885).

The toolkit now compiles against logback 1.6.5, so an API removal fails the
build. LogbackVersionCompatibilityTest renders both layouts against logback
1.2.13, 1.3.16, 1.4.14, 1.5.12, 1.5.14, 1.5.38 and 1.6.5, each loaded in an
isolated class loader.

Add apm-toolkit-logback-scenario, the first plugin test of the logback
toolkit and its agent activation. It runs logback 1.2.x to 1.5.x with the
released toolkit and checks the trace ID and SkyWalking context rendered by
both layouts, including behind an AsyncAppender, through the gRPC log
reporter.
@wu-sheng wu-sheng added this to the 9.8.0 milestone Oct 6, 2026
Register the SkyWalking conversion words by replacing the context's
conversion rule registry with an updated copy, under the context monitor
held only for the copy. Layouts starting concurrently, from any class
loader, keep each other's words, and logback reads a registry that is
never modified afterwards, so no lock is held while logback creates and
starts the converters. Nothing is copied once the words are registered.

On logback before 1.5.14, which also writes <conversionRule>s to this
registry, a rule logback registers at the same time as a layout starts in
another thread may be lost; this is documented.
@wu-sheng
wu-sheng merged commit fcbe4fe into main Oct 7, 2026
232 of 256 checks passed
@wu-sheng
wu-sheng deleted the fix/logback-1.6-converter-registry branch October 7, 2026 00:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Logback plugin not compatible with logback >= 1.6.0

2 participants