java - GraalVM 中的 Log4j 给出错误 StatusLogger 无法识别的格式说明符 [d]

标签 java aws-lambda log4j graalvm graalvm-native-image

我有一个用 Java 编写的 AWS Lambda 函数。我想使用自定义 GraalVM 运行时运行 Lambda 函数,如 this blog post 中所做的那样。例如

每当应用程序启动时,我都会收到以下错误:

WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance.
ERROR StatusLogger Unrecognized format specifier [d]
ERROR StatusLogger Unrecognized conversion specifier [d] starting at position 16 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [thread]
ERROR StatusLogger Unrecognized conversion specifier [thread] starting at position 25 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [level]
ERROR StatusLogger Unrecognized conversion specifier [level] starting at position 35 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [logger]
ERROR StatusLogger Unrecognized conversion specifier [logger] starting at position 47 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [msg]
ERROR StatusLogger Unrecognized conversion specifier [msg] starting at position 54 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [n]
ERROR StatusLogger Unrecognized conversion specifier [n] starting at position 56 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [d]
ERROR StatusLogger Unrecognized conversion specifier [d] starting at position 16 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [thread]
ERROR StatusLogger Unrecognized conversion specifier [thread] starting at position 25 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [level]
ERROR StatusLogger Unrecognized conversion specifier [level] starting at position 35 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [logger]
ERROR StatusLogger Unrecognized conversion specifier [logger] starting at position 47 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [msg]
ERROR StatusLogger Unrecognized conversion specifier [msg] starting at position 54 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [n]
ERROR StatusLogger Unrecognized conversion specifier [n] starting at position 56 in conversion pattern.

这就是我的 log4j2.xml 文件的样子

<Configuration status="WARN">
    <Appenders>
        <Lambda name="Lambda">
            <PatternLayout>
                <pattern>%d{yyyy-MM-dd HH:mm:ss} %X{AWSRequestId} %-5p %c{1} - %m%n</pattern>
            </PatternLayout>
        </Lambda>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="Lambda"/>
        </Root>
        <Logger name="software.amazon.awssdk" level="WARN" />
        <Logger name="software.amazon.awssdk.request" level="DEBUG" />
    </Loggers>
</Configuration>

这里的其他类似问题表明这是由于 fatjar 中的 log4j 包冲突造成的。 基于this answer中的建议,我现在使用 ShadowJar 进行转换来构建编译 GraalVM 应用程序的 fatjar。 但是我仍然收到错误。

我的 gradle 构建文件的相关部分如下所示

dependencies {
    implementation platform('software.amazon.awssdk:bom:2.+')
    implementation platform('com.amazonaws:aws-xray-recorder-sdk-bom:2.+')
    implementation 'com.amazonaws:aws-lambda-java-core:1.2.1'
    implementation 'com.amazonaws:aws-lambda-java-events:2.2.9'
    implementation 'com.amazonaws:aws-xray-recorder-sdk-core'
    implementation 'com.amazonaws:aws-xray-recorder-sdk-aws-sdk-core'
    implementation 'com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2'
    implementation 'com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2-instrumentor'

    implementation 'org.apache.logging.log4j:log4j-slf4j18-impl:2.13.2'
    implementation 'com.google.code.gson:gson:2.8.6'

    implementation 'com.formkiq:lambda-runtime-graalvm:1.1'

    implementation project(":aws-java-utilities:utilities")

    runtimeOnly 'com.amazonaws:aws-lambda-java-log4j2:1.2.0'
    runtimeOnly 'mysql:mysql-connector-java:8.0.+'

    // mqttv3 1.1.1 fails to connect for unknown reasons
    testImplementation (group: 'org.eclipse.paho', name: 'org.eclipse.paho.client.mqttv3', version: '1.1.0'){force = true}
    testImplementation 'com.amazonaws:aws-iot-device-sdk-java:1.3.+'
    testImplementation 'org.junit.jupiter:junit-jupiter:5.6.2'
    testImplementation "org.mockito:mockito-core:2.+"
    testImplementation project(":aws-java-utilities:end2endTest-utilities")
    testImplementation 'software.amazon.awssdk:rdsdata'
}

