Search code examples
jsonlogginglogstash-logback-encoder

How to customize message attribute of JSON Logging using logstash-logback-encoder?


I am using logstash-logback-encoder to print logs in json format.

Below is my logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="sample" class = "org.ssn.app.config.CustomLogService">
</appender>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="net.logstash.logback.encoder.LogstashEncoder">
    <provider class="net.logstash.logback.composite.loggingevent.ArgumentsJsonProvider"/>
    </encoder> 
    
 
  </appender>
  <logger name="org.ssn.app" additivity="false" level="DEBUG">
    <appender-ref ref="STDOUT"/>
</logger>
  <root level="INFO">
  
    <appender-ref ref="STDOUT"/>
    
  </root> 
  
  
</configuration>
  1. Below my code snippet
    JSONObject lJsonObj = new JSONObject();
    lJsonObj.put("dl_no","DL10252");
    logger.debug(lJsonObj.toString,Markers.append("ss","sss"));
  1. The output is below
{
    "@timestamp": "2021-06-17T18:49:07.914+05:30",
    "@version": "1",
    "message": "{\"dl_no\":\"DL10252\"}",
    "logger_name": "org.ssn.app.controller.TestController1",
    "thread_name": "http-nio-8080-exec-1",
    "level": "DEBUG",
    "level_value": 10000,
    "ss": "sss"
}

Is there is any way to modify the message attribute's value data type so that we can avoid "\" >back slashes? Because typically i want to put JSON or nested JSON inside message attribute's >value and want to view them without any backslashes


Solution

  • The message field of a log event is typically a string, since the majority of logger statements are strings.

    Since the message field is a string, any double quote characters (") within the string value must be escaped. This means that if JSON is included within the message field value, the double quote characters will be escaped.

    The encoder has no way of knowing the message value is properly formatted JSON. Therefore, it has to escape it to ensure that the JSON produced for the log event is proper JSON.

    If you have a pre-serialized JSON value that you want to include in the JSON log event, then you can use Markers.appendRaw or StructuredArguments.raw to add your value to a different field (not the message field).

    For example:

    JSONObject lJsonObj = new JSONObject();
    lJsonObj.put("dl_no", "DL10252");
    String jsonString = lJsonObj.toString()
    
    // using markers
    logger.debug(Markers.appendRaw("my_field", jsonString), "my message");
    
    // using structured arguments
    logger.debug("my message", StructuredArguments.raw("my_field", jsonString));
    
    

    which would yield something like:

    {
        "@timestamp": "2021-06-17T18:49:07.914+05:30",
        "@version": "1",
        "message": "my message",
        "logger_name": "org.ssn.app.controller.TestController1",
        "thread_name": "http-nio-8080-exec-1",
        "level": "DEBUG",
        "level_value": 10000,
        "my_field": {"dl_no" : "DL10252"}
    }
    

    Alternatively, rather than pre-serializing the JSON string, you can let the encoder serialize the value. For example, the following would yield the same as above...

    // using markers
    logger.debug(Markers.append("my_field", Map.of("dl_no", "DL10252")), "my message");
    
    // using structured arguments
    logger.debug("my message", StructuredArguments.kv("my_field", Map.of("dl_no", "DL10252"));