4

I am using spring-boot and using logback to generate the logs. Now I want to log a specific header in every log.

How can i achieve that.

My logback file is

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <springProperty name="appName" source="spring.application.name" defaultValue="apigateway" />
    <property name="LOG_PATH" value="${LOG_PATH}" />
    <!-- Console logging -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>
                [%d{YYYY-MM-dd HH:mm:ss.SSS}] [%X{X-B3-CONVID:-}] [%X{X-B3-TraceId:-}] [%X{X-B3-SpanId:-}] [${HOSTNAME}] [%level] [${appName}] [%logger{36}.%M] - %msg %n
            </pattern>
        </encoder>
    </appender>

    <appender name="APPLICATIONLOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <append>true</append>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/applogs/application.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>60</maxHistory>
            <totalSizeCap>20GB</totalSizeCap>
        </rollingPolicy>

        <encoder>
            <Pattern>
                [%d{YYYY-MM-dd HH:mm:ss.SSS}] [%X{X-B3-CONVID:-}] [%X{X-B3-TraceId:-}] [%X{X-B3-SpanId:-}] [${HOSTNAME}] [%level] [${appName}] [%logger{36}.%M] - %msg %n
            </Pattern>
        </encoder>
    </appender>


    <!-- set logger level: e.g. info, trace, debug, error -->
    <root level="info">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="APPLICATIONLOG" />
    </root>

</configuration>

Apart from this I have not done anything to confgure the logs. Just added the dependency for slf4j and then added the logback spring file.

Any help is appreciated

Ankit Bansal
  • 2,162
  • 8
  • 42
  • 79
  • can you add what is o/p like for above settings, and what is that you expect?, you want %X{X-B3-TraceId:-} to be printed in every log? – dkb Jun 20 '18 at 06:12
  • this o/p is print on every log and i want my header to be printed on every log – Ankit Bansal Jun 20 '18 at 07:03
  • What I mean is, do you need to print RESTful service Request's header or Log file's header(like log file's 1st line will be ) ? – dkb Jun 20 '18 at 07:13
  • Yes, in my service rest api, I will get a http header named TrasactionId and I want to be printed in every log – Ankit Bansal Jun 20 '18 at 07:29
  • is it like this `[INFO [[2018-06-20 14:18:46,795] [GET /api/id/123] [[c.TestResource - [Txn-a553970e-5951-4afd-a183-13216438f37d] - test api response : "hello"` ? – dkb Jun 20 '18 at 08:52
  • [2018-06-20 11:37:31.638] [] [6e2260ca8c4f51e4] [6e2260ca8c4f51e4] [serverName] [ERROR] [apigateway] [c.s.u.c.PerformanceMetricsLogger.logRequestsWithTimeGreaterThanThreshold] - Monitoring Data : API response time : Service : apigateway, API : commonapi/v1/info/getHamburgerData,Controller: CommonDataControllerVOne, Method: getHamburgerData, Response Time: 280.. Its like this right now – Ankit Bansal Jun 20 '18 at 09:00

2 Answers2

3

add [%X{TrasactionId}] in your console and file appender pattern like

for STDOUT appender

<pattern>
   [%d{YYYY-MM-dd HH:mm:ss.SSS}] [%X{TrasactionId}] [%X{X-B3-CONVID:-}] [%X{X-B3-TraceId:-}] [%X{X-B3-SpanId:-}] [${HOSTNAME}] [%level] [${appName}] [%logger{36}.%M] - %msg %n
</pattern>

and

for APPLICATIONLOG appender

<Pattern>
   [%d{YYYY-MM-dd HH:mm:ss.SSS}] [%X{TrasactionId}] [%X{X-B3-CONVID:-}] [%X{X-B3-TraceId:-}] [%X{X-B3-SpanId:-}] [${HOSTNAME}] [%level] [${appName}] [%logger{36}.%M] - %msg %n
</Pattern>

and following code in a project.

import org.slf4j.MDC;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.Response;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ClientFilter implements ContainerRequestFilter, ContainerResponseFilter {

    private final String TRANSACTION_ID = "TrasactionId"; 
    @Override
    public void filter(ContainerRequestContext requestContext) {
        final String transactionId = requestContext.getHeaderString(TRANSACTION_ID);
        if (transactionId == null || transactionId == "") {
            log.debug("transactionId is null/empty");
            return;
        }
        MDC.put(TRANSACTION_ID, TRANSACTION_ID + ":" + transactionId);
        // other logic based on this based on your requirement
    }

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
        final String transactionId = requestContext.getHeaderString(TRANSACTION_ID);
        if (transactionId == null || transactionId == "") {
            return;
        }
        responseContext.getHeaders().add(TRANSACTION_ID, transactionId);
        MDC.remove(TRANSACTION_ID);
    }

}

This will add in logs as below along with other texts

[2018-06-20 11:37:31.638] [TrasactionId:75c2f962-fcdc-452e-bf7e-eddc6453673e] [6e2260ca8c4f51e4] [6e2260ca8c4f51e4] [serverName] [ERROR] [apigateway [c.s.u.c.PerformanceMetricsLogger.logRequestsWithTimeGreaterThanThreshold] - Monitoring Data : API response time : Service : apigateway, API : commonapi/v1/info/getHamburgerData

Note:

  1. Make sure header value is same as TrasactionId, or add same string everywhere to make it work.

  2. Register client to jersey jersey.register(ClientFilter.class);

dkb
  • 4,389
  • 4
  • 36
  • 54
  • The answer you have mentioned is jersey specific. We are using spring boot without jersey. Can you explain how to do this – Ankit Bansal Jun 20 '18 at 09:41
  • No, you did not get the point, I am using slf4J's feature, MDC, I have added here the code to get a broader view, If you know how to add Filter in spring, then you can add the same code of ClientFilter there. It will work as it is. – dkb Jun 20 '18 at 09:43
  • Yes, so what I have to do is add it to MDC and it will be available in logback file – Ankit Bansal Jun 20 '18 at 09:43
0

Please find below example with Spring

If you want to log http headers then you need to use MDC feature: http://logback.qos.ch/manual/mdc.html

Create Filter:

@Component
class RequestHeaderFilterConfig : Filter {

    private val xRequestId = "X-Request-Id"

    override fun doFilter(request: ServletRequest?, response: ServletResponse?, chain: FilterChain?) {
        val httpRequest = request as HttpServletRequest
        MDC.put(xRequestId, httpRequest.getHeader(xRequestId))
        chain?.doFilter(request, response)
    }

    override fun destroy() = MDC.remove(xRequestId)
}

Controller:

@PostMapping
fun operation(@RequestHeader(value = "X-Request-Id", required = false) xRequestId: String? = null): ResponseEntity<Output> {
    ....
}

logback.xml

<Pattern>%d{dd-MM-yyyy HH:mm:ss.SSS} [%thread] %-5level [X-Request-Id: %X{X-Request-Id}] %logger{36}.%M:%line - %msg%n</Pattern>
2787184
  • 3,749
  • 10
  • 47
  • 81