0

I am using spring boot in a project and currently exploring the logging behaviour. For that I'm using the zipkin service.

My logback.xml is as follows:

    <appender name="STASH"
    class="net.logstash.logback.appender.LogstashTcpSocketAppender">
    <destination>192.168.0.83:5000</destination>
      <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder"
        <providers>
            <mdc /> <!-- MDC variables on the Thread will be written as JSON fields -->
            <context /> <!--Outputs entries from logback's context -->
            <version /> <!-- Logstash json format version, the @version field in the output -->
            <logLevel />
            <loggerName />
            <pattern>
                <pattern>
                    {
                    "serviceName": "zipkin-demo"
                    }           
                </pattern>
            </pattern>
            <threadName />
            <message />
            <logstashMarkers />
            <arguments />
            <stackTrace />
        </providers>
    </encoder>
</appender>

<root level="info">
    <appender-ref ref="STASH" />
</root> 

Now for what I have understood, to log in json, you need a custom logger implementation which I have done as follows:

public class CustomLogger {

public static void info(Logger logger, Message message, String msg) {
    log(logger.info(), message, msg).log();
}

private static JsonLogger log(JsonLogger logger, Message message, String msg) {
    try {
        if (message == null) {
            return logger.field("Message", "Empty message").field("LogTime", new Date() );
        }
        logger
        .field("message", message.getMessage())            
        .field("id", message.getId());

        StackTraceElement ste = (new Exception()).getStackTrace()[2];
        logger.field(
                "Caller",
                ste.getClassName() + "." + ste.getMethodName() + ":" + ste.getLineNumber());
        return logger;
    } catch (Exception e) {
        return logger.exception("Error while logging", e).stack();
    }
}

My message class is:

public class Message {

private int id;
private String message;

..constructor & setters and getters
}

Now in my controller class I'm using my custom logger as:

static  com.savoirtech.logging.slf4j.json.logger.Logger log = com.savoirtech.logging.slf4j.json.LoggerFactory.getLogger(Controller.class.getClass());
Message msg = new Message(1, "hello");
CustomLogger customLogger = new CustomLogger();
customLogger.info(log, msg, "message");

My logs end up in kibana as:

 "message": "{\"message\":\"hello\",\"id\":1,\"Caller\":\"<class_name>:65\",\"level\":\"INFO\",\"thread_name\":\"http-nio-3333-exec-2\",\"class\":\"<custom_logger_class>\",\"logger_name\":\"java.lang.Class\",\"@timestamp\":\"2018-07-20 19:02:14.090+0530\",\"mdc\":{\"X-B3-TraceId\":\"554c43b0275c3430\",\"X-Span-Export\":\"true\",\"X-B3-SpanId\":\"368702fffa40d2cd\"}}",

Now instead of this I would want my message part of the logs as a json entry. Where am I going wrong? I have tried searching a way extensively but to no avail. Is it even possible?

Swapnil Pandey
  • 577
  • 3
  • 8
  • 25

1 Answers1

0

I finally got it working. I just changed the logstash config file and added:

input
{  
   tcp   
   {  
      port => 5000 
      type => "java" 
      codec => "json"
   }
}
filter
{  
   if [type]== "java"   
   {  
      json
      {  
         source => "message"
      }
   }
}

The filter part was missing earlier.

Swapnil Pandey
  • 577
  • 3
  • 8
  • 25