【问题标题】:Process Id in Logback Logging PatternLogback 日志模式中的进程 ID
【发布时间】:2016-04-26 20:54:22
【问题描述】:

我有以下 logback 模式:

<pattern>
    {"hostname": "${HOSTNAME}", 
     "level": "%p", 
     "method": "%M", 
     "process_id": "${process}", 
     "thread_id": "%t", 
     "timestamp": "%d{Y-M-d}T%d{H:M:S.s}", 
     "mesg":"%msg"}%n
</pattern>

不幸的是,当实际生成日志消息时,我看到:"process_id": "process_IS_UNDEFINED"

是否有任何自动设置的进程 id 变量,例如主机名?我在 logback 文档中查找此类自动设置变量的文档列表时遇到了很多麻烦,有人知道更好的文档来源吗?

编辑:我知道映射诊断上下文,但希望有一个不需要此类设置的内置解决方案,就像主机名的工作方式一样。

【问题讨论】:

    标签: java logback


    【解决方案1】:

    你可以通过Mapped Diagnostic Context解决你的问题:

    import org.slf4j.MDC;
    
    public class Main {
        public static void main(String... args) {
            // put process ID early
            MDC.put("process_id", 
                ManagementFactory.getRuntimeMXBean().getName());
        }
    }
    

    之后,您只需重新定义您的模式,如下所示:

    <pattern>{..., "process_id": "%X{process_id}"}</pattern>
    

    已编辑

    您也可以创建自己的编码器和转换器并在logback.xml 中使用它们:

    import ch.qos.logback.classic.PatternLayout;
    import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
    
    public class ExtendedPatternLayoutEncoder extends PatternLayoutEncoder {
        @Override
        public void start() {
            // put your converter
            PatternLayout.defaultConverterMap.put(
                "process_id", ProcessIdConverter.class.getName());
            super.start();
        }
    }
    
    import ch.qos.logback.classic.pattern.ClassicConverter;
    import ch.qos.logback.classic.spi.ILoggingEvent;
    
    import java.lang.management.ManagementFactory;
    
    public class ProcessIdConverter extends ClassicConverter {
        private static final String PROCESS_ID =
                ManagementFactory.getRuntimeMXBean().getName();
    
        @Override
        public String convert(final ILoggingEvent event) {
            // for every logging event return processId from mx bean
            // (or better alternative)
            return PROCESS_ID;
        }
    }
    
    <encoder class="some.package.ExtendedPatternLayoutEncoder">
        <pattern>{..., "process_id": "%process_id"}</pattern>
    </encoder>
    

    完整示例:

        <encoder class="some.package.ExtendedPatternLayoutEncoder">
            <pattern>%d{dd.MM.yyyy HH:mm:ss.SSS} PID:%process_id [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    

    【讨论】:

    • 这是一个我知道的解决方案,但它很烦人,因为它需要修改我们的实际代码。无论如何在修改应用程序代码之外设置MDC?也许通过编写一个单独的类来修改 MDC 并将其放在类路径上?
    • @qwwqwwq 我不确定是否有一些记录在案的方法。我想你可以覆盖ch.qos.logback.classic.PatternLayoutBase 类并将你的转换器放在defaultConverterMap 中。但这是一个肮脏的黑客:)
    • @qwwqwwq 还有另一种方法。您实际上可以从 ch.qos.logback.classic.PatternLayout 继承并在您的 logback.xml 中使用它,例如 here
    • @qwwqwwq 我也认为实现自己的编码器/布局以渲染json 输出是个好主意,这样您就可以在"mesg" 中正确转义消息
    • 这看起来好多了!是的,这是关于 JSON 的一个很好的观点,感谢您提出这个问题。
    【解决方案2】:

    有比@vsminkov 更好的解决方案。 我在这里找到它:Layouts,它是否说创建自定义转换说明符。 基本上你创建你的转换器,但不是扩展PatternLayoutEncoder,而是在你的配置中添加一个转换规则:

    <configuration>
    
      <conversionRule conversionWord="pid" 
                      converterClass="my.custom.converter.ProcessIdConverter" />
      <conversionRule conversionWord="processId" 
                      converterClass="my.custom.converter.ProcessIdConverter" />
    
      <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
          <pattern>%-6pid [%thread] - %msg%n</pattern>
        </encoder>
      </appender>
      ...
    </configuration>
    

    这样你就摆脱了编码器

    【讨论】:

    • 这是真正的交易。比默认答案好得多。
    【解决方案3】:

    DefaultLogbackConfiguration 中定义的控制台日志记录的默认模式是:

    "${CONSOLE_LOG_PATTERN:-"
                + "%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) "
                + "%clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} "
                + "%clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"
    

    正如@Hlulani 所指出的,并且您可以在此默认模式中看到,您可以使用 ${PID} 并且 logback 将用进程 ID 替换它。

    【讨论】:

    • 您链接到的日志记录模式来自spring-boot,这是一个使用 logback 作为第三方依赖项的项目。他们在这里将 PID 指定为自定义日志记录属性:github.com/spring-projects/spring-boot/blob/… 如果您只使用 logback 作为依赖项,您将无法使用这样的日志记录模式。
    【解决方案4】:

    我尝试使用对我有用的 ${PID}

    <pattern>
        {"hostname": "${HOSTNAME}", 
         "level": "%p", 
         "method": "%M", 
         "process_id": "${PID}", 
         "thread_id": "%t", 
         "timestamp": "%d{Y-M-d}T%d{H:M:S.s}", 
         "mesg":"%msg"}%n
    </pattern>
    

    【讨论】:

    • 我不认为这在 logback 中“开箱即用”,您必须在项目的某个地方指定自定义日志记录属性PID,也许第三方库正在这样做?如果在 logback 源代码中搜索字符串PID,它似乎没有出现在代码的任何地方。
    【解决方案5】:

    也许你可以尝试 %thread 而不是进程。

    【讨论】:

    • 感谢您的回复,我已经有了线程ID,但正在寻找进程ID。
    猜你喜欢
    • 2021-07-28
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 2011-12-11
    • 2014-10-25
    • 2017-06-26
    • 2020-10-09
    相关资源
    最近更新 更多