javaspring-bootlogginglogbacklogstash-logback-encoder

Limit message size with custom encoder using logback


I'm trying to limit the log message size, I succeed to do it with the error traceback (using ShortenedThrowableConverter) but I didn't manage to find a solution to the message itself.

I know one way is to use <pattern/> but since I'm implementing the encoder by myself.

I tried using layout but encountered with this error below:

no applicable action for [layout], current ElementPath  is [[configuration][appender][encoder][layout]]

Here is some of my code:

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="console-json" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="com.test.log.logback.JsonEncoder">
            <throwableConverter class="net.logstash.logback.stacktrace.ShortenedThrowableConverter">
                <maxLength>20</maxLength>
            </throwableConverter>
        </encoder>
    </appender>

    <root level="info">
        <appender-ref ref="console-json" />
    </root>

    <shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>

    <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
        <resetJUL>true</resetJUL>
    </contextListener>
</configuration>

encoder:

package com.test.log.logback;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.logstash.logback.stacktrace.ShortenedThrowableConverter;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;


public class JsonEncoder extends net.logstash.logback.encoder.LogstashEncoder {


    private String customFields;
    ShortenedThrowableConverter converter = new ShortenedThrowableConverter();
    public JsonEncoder() {
        converter.setMaxLength(10);
        setThrowableConverter(converter);
        setFieldNames(new FieldNames());
        setTimeZone("UTC");
        setFindAndRegisterJacksonModules(false);
    }   
    
}

Solution

  • To limit the message field within the JSON output when using the net.logstash.logback.encoder.LogstashEncoder, you'll need to:

    1. Disable the default message field output
    2. Add a custom message field using the pattern provider

    For example:

    <encoder class="net.logstash.logback.encoder.LogstashEncoder">
        <!-- Disable the default message field -->
        <fieldNames>
            <message>[ignore]</message>
        </fieldNames>
        <!-- Add a new message field that truncates the message to 20 characters -->
        <provider class="net.logstash.logback.composite.loggingevent.LoggingEventPatternJsonProvider">
            <pattern>{"message":"%0.-20message"}</pattern>
        </provider>
    </encoder>
    

    or as a custom encoder:

    public class JsonEncoder extends LogstashEncoder {
        @Override
        public void start() {
            // Disable the default message field
            getFieldNames().setMessage("[ignore]");
    
            // Add a new message field that truncates the message to 20 characters
            LoggingEventPatternJsonProvider patternProvider = new LoggingEventPatternJsonProvider();
            patternProvider.setContext(getContext());
            patternProvider.setPattern("{\"message\":\"%0.-20message\"}");
            addProvider(patternProvider);
            super.start();
        }
    }
    
    

    Alternatively, you can use net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder (which is the superclass of LogstashEncoder), and build up the JSON event exactly as you like with JSON providers. See here.

    For example:

    <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
        <providers>
            <pattern>
                <pattern>
                    {
                    "timestamp": "%date{ISO8601}",
                    "message":"%0.-20message"
                    }
                </pattern>
            </pattern>
            <!--
                To add additional fields to the JSON output, either
                add the fields to the above pattern, or
                add additional JSON providers here.
             -->
        </providers>
    </encoder>
    

    or as a custom encoder:

    public class JsonEncoder extends LoggingEventCompositeJsonEncoder {
        @Override
        public void start() {
            getProviders().addProvider(new LoggingEventFormattedTimestampJsonProvider());
    
            LoggingEventPatternJsonProvider patternProvider = new LoggingEventPatternJsonProvider();
            patternProvider.setContext(getContext());
            patternProvider.setPattern("{\"message\":\"%0.-20message\"}");
            getProviders().addProvider(patternProvider);
    
            /*
             * To add additional fields to the JSON output, either
             * add the fields to the above pattern, or
             * add additional JSON providers here.
             */
            super.start();
        }
    }