业务开发中,日志的收集极为重要,特别是在进行故障分析时,日志记录得好,可以帮我们快速定位问题原因。
Linux日志查看命令:tail、cat、head、more
tail 和 head 命令
tail 查看日志尾部最后几行的日志,一般会结合 grep 进行搜索应用:
tail -n 10 test.log tail -fn 1000 test.log | grep 'test'
head 和 tail,查看日志文件的前几行日志,其他应用和 tail 类似:
head -n 10 test.log
more 和 less
more 命令可以按照分页的方式现实日志内容,并且可以进行快速地翻页操作,除了 more 命令以外,常用的还有 less 命令,和 more 的应用类似。
cat
cat 命令用于查看全部文件,是由第一行到最后一行连续显示在屏幕上,一次显示整个文件。
在分布式系统下,用户一个请求通常需要先后调用(rpc、http)多个工程模块,依次处理数据,才能返回正确结果。日志变得越来越分散,如何更好地收集和分析日志,就变成了一个特别重要的问题。
存在的问题:如何对日志文件之间的关系进行聚合,从全局上梳理日志,从而进行调用链路的分析。
考虑到上述问题,我在工作中设计了一个分布式链路日志方案:
- 通过aop切面思想,对每个工程设计一个日志拦截器,并统一日志key名。
- 拦截器内部对于每个请求,先检查key对应的value是否为空,如果为空则自己生产一个唯一日志id放入请求头。
- 对于所有产生的日志,直接丢入消息队列。
- 利用es异步收集统计所有队列中日志。
根据该方案,即可通过请求附带server_request_id实现日志链路调用分析,具体判断哪个工程模块出现了异常。
具体代码如下:
@Component
@Slf4j
@Order(1)
public class LogFilter implements Filter {
private static final String REQUEST_ID = "server_request_id";
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String requestId = httpRequest.getHeader(REQUEST_ID);
if (requestId == null) {
requestId = UUID.randomUUID().toString();
}
log.info("requestId is: {}", requestId);
MDC.put(REQUEST_ID, requestId);
httpResponse.setHeader(REQUEST_ID, requestId);
try {
chain.doFilter(request, response);
} finally {
MDC.clear();
}
}
}