Search code examples
javastringstring-formattingslf4j

Pass Values dynamically to String formatter with format specifier


I am trying to print logs where the params keep changing for every request. I am trying to use String formatter.

Here is my code

MailService.java

static final LinkedHashMap<String , String> logMap = new LinkedHashMap<String , String>();

logMap.put("mailType", mailType);
logMap.put("projectId", projectId);

LogUtility.getDownstreamReqLog(LOGGER,jwtTokenProvider,url,logMap);

LogUtility.java

public static void getDownstreamReqLog(Logger log, JwtTokenProvider jwtTokenProvider, URI url,LinkedHashMap<String,String> logMap) {

    String message = " {" + BffConstants.REQUEST_ID_KEY + " = %s }" + " {" + BffConstants.REQUEST_URL + " = %s }";

    List<String> values = new ArrayList<>();

    String mapKeys = "";
    for (String key : logMap.keySet()) {
        mapKeys = mapKeys + " {" + key + " =%s }";
        values.add(logMap.get(key));
    }

    message = message + mapKeys;

    LogUtility.info(log, message,jwtTokenProvider.getRequestId(),url,values.toArray(new
   String[0]));
}

public static void info(Logger log, String message, Object... args) {
    log.info(getFormattedMessage(message, args));
}

private static String getFormattedMessage(String message, Object... args) {
    String formattedMessage = message;
    if (args != null && args.length > 0) {
        formattedMessage = String.format(message, args);
    }
    return formattedMessage;
}

Request Id key and Url is common for all requests. Other params vary based on request.So i am trying to dynamically append key and value pairs to the log info method. Keys are getting passed as expected. But the issue i am facing is values is going as an array.Is there a way where i can pass it as individual Strings as array will cause formatting error. For example Object array args is taking inputs in this format

    [0] = "requestId"
    [1] = "url"
    [2] = String[2]

I want it to get passed in this format

    [0] = "requestId"
    [1] = "url"
    [2] = "value1"
    [3] = "value2"
    and so on... based on number of values present in LinkedHashMap so that respective formatter key gets mapped to respective value. 

Is there a way i can accomplish it in getDownstreamReqLog method or do i have to start thinking to make changes in getFormattedMessage method itself if its not possible to pass values as individual Strings instead of array? Thank you for any inputs.


Solution

  • You could add your requestId and url to your values list and call LogUtility.info only with your array

    public static void getDownstreamReqLog(Logger log, JwtTokenProvider jwtTokenProvider, URI url,LinkedHashMap<String,String> logMap) {
    
        String message = " {" + BffConstants.REQUEST_ID_KEY + " = %s }" + " {" + BffConstants.REQUEST_URL + " = %s }";
    
        List<String> values = new ArrayList<>();
        values.add(jwtTokenProvider.getRequestId()); 
        values.add(url.toString());
    
        String mapKeys = "";
        for (String key : logMap.keySet()) {
            mapKeys = mapKeys + " {" + key + " =%s }";
            values.add(logMap.get(key));
        }
    
        message = message + mapKeys;
    
        LogUtility.info(log, message, values.toArray(new String[0]));
    }