环境 springboot 项目
定义一个filter
import lombok.extern.slf4j.Slf4j; import org.slf4j.MDC; import org.springframework.stereotype.Component; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import java.io.IOException; import java.util.UUID; @Component @Slf4j public class LogTraceFilter implements Filter { private final String TRACE_ID = "TRACE_ID"; @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { try{ String traceId = UUID.randomUUID().toString().replace("-", ""); MDC.put(TRACE_ID, traceId); filterChain.doFilter(servletRequest, servletResponse); }catch (Exception e){ log.error("添加traceId出错,错误信息:",e); }finally { MDC.remove(TRACE_ID); } } @Override public void destroy() { } }
log4j2 日志输出中加入traceId
<?xml version="1.0" encoding="UTF-8"?> <!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出--> <!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数--> <configuration monitorInterval="5" > <!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL --> <!--变量配置--> <Properties> <!-- 格式化输出:%date表示日期,%thread表示线程名,%X{TRACE_ID}这个是链路追踪的traceId, %-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符--> <!-- %logger{36} 表示 Logger 名字最长36个字符 --> <property name="LOG_PATTERN" value="%date{HH:mm:ss.SSS} 【%thread】 【%X{TRACE_ID}】 %-5level 【%logger{36}】 - %msg%n"/> <!-- 定义日志存储的路径 --> <property name="FILE_PATH" value="E:\\logs\\test"/> <property name="FILE_NAME" value="springboot-test"/> </Properties> <appenders> <console name="Console" target="SYSTEM_OUT"> <!--输出日志的格式--> <PatternLayout pattern="${LOG_PATTERN}"/> <!--控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--> <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> </console> <!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用--> <File name="Filelog" fileName="${FILE_PATH}/test.log" append="false"> <PatternLayout pattern="${LOG_PATTERN}"/> </File> <!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档--> <RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log" filePattern="${FILE_PATH}/${FILE_NAME}-INFO-%d{yyyy-MM-dd}_%i.log.gz"> <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--> <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="${LOG_PATTERN}"/> <Policies> <!--interval属性用来指定多久滚动一次,默认是1 hour--> <TimeBasedTriggeringPolicy interval="1"/> <SizeBasedTriggeringPolicy size="10MB"/> </Policies> <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖--> <DefaultRolloverStrategy max="15"/> </RollingFile> <!-- 这个会打印出所有的warn及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档--> <RollingFile name="RollingFileWarn" fileName="${FILE_PATH}/warn.log" filePattern="${FILE_PATH}/${FILE_NAME}-WARN-%d{yyyy-MM-dd}_%i.log.gz"> <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--> <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="${LOG_PATTERN}"/> <Policies> <!--interval属性用来指定多久滚动一次,默认是1 hour--> <TimeBasedTriggeringPolicy interval="1"/> <SizeBasedTriggeringPolicy size="10MB"/> </Policies> <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖--> <DefaultRolloverStrategy max="15"/> </RollingFile> <!-- 这个会打印出所有的error及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档--> <RollingFile name="RollingFileError" fileName="${FILE_PATH}/error.log" filePattern="${FILE_PATH}/${FILE_NAME}-ERROR-%d{yyyy-MM-dd}_%i.log.gz"> <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--> <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="${LOG_PATTERN}"/> <Policies> <!--interval属性用来指定多久滚动一次,默认是1 hour--> <TimeBasedTriggeringPolicy interval="1"/> <SizeBasedTriggeringPolicy size="10MB"/> </Policies> <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖--> <DefaultRolloverStrategy max="15"/> </RollingFile> </appenders> <!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。--> <!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效--> <loggers> <!--过滤掉spring和mybatis的一些无用的DEBUG信息--> <logger name="org.mybatis" level="info" additivity="false"> <AppenderRef ref="Console"/> </logger> <!--监控系统信息--> <!--若是additivity设为false,则 子Logger 只会在自己的appender里输出,而不会在 父Logger 的appender里输出。--> <Logger name="org.springframework" level="info" additivity="false"> <AppenderRef ref="Console"/> </Logger> <root level="info"> <appender-ref ref="Console"/> <appender-ref ref="Filelog"/> <appender-ref ref="RollingFileInfo"/> <appender-ref ref="RollingFileWarn"/> <appender-ref ref="RollingFileError"/> </root> </loggers> </configuration>
请求后看日志
18:00:12.730 【http-nio-8080-exec-1】 【d9c6d00bafbb4aefb2502ae97a766f32】 INFO 【com.example.springboottest.test.TestController】 - controller request come in http-nio-8080-exec-1 18:00:12.730 【http-nio-8080-exec-1】 【d9c6d00bafbb4aefb2502ae97a766f32】 INFO 【com.example.springboottest.test.service.impl.TestServiceImpl】 - service request come in http-nio-8080-exec-1 18:00:12.731 【http-nio-8080-exec-1】 【d9c6d00bafbb4aefb2502ae97a766f32】 INFO 【com.example.springboottest.test.service.impl.TestServiceImpl】 - service inner request come in http-nio-8080-exec-1
输出格式改为JSON 格式
可以看到,上边输出的日志格式 非JSON 格式,如果想使用日志输出的格式为 JOSN格式应该怎么办呢?
可以看到上边的log4j2.xml的配置文件 使用的是 PatternLayout ,我们可以改用下边的格式
<JsonLayout compact="true" locationInfo="true" complete="false" eventEol="true" pattern="${LOG_PATTERN}" />
输出结果
{"instant":{"epochSecond":1601169916,"nanoOfSecond":590000000},"thread":"http-nio-8080-exec-2","level":"INFO","loggerName":"com.example.springboottest.test.TestController","message":"controller request come in http-nio-8080-exec-2","endOfBatch":false,"loggerFqcn":"org.apache.logging.slf4j.Log4jLogger","threadId":159,"threadPriority":5,"source":{"method":"sayHello","file":"TestController.java","line":27,"class":"com.example.springboottest.test.TestController"}} {"instant":{"epochSecond":1601169916,"nanoOfSecond":591000000},"thread":"http-nio-8080-exec-2","level":"INFO","loggerName":"com.example.springboottest.test.service.impl.TestServiceImpl","message":"service request come in http-nio-8080-exec-2","endOfBatch":false,"loggerFqcn":"org.apache.logging.slf4j.Log4jLogger","threadId":159,"threadPriority":5,"source":{"method":"doTestService","file":"TestServiceImpl.java","line":14,"class":"com.example.springboottest.test.service.impl.TestServiceImpl"}} {"instant":{"epochSecond":1601169916,"nanoOfSecond":592000000},"thread":"http-nio-8080-exec-2","level":"INFO","loggerName":"com.example.springboottest.test.service.impl.TestServiceImpl","message":"service inner request come in http-nio-8080-exec-2","endOfBatch":false,"loggerFqcn":"org.apache.logging.slf4j.Log4jLogger","threadId":159,"threadPriority":5,"source":{"method":"doTestServiceInner","file":"TestServiceImpl.java","line":20,"class":"com.example.springboottest.test.service.impl.TestServiceImpl"}}
可以看到,输出的格式是JSON格式了,但是我们自己定义的 TRACEID 并没有输出。
我们可以修改为如下结果,添加我们自定义的字段
<JsonLayout compact="true" locationInfo="true" complete="false" eventEol="true" pattern="${LOG_PATTERN}"> <KeyValuePair key="TRACE_ID" value="${ctx:TRACE_ID}"/> </JsonLayout>
输出结果,可以看到,已经有了 TRACEID 字段了
{"instant":{"epochSecond":1601170158,"nanoOfSecond":492000000},"thread":"http-nio-8080-exec-2","level":"INFO","loggerName":"com.example.springboottest.test.TestController","message":"controller request come in http-nio-8080-exec-2","endOfBatch":false,"loggerFqcn":"org.apache.logging.slf4j.Log4jLogger","threadId":158,"threadPriority":5,"source":{"method":"sayHello","file":"TestController.java","line":27,"class":"com.example.springboottest.test.TestController"},"TRACE_ID":"130999f8b5154eecb41e56eca76260b2"} {"instant":{"epochSecond":1601170158,"nanoOfSecond":493000000},"thread":"http-nio-8080-exec-2","level":"INFO","loggerName":"com.example.springboottest.test.service.impl.TestServiceImpl","message":"service request come in http-nio-8080-exec-2","endOfBatch":false,"loggerFqcn":"org.apache.logging.slf4j.Log4jLogger","threadId":158,"threadPriority":5,"source":{"method":"doTestService","file":"TestServiceImpl.java","line":14,"class":"com.example.springboottest.test.service.impl.TestServiceImpl"},"TRACE_ID":"130999f8b5154eecb41e56eca76260b2"} {"instant":{"epochSecond":1601170158,"nanoOfSecond":494000000},"thread":"http-nio-8080-exec-2","level":"INFO","loggerName":"com.example.springboottest.test.service.impl.TestServiceImpl","message":"service inner request come in http-nio-8080-exec-2","endOfBatch":false,"loggerFqcn":"org.apache.logging.slf4j.Log4jLogger","threadId":158,"threadPriority":5,"source":{"method":"doTestServiceInner","file":"TestServiceImpl.java","line":20,"class":"com.example.springboottest.test.service.impl.TestServiceImpl"},"TRACE_ID":"130999f8b5154eecb41e56eca76260b2"}
相关推荐
异构系统链路追踪——滴滴 trace 实践.pdf
引用步骤: 1.基于SpringBoot自动装配,引用jar包即可,坐标如下:...3.日志配置中添加traceId引用,如下: [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%X{traceId}] [%thread] %-5level %logger{80} %line - %msg%n</Pattern>
微服务日志链路追踪-log-trace-spring-boot
traceId :记录整个服务链路的 ID,由首次请求方创建(这里使用zst-service-demo01创建),整个服务链路中唯一 spanId :记录当前服务块的 ID,由当前服务方创建。 parentId :记录上一个请求服务的 spanId 安装教程...
SpringBoot+AOP+TraceID.pdf
Skywalking链路追踪自身耗时和总耗时算法分析
应项目需要,在不改变dubo底层的源码的情况下,实现traceid的穿透,达到在分布式的微服务情况下,实现通过全局唯一id实现整个服务链路的追踪和日志的统一处理。
Best Trace是一款可以在你的设备上发起 traceroute 请求,附带链路可视化的软件,它不仅可以在地图上标注路由的所在位置和AS号,还支持查询本机IP和批量Ping等。
SOFATracer 是一个用于分布式系统调用跟踪的组件,通过统一的 traceId 将调用链路中的各种网络调用情况以日志的方式记录下来,以达到透视化网络调用的目的。这些日志可用于故障的快速发现,服务治理等。 一、背景 在...
写了一个TRACE的小程序,用来打印信息和记录日志。 可以编译Debug版和Release版。 用到了一些宏和VA的知识。 如果想要一起研究,可以找我。 imzzq@hotmail.com
项目介绍本项目仿照...项目默认透传了如下header,可以自动支持jaeger、zipkin链路追踪"x-request-id", "x-b3-traceid", "x-b3-spanid", "x-b3-sampled", "x-b3-flags", "x-b3-parentspanid","x-ot-span-context",
基于dubbo分布式应用集群,日志跟踪变得比以往困难。基于spi的调用拦截,可以将traceid通过rpc context保存下来,并通过MDC输出到日志中去,解决调用跟踪难的问题。
TcpTrace-TCP追踪,C#,Java…… 涉及Tcp的都可以用它追踪到。
本赛题主要是考察链路追踪中的Tail-based Sampling。 问题背景 为了应对各种复杂的业务,系统架构也从单机大型软件演化成微服务架构。微服务构建在不同的软件集上,这些软件模块可能是由不同团队开发的,可能使用...
用Trace与TextWriterTraceListener实现的类似Log4Net的日志工具 很实用,希望有帮助到大家
由于Node.js的 单线程模型 的限制,我们无法设置全局 traceid 来聚合请求,即 实现输出日志与请求的绑定 。如果不实现日志和请求的绑定,我们难以判断日志输出与对应用户请求的对应关系,这对 线上问题排查 带来...
oracle 11g的监听日志和警告日志...其中警告日志在alert目录下,监听日志在trace目录下。listener目录下产生的日志文件比较大,是主要清理的对象,而db1目录下产生的文件比较小,基本不需要清除。在listener目录下监听
用于Flask应用程序的简单日志记录装饰器 用法 只需导入跟踪装饰器并将其应用于您要记录的任何函数。 from flask_trace import trace @ trace def my_awesome_function ( arg1 , arg2 ): pass 现在,对my_awesome_...
程序开发环境中的日志记录是由嵌入在程序中以输出一些对开发人员有用信息的语句所组成。例如,跟踪语句(trace),结构转储和常见的System.out.println或printf调试语句。log4j提供分级方法在程序中嵌入日志记录语句...
加入头文件#include 即可引入日志库 boost中的log库有以下六种级别: BOOST_LOG_TRIVIAL(trace) << A trace severity message; BOOST_LOG_TRIVIAL(debug) << A debug severity message; BOOST_LOG_...