在实际项目中会产生海量日志,我们需要收集某种格式的INFO级别日志(例如请求报文和响应报文)到es中,然后通过kibana查看日志。
而要求每个开发人员打印特定格式的日志,显然是不优雅,所以我们需要自定义log.info()
的方法,供开发人员使用。
需要解决两个问题:
- Format格式:支持{}替换符,可以使用MessageFormatter官方API。
- 信息中,需要打印调用类和调用方法信息,可以使用StackTraceElement获取。
@Slf4j
public class TestLogger {
private final static DateTimeFormatter LOG_DATE = DateTimeFormatter
.ofPattern("yyyy-MM-dd HH:mm:ss");
public static void log(String appendLogPattern, Object... appendLogArguments) {
//打印数据
FormattingTuple formattingTuple = MessageFormatter.arrayFormat(appendLogPattern, appendLogArguments);
String appendLog = formattingTuple.getMessage();
StackTraceElement stackTraceElement = (new Throwable()).getStackTrace()[1];
//获取调用者的类以及方法
logDetail(stackTraceElement, appendLog);
}
//将异常使用log.info()级别日志打印。
public static void log(Throwable e) {
//writer类。
StringWriter stringWriter = new StringWriter();
//将异常信息填充到stringWriter中。
e.printStackTrace(new PrintWriter(stringWriter));
//打印数据
String appendLog = stringWriter.toString();
StackTraceElement stackTraceElement = (new Throwable()).getStackTrace()[1];
logDetail(stackTraceElement, appendLog);
}
private static void logDetail(StackTraceElement stackTraceElement, String appendLog) {
//traceId,即本次请求的唯一id(此处使用了skywalking获取traceId,按照项目实际需要打印)
String traceId = TraceContext.traceId();
String time = LocalDateTime.now().format(LOG_DATE);
log.info("类型:test traceId:{} {} {}.{}:{} {}",
traceId, time, stackTraceElement.getClassName(), stackTraceElement.getMethodName(), stackTraceElement.getLineNumber(),
appendLog);
}
}
调用者:
@Slf4j
@Service
public class LoggerService {
public void testLogger(String name) {
//打印日志
TestLogger.log("请求参数:{}",name);
}
}
结果信息
2020-12-01 15:18:53,485 INFO [6634] [http-nio-8087-exec-2] [] (TestLogger.java:52): 类型:test traceId: 2020-12-01 15:18:53 com.tellme.service.LoggerService.testLogger:17 请求参数:tom
网友评论