Идентификатор процесса в журнале ведения журнала

У меня есть следующий шаблон журнала:

<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"

Есть ли автоматически заданная переменная для идентификатора процесса, например, для имени хоста? У меня возникли проблемы с поиском документально зарегистрированного списка таких автоматически заданных переменных в документации по протоколированию, может ли кто-нибудь узнать о лучшем источнике документации?

Изменить: мне известно о Mapped Diagnostic Contexts, но надеялся на встроенное решение, которое не нуждается в такой настройке, подобно тому, как работает имя хоста.

Ответ 1

Вы можете решить свою проблему с помощью Диагностического контекста:

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>

EDITED

Также вы можете создать свой собственный энкодер и конвертер и использовать их в 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>

Ответ 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

Возможно, вы можете попробовать% thread вместо процесса.