shadowJar {
    archivesBaseName = project.name + '-lambda'
    manifest {
        attributes 'Main-Class': 'com.formkiq.lambda.runtime.graalvm.LambdaRuntime'
    }
    transform(com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer)
}

如果我尝试运行 jar (或具有相同任务但不同主类的一个构建),我会收到此错误。

WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance.
2021-01-16 19:35:23,290 main ERROR Error processing element Lambda ([Appenders: null]): CLASS_NOT_FOUND
2021-01-16 19:35:23,343 main ERROR Unable to locate appender "Lambda" for logger config "root"

我用来构建 GraalVM 应用程序的命令如下所示

docker run --rm -v $(pwd):/working oracle/graalvm-ce:20.1.0-java11 \
    /bin/bash -c "
                    gu install native-image; \
                    native-image --enable-url-protocols=http,https \
                      -H:+AllowIncompleteClasspath \
                      -H:ReflectionConfigurationFiles=/working/src/main/resources/reflect.json \
                      -H:IncludeResourceBundles=com.mysql.cj.LocalizedErrorMessages \
                      -H:IncludeResources=.\*.properties \
                      -H:IncludeResources=.\*.xml \
                      -H:+ReportUnsupportedElementsAtRuntime -J-Xmx5G --no-server -jar \"/working/build/libs/$1-lambda-all.jar\";`

gradle dependency 告诉我,所有对 log4j 的引用都使用相同的版本,例如:

...
+--- org.apache.logging.log4j:log4j-slf4j18-impl:2.13.2
|    +--- org.slf4j:slf4j-api:1.8.0-beta4
|    +--- org.apache.logging.log4j:log4j-api:2.13.2
|    \--- org.apache.logging.log4j:log4j-core:2.13.2
|         \--- org.apache.logging.log4j:log4j-api:2.13.2
...

我看到有关此主题的一些问题提到这是由于 Log4j2Plugins.dat 文件冲突造成的。我可以在我的依赖项中看到我有两个这样的文件。 一份位于 com.amazonaws:aws-lambda-java-log4j2:1.2.0 中,一份位于 org.apache.logging.log4j:log4j-api:2.13.2 中。根据我之前链接的答案,我的 gradle 构建中的转换应该解决这个问题,但我不知道如何验证这是否属实。

我一整天都在为这个问题绞尽脑汁,而且我对如何让日志记录正常工作感到非常困惑。

任何帮助我前进的帮助将不胜感激。

最佳答案

我也遇到了和你一样的问题。经过一番挖掘,我偶然发现了这个 jira 和 github 问题:

https://issues.apache.org/jira/browse/LOG4J2-2604

https://github.com/oracle/graal/issues/808

使用 GraalVM 构建时,您必须指定要捆绑的资源。应用 github 问题中指定的 resources-config.json 设置对我有用(但是,reflect-config.json 不起作用)。

工作反射配置可以在另一个 github 问题中找到 https://github.com/oracle/graal/issues/2008#issuecomment-777858227

关于java - GraalVM 中的 Log4j 给出错误 StatusLogger 无法识别的格式说明符 [d],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65752742/

相关文章:

java - 如何使用 SQS 事件对 aws lambda 进行单元测试

python - 无法导入模块 'lambda_function' : No module named '_speech_py_impl'

Java Swing - 从 CLick 获取 X,Y

Java 大规模多框架实例问题

c# - 如何轻松地为多个 Lambda 函数添​​加环境变量?

java - 虚拟 log4j 配置(用于测试)

java - 线程 "main"java.lang.NoClassDefFoundError : org/slf4j/ILoggerFactory 中的异常

java - Log4j 每次都打印到控制台

java - JAXB 编码为 StringWriter : Is it necassary to declare the string encoding (e. g。 UTF-8)?

java - Java是如何实现String池化的?