日志场景下如何将动态参数作为独立字符串传入String格式化器?
动态请求参数日志格式化问题
我想用String格式化器打印动态变化的请求参数日志,Request Id和Url是所有请求的公共参数,其他参数随请求变化。当前代码在传递参数时出现格式化错误,因为动态参数被作为数组整体传入,而非独立的字符串元素。
现有代码
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; }
当前问题
调用LogUtility.info时,传入的args数组结构错误:
[0] = "requestId" [1] = "url" [2] = String[2] // 动态参数被作为单个数组元素传入,导致String.format匹配失败
期望的参数结构
[0] = "requestId" [1] = "url" [2] = "value1" [3] = "value2" // 动态参数逐个展开为独立元素
解决方案
不需要修改getFormattedMessage方法,只需在getDownstreamReqLog中把公共参数和动态参数合并成一个完整的数组再传入即可:
修改后的getDownstreamReqLog代码:
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<Object> allArgs = new ArrayList<>(); // 添加公共参数到列表 allArgs.add(jwtTokenProvider.getRequestId()); allArgs.add(url); String mapKeys = ""; for (String key : logMap.keySet()) { mapKeys = mapKeys + " {" + key + " =%s }"; // 将动态参数值逐个加入列表 allArgs.add(logMap.get(key)); } message = message + mapKeys; // 将合并后的列表转为数组传入info方法 LogUtility.info(log, message, allArgs.toArray(new Object[0])); }
说明
- 用
ArrayList<Object>统一存放公共参数和动态参数,避免数组嵌套的问题 - 最终通过
toArray(new Object[0])将列表转为Object数组,完全匹配info方法的可变参数要求 - 这样
String.format就能正确将每个%s与对应的参数一一匹配,不会出现格式化错误
内容的提问来源于stack exchange,提问作者Sachin HR
相关产品推荐
相关产品推荐

