当前位置: 首页 > 知识库问答 >
问题:

将自定义域添加到log4j json布局打破了spring日志结构

汤承允
2023-03-14

我有一个使用Log4j2(带有Slf4j)的Spring Boot(2.2.6)应用程序。Log4j被配置为使用json布局,最后我希望在DataDog中获取日志。因此,'service name'作为JSON中的一个字段非常重要。

现在,根据log4j文档(https://logging.apache.org/log4j/2.x/manual/layouts.html#JSONLayout),可以添加一个带有'KeyValuePair'标记的自定义字段,这样就可以工作了。不幸的是,这打破了Spring原木的正常结构。

log4j2.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Appenders>
        <!-- Write logs to stdout, JSON, one line per log event -->
        <Console name="Console" target="SYSTEM_OUT">
            <JSONLayout compact="true" eventEol="true" includeStacktrace="true" locationInfo="true"
                        stacktraceAsString="true" properties="true">
      <KeyValuePair key="serviceName" value="$${env:APPLICATION_NAME:-local}-sidecar"/> <!-- fine w/o this line -->
</JSONLayout>
        </Console>
    </Appenders>
    <Loggers>
        <Logger name="my.service" level="debug" additivity="false">
            <AppenderRef ref="Console"/>
        </Logger>
        <Logger name="org.springframework" level="info" additivity="false">
            <AppenderRef ref="Console"/>
        </Logger>
        <Logger name="org.apache" level="info" additivity="false">
            <AppenderRef ref="Console"/>
        </Logger>
        <Root level="info">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

不带自定义域得日志:

{
  "thread": "main",
  "level": "INFO",
  "loggerName": "com.nginxtrafficsidecar.ApplicationKt",
  "message": "Starting ApplicationKt on xxx with PID 17300 (C:\\Users\\Felix\\Documents\\code\\nginx-traffic-sidecar\\build\\classes\\kotlin\\main started by Felix in C:\\Users\\Felix\\Documents\\code\\nginx-traffic-sidecar)",
  "endOfBatch": false,
  "loggerFqcn": "org.apache.commons.logging.LogAdapter$Log4jLog",
  "threadId": 1,
  "instant": {
    "epochSecond": 1587975181,
    "nanoOfSecond": 331370300
  },
  "source": {
    "class": "org.springframework.boot.StartupInfoLogger",
    "method": "logStarting",
    "file": "StartupInfoLogger.java",
    "line": 55,
    "classLoaderName": "app"
  },
  "contextMap": {},
  "threadPriority": 5
}

带自定义域得日志:

{
  "logEvent": "Starting ApplicationKt on xxx with PID 9732 (C:\\Users\\Felix\\Documents\\code\\nginx-traffic-sidecar\\build\\classes\\kotlin\\main started by Felix in C:\\Users\\Felix\\Documents\\code\\nginx-traffic-sidecar)",
  "serviceName": "local-sidecar"
}

Spring docu提到了如何使用logback,而不是log4j(https://docs.Spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-custom-log-configuration,章节末尾)

共有1个答案

廉雅惠
2023-03-14
  • 下载Jackson Annotations并导入它,因为JSONLayout使用Jackson Annotations内部代码。
    • 在我的示例中,下载并导入这些
    jackson-annotations-2.10.3.jar
    jackson-core-2.10.3.jar
    jackson-databind-2.10.3.jar
    
    <JsonLayout>
      <KeyValuePair key="testKey" value="testValue"/>
    </JsonLayout>
    

    keyvalue替换为要使用的内容。在我的示例中,key是“testkey”,value是“testvalue”

    它是我的完整示例代码和xml配置信息。代码

    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import org.apache.logging.log4j.ThreadContext;
    
    public class LogTest{
        private static final Logger logger = LogManager.getLogger(LogTest.class.getName());
    
    
        public static void main(String[] args) {
            ThreadContext.put("logFileName", "testFile1" );
            logger.info("log printed! - testFile1");
    
            ThreadContext.put("logFileName", "testFile2" );
            logger.info("log printed! - testFile2");
    
            ThreadContext.remove("logFileName");
        }
    
    }
    
    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="WARN">
        <Appenders>
            <Routing name="RoutingAppender">
                <Routes pattern="${ctx:logFileName}">
                    <Route>
                        <RollingFile name="Rolling-${ctx:logFileName}"
                                     fileName="./logs/${ctx:logFileName}.log"
                                     filePattern="./logs/${ctx:logFileName}.%i.log.gz">
                            <JsonLayout>
                                <KeyValuePair key="testKey" value="testValue"/>
                            </JsonLayout>
                            <SizeBasedTriggeringPolicy size="512" />
                        </RollingFile>
                    </Route>
                </Routes>
            </Routing>
        </Appenders>
    
        <Loggers>
            <Root level="all">
                <AppenderRef ref="RoutingAppender" />
            </Root>
        </Loggers>
    </Configuration>
    
    {
      "instant" : {
        "epochSecond" : 1588590944,
        "nanoOfSecond" : 469000000
      },
      "thread" : "main",
      "level" : "INFO",
      "loggerName" : "com.test.LogTest",
      "message" : "log printed! - testFile2",
      "endOfBatch" : false,
      "loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
      "threadId" : 1,
      "threadPriority" : 5,
      "testKey" : "testValue"
    }
    
    

 类似资料:
  • 问题内容: 我有一些带有自定义注释的类,不应实例化(抽象类,它只是真实bean的子组件)。但是在此类的顶部,在运行时,在上下文初始化阶段,我想将额外的bean放入应用程序上下文中。 因此,基本上,我需要扫描类路径,处理结果,并将新bean引入当前的应用程序上下文中。 似乎spring-mvc,spring-tasks和spring-integration正在这样做(我试图从源中学习它-没运气) 我

  • 问题内容: 我已经构建了自己的自定义react-bootstrap Popover组件: 该组件的呈现方式如下: 现在,我想向组件中添加自定义道具,例如:我的文字,并使用新道具在弹出框中设置一些内容,例如- 但随后我在浏览器中收到此警告: 警告:标签上的未知道具。从元素中删除这些道具。 现在,我想我可以删除零件并逐个插入所有原始道具,而无需自定义道具,但是这样我就失去了“淡入淡出”效果,这也是处理

  • 我一直在找,但还是想不出来。我需要为日志输出添加一个自定义日志模式。通过resources目录中的logback.xml文件,我可以非常轻松地完成此操作,而且它完全按照我所希望的方式工作。 但是,如果可能的话,我希望能够在整个application.yml文件中这样做。主要是因为我想把它外化在一个地方。

  • 问题内容: 我正在研究启用AJAX的asp.net应用程序。我刚刚向Array.prototype添加了一些方法,例如 该解决方案对我有用,可以以“漂亮”的方式重用代码。 但是,当我测试了它与整个页面一起使用时,我遇到了问题。我们有了一些自定义的Ajax扩展程序,它们开始表现出意想不到的效果:某些控件在其内容或值上显示为“未定义”。 这可能是什么原因?我是否缺少修改标准对象原型的东西? 注意:我很

  • 如果我创建一个继承JComponent的新类,我重写了JComponent的绘图Component(Graphics g)方法,通过使用g绘制一个圆圈,我应该修改什么才能使MouseListener仅在我单击组件的边界内时触发? 因为我在组件的构造函数中添加了setBounds(…)然后添加了一个MouseListener,但它会在我每次单击自定义组件所在容器中的任何位置时触发,而不仅仅是在我单击