我有一个 spring 应用程序服务于网络请求。每个请求方法看起来像这样
@RequestMapping(value = someUri, method = RequestMethod.POST)
Response someUriProcessor (SomeRequestModelMethod request) throws Exception {
try (JsonLogger logger = new JsonLogger(request, loggingTest1Uri)){
// get actual result
Response result = getSomeResultMethod(request);
// feed result to special logging object
logger.setResult (result);
// return result to client
return result;
}
}
JsonLogger 类在 close 方法中生成 JSON 对象,并通过标准的 slf4j 日志框架记录它,并上传到日志分析工具(Splunk),它记录请求、响应、响应时间等。
在执行大量工作的 getSomeResultMethod 期间,在生产中使用标准 slf4j 和 logback 绑定(bind)生成大量有用的日志。 我希望这些日志包含在 JsonLogger 中而不触及所有底层类(它们有很多),比如使用方法 JsonLogger.appendToResultLog(String txt)。我的第一个想法是创建我自己的包装 slf4j 绑定(bind),在每次调用 logger.info、logger.error 等方法时展开堆栈跟踪,使用反射到 rest Controller 方法并在其中附加日志字符串 JsonLogger。
我有一种强烈的感觉,我正在发明一辆自行车。是否有任何或多或少的标准方法来实现所需的结果?
最佳答案
结束时没有方面和反射 - 只是自定义 logback appender。
public class JsonInnerLogsAppender extends AppenderBase<ILoggingEvent> {
public JsonInnerLogsAppender () {
this.setName("JSON_LOGGING_INTERNAL");
}
@Override
protected void append(ILoggingEvent eventObject) {
JsonLogger.putLogInfo(eventObject.getFormattedMessage());
}
}
还有像这样的JsonLogger
public class JsonLogger implements AutoCloseable {
/**
* Contains mapping between current thread id and corresponding JsonLogger object
*/
private static transient ConcurrentHashMap<Long, JsonLogger> loggersMap = new ConcurrentHashMap<>();
/**
* Should be configured with special appender pattern, like
* <encoder>
* <pattern>%date{ISO8601} [%-18thread] %-5level %msg %logger{70}%n</pattern>
* </encoder>
*/
private transient Logger logger = LoggerFactory.getLogger(getClass());
private transient static Gson gson = new Gson();
/**
* Container that would be serialized to JSON after close and added to JSON log
*/
private final JsonLogContainer logContainer;
public JsonLogger (Object request, HttpServletRequest servletRequest) {
this.logContainer = new JsonLogContainer(gson.toJson(request), servletRequest.getRequestURI());
// request is started
loggersMap.put(Thread.currentThread().getId(), this);
}
/**
* @param logString formatted log string, called from custom appender
*/
public static void putLogInfo (String logString) {
// find appropriate JsonLogger instance (if any) and append log to it
JsonLogger jsonLogger = loggersMap.get(Thread.currentThread().getId());
if ( null != jsonLogger ) {
jsonLogger.putLogToContainer(logString);
}
}
private void putLogToContainer (String logString) {
logContainer.putLog(logString);
}
@Override
public void close() throws Exception {
String log = this.logContainer.getLog(new Date());
// request is completed
loggersMap.remove(Thread.currentThread().getId());
// put record to JSON log
logger.info(log);
}
public void setResult(Object result) {
logContainer.setResponse(gson.toJson(result));
}
}
关于java - 懒人登录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34956301/