Search code examples
javalogback

Process Id in Logback Logging Pattern


I have the following logback pattern:

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

Unfortunately when the log messages are actually generated I see: "process_id": "process_IS_UNDEFINED"

Is there any automatically set variable for process id, such as there is for hostname? I am having a lot of trouble finding a documented list of such automatically set variables in the logback documentation, does anyone know of a better documentation source?

Edit: I am aware of Mapped Diagnostic Contexts, but was hoping for a builtin solution that does not need such setup, much like how hostname works.


Solution

  • You can solve your problem with 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());
        }
    }
    

    After that all you need is to re-define your pattern as follows:

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

    EDITED

    Also you can create your own encoder and converter and use them in 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>
    

    Full example:

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