Search code examples
ballerinahttpinterceptorballerina-http

How to use a correlation ID for logging in microservices in Ballerina?


I'm trying to develop an HTTP service in Ballerina. I need to add a correlation Id to each log entry printed in the service like mentioned in [1] for java. Is there any recommended approach to achieve this in ballerina?

[1] https://dzone.com/articles/correlation-id-for-logging-in-microservices

I was trying the following simple HTTP service.

import ballerina/http;

type Album readonly & record {|
    string title;
    string artist;
|};

table<Album> key(title) albums = table [
    {title: "Blue Train", artist: "John Coltrane"},
    {title: "Jeru", artist: "Gerry Mulligan"}
];

service / on new http:Listener(9090) {
    resource function get albums() returns Album[] {
        return albums.toArray();
    }
}

Solution

  • You can implement a request interceptor to generate correlation Id from UUID generation for each request and put it into the http:RequestContext as a key-value pair. The http:RequestContext is available throughout the request life cycle. Hence whenever the logging is required, retrieve the correlation Id from the http:RequestContext. You can add http:RequestContext as resource function argument to any service type.

    import ballerina/http;
    import ballerina/uuid;
    import ballerina/log;
    
    type Album readonly & record {|
        string title;
        string artist;
    |};
    
    table<Album> key(title) albums = table [
        {title: "Blue Train", artist: "John Coltrane"},
        {title: "Jeru", artist: "Gerry Mulligan"}
    ];
    
    function generateCorrelationId() returns string {
        return uuid:createType1AsString();
    }
    
    service class RequestInterceptor {
        *http:RequestInterceptor;
    
        resource function 'default [string... path](http:RequestContext ctx)
            returns http:NotImplemented|http:NextService|error? {
            string id = generateCorrelationId();
            ctx.set("correlation-id", id);
    
            return ctx.next();
        }
    }
    
    service http:InterceptableService / on new http:Listener(9090) {
        public function createInterceptors() returns RequestInterceptor {
            return new RequestInterceptor();
        }
    
        resource function get albums(http:RequestContext ctx) returns Album[] {
            log:printInfo("Correlation ID: " + ctx.get("correlation-id").toString());
            return albums.toArray();
        }
    }