Skip to content

Issue with logstash-logback-encoder 8.1+ and shaded Logback classes (ICCE) #1113

@stefan-so-elo

Description

@stefan-so-elo

Hello.

When using logstash-logback-encoder starting from version 8.1, the following error occurs at runtime:

Exception in thread "main" java.lang.IncompatibleClassChangeError: Unexpected return type found for PatternLayoutBase.getInstanceConverterMap(), logback-core dependency version is not compatible
    at org.apache.juli.logging.net.logstash.logback.pattern.PatternLayoutCompatibilityUtil.registerConverter(PatternLayoutCompatibilityUtil.java:78)

In our setup, we are using https://github.com/tomcat-slf4j-logback/tomcat10-slf4j-logback, which shades Logback using the Maven Shade Plugin with the following relocation:

<relocation>
    <pattern>ch.qos.logback</pattern>
    <shadedPattern>org.apache.juli.logging.ch.qos.logback</shadedPattern>
</relocation>

Due to this relocation from ch.qos.logback to org.apache.juli.logging.ch.qos.logback, the IncompatibleClassChangeError is triggered.

The root cause appears to be an explicit type check in logstash-logback-encoder that assumes the original Logback package name. In particular, there is a direct reference to:

ch.qos.logback.core.pattern.DynamicConverter

in the following code:

if (valueType.getTypeName().equals("java.lang.String")) {
    /*
     * In logback <= 1.5.12, getInstanceConverterMap() is a Map<String, String>.
     *     key = converter name
     *     value = name of converter class
     */
    putUnchecked(layout.getInstanceConverterMap(), converterName, converterClass.getName());
} else if (valueType.getTypeName().equals("java.util.function.Supplier<ch.qos.logback.core.pattern.DynamicConverter>")) {
    /*
     * In logback >= 1.5.13, getInstanceConverterMap() is a Map<String, Supplier<DynamicConverter>.
     *     key = converter name
     *     value = supplier of converter instances
     *
     * Related issues:
     *     https://github.com/qos-ch/logback/issues/803
     *     https://github.com/qos-ch/logback/issues/931
     *     https://github.com/qos-ch/logback/issues/932
     */
    putUnchecked(layout.getInstanceConverterMap(), converterName, converterSupplier);
} else {
    throw new IncompatibleClassChangeError(
            "Unexpected return type found for PatternLayoutBase.getInstanceConverterMap(), logback-core dependency version is not compatible");
}

Because the class is shaded, this check fails and leads to the ICCE at runtime.

Questions:

Is there a way to make this compatibility check shading-tolerant, for example by avoiding direct class references?

Alternatively, are there recommended approaches to resolve this issue when Logback must be shaded (as required by tomcat10-slf4j-logback)?

Any guidance or suggestions would be greatly appreciated.

Thank you very much.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions