Sleuth+logback 设置traceid 及自定义信息方式


Posted in Java/Android onJuly 26, 2021

Sleuth+logback 设置traceid及自定义信息

背景:

分布式系统中,如何快速定位某个用户的请求日志?

使用Sleuth生成的traceid可以跟踪某个请求,但是很多时候我们需要知道traceid 与某个用户的映射关系,方便定位某个用户的日志

方案:

@Component
@Order(TraceWebServletAutoConfiguration.TRACING_FILTER_ORDER + 1)
public class CustomHttpSpanExtractor extends GenericFilterBean {
    private final Tracer tracer;
    CustomHttpSpanExtractor(Tracer tracer) {
        this.tracer = tracer;
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        Span currentSpan = this.tracer.currentSpan();
        if (currentSpan == null) {
            chain.doFilter(request, response);
            return;
        }
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        try {
          //  mdc(httpRequest,currentSpan.context().traceIdString());
            MDC.put(MdcConstant.USER_ID,"userid-12345");
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            chain.doFilter(request, response);
        } finally {
            MDC.clear();//must be,threadLocal
        }
    }}

logback 配置

<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS}[${applicationName},%X{X-B3-TraceId:-},%X{userId:-}] [%thread] %-5level %logger{50} - %msg%n</pattern>

Sleuth+logback 设置traceid 及自定义信息方式

logback简单使用,自定义key

1.logback的pom依赖

<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>4.11</version>
</dependency>

2.配置文件: logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="false" scanPeriod="5000" debug="false">
 <springProperty scope="context" name="springAppName" source="spring.application.name" defaultValue="defaultAppName"/>
 <timestamp key="bySecond" datePattern="yyyy-MM-dd HH:mm:ss"/>   
 <appender name="STASH-REDIS" class="com.jlb.yts.common.util.aop.RedisAppender">
        <key>${springAppName:-}</key>
  <!-- <filter class="ch.qos.logback.classic.filter.LevelFilter">  
            <level>ALL</level>  
            <onMatch>ACCEPT</onMatch>  
            <onMismatch>DENY</onMismatch>  
        </filter> -->
  <layout>
   <pattern>
    {
    "time": "%d{yyyy-MM-dd HH:mm:ss}",
    "application":"tech_cloud",
    "subapplication":"${springAppName:-}",
    "level": "%level",
    "trace": "%X{X-B3-TraceId:-}",
    "span": "%X{X-B3-SpanId:-}",
    "parent": "%X{X-B3-ParentSpanId:-}",
    "classname": "%logger{100}",
    "msg": "%message"
    }
            </pattern>
  </layout>
    </appender>
    <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender"> 
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
        <queueSize>5120</queueSize>
        <appender-ref ref="STASH-REDIS" />
    </appender>
 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
     <encoder charset="UTF-8">
       <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{40} - %msg%n</pattern>
     </encoder>
    </appender>
    <logger name="com.jlb.yts" additivity="true" level="ERROR">
     <appender-ref ref="ASYNC" />
    </logger>
    <logger name="com.jlb.yts" additivity="true" level="INFO">
     <appender-ref ref="ASYNC" />
    </logger>
    <!-- mongodb打印语句 -->
 <logger name="org.springframework.data.mongodb.core" level="DEBUG"/>
    <logger name="com.jlb.yts" additivity="true" level="DEBUG">
     <appender-ref ref="ASYNC" />
    </logger>
    <root level="INFO">
     <appender-ref ref="STDOUT" />
    </root>
</configuration>

3.自定义appender

package com.jlb.yts.common.util.aop;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.IThrowableProxy;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.classic.spi.StackTraceElementProxy;
import ch.qos.logback.core.Layout;
import ch.qos.logback.core.UnsynchronizedAppenderBase;
import ch.qos.logback.core.filter.Filter;
import com.jlb.yts.common.util.redis.RedisHandle;
import com.jlb.yts.common.util.redis.ReidsConnect;
import net.logstash.logback.layout.LoggingEventCompositeJsonLayout;
import java.lang.reflect.Field;
public class RedisAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
 public static String service;
 
 Layout<ILoggingEvent> layout;
 public void setFilter(Filter<ILoggingEvent> filter) {
  if(filter != null){
   this.addFilter(filter);
  }
 }
 
 String key = null;
 public RedisAppender() {
  layout = new LoggingEventCompositeJsonLayout();
 }
 private final static RedisHandle redisHandle = ReidsConnect.init("redis-log.properties","redis-log.properties");
 @Override
 protected void append(ILoggingEvent event) {
  try {
   LoggingEvent loggingEvent = (LoggingEvent) event;
   String json = layout.doLayout(loggingEvent);
   redisHandle.addList(key,json);
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   
  }
 }
 
 public String getKey() {
  return key;
 }
 public void setKey(String key) {
  String prefix = (System.getenv("APPLICATION_ENV") == null)?"dev":System.getenv("APPLICATION_ENV");
  key = prefix + "-" + key;
  this.key = key;
 }
 public Layout<ILoggingEvent> getLayout() {
  return layout;
 }
 public void setLayout(Layout<ILoggingEvent> layout) {
  this.layout = layout;
 }
}

4.代码实例

//注意导入的包都是slf4j的包
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogbackTest {
    private static final Logger LOGGER = LoggerFactory.getLogger(LogbackTest.class);
    public static void main(String[] args) {
        LOGGER.trace("logback的--trace日志--输出了");
        LOGGER.debug("logback的--debug日志--输出了");
        LOGGER.info("logback的--info日志--输出了");
        LOGGER.warn("logback的--warn日志--输出了");
        LOGGER.error("logback的--error日志--输出了");
    }
}

5.日志添加自定义KEY

import org.slf4j.MDC;
MDC.put(key, value);

logback.xml 配置

"key":"%X{key:-}"

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Java/Android 相关文章推荐
总结一下关于在Java8中使用stream流踩过的一些坑
Jun 24 Java/Android
eclipse创建项目没有dynamic web的解决方法
Jun 24 Java/Android
Java多条件判断场景中规则执行器的设计
Jun 26 Java/Android
Java常用函数式接口总结
Jun 29 Java/Android
Java中多线程下载图片并压缩能提高效率吗
Jul 01 Java/Android
springboot 启动如何排除某些bean的注入
Aug 02 Java/Android
JPA 通过Specification如何实现复杂查询
Nov 23 Java/Android
SpringCloud Function SpEL注入漏洞分析及环境搭建
Apr 08 Java/Android
Java字符缓冲流BufferedWriter
Apr 09 Java/Android
Spring Boot项目如何优雅实现Excel导入与导出功能
Jun 10 Java/Android
Java多线程并发FutureTask使用详解
Jun 28 Java/Android
Java实现超大Excel文件解析(XSSF,SXSSF,easyExcel)
Jul 15 Java/Android
Java日常练习题,每天进步一点点(38)
Jul 26 #Java/Android
dubbo集成zipkin获取Traceid的实现
Jul 26 #Java/Android
dubbo服务整合zipkin详解
spring boot中nativeQuery的用法
Jul 26 #Java/Android
java泛型通配符详解
Jul 25 #Java/Android
SpringBoot SpringEL表达式的使用
Jul 25 #Java/Android
SpringRetry重试框架的具体使用
You might like
php多文件上传下载示例分享
2014/02/20 PHP
php车辆违章查询数据示例
2016/10/14 PHP
Zend Framework路由器用法实例详解
2016/12/11 PHP
PJ Blog修改-禁止复制的代码和方法
2006/10/25 Javascript
jquery多行滚动/向左或向上滚动/响应鼠标实现思路及代码
2013/01/23 Javascript
循环 vs 递归浅谈
2013/02/28 Javascript
学习JavaScript设计模式(策略模式)
2015/11/26 Javascript
JS设置cookie、读取cookie
2016/02/24 Javascript
AngularJS入门教程之控制器详解
2016/07/27 Javascript
在Docker快速部署Node.js应用的详细步骤
2016/09/02 Javascript
jQuery双向列表选择器DIV模拟版
2016/11/01 Javascript
easyui combotree加载静态数据问题(选不上)解决方法
2016/12/26 Javascript
angularjs利用directive实现移动端自定义软键盘的示例
2017/09/20 Javascript
JavaScript中正则表达式使数字、中文或指定字符高亮显示
2017/10/31 Javascript
Vue.js 实现微信公众号菜单编辑器功能(二)
2018/05/08 Javascript
对angularJs中自定义指令replace的属性详解
2018/10/09 Javascript
Vue从TodoList中学父子组件通信
2019/02/05 Javascript
微信小程序实现单个卡片左滑显示按钮并防止上下滑动干扰功能
2019/12/06 Javascript
jQuery 函数实例分析【函数声明、函数表达式、匿名函数等】
2020/05/19 jQuery
多线程爬虫批量下载pcgame图片url 保存为xml的实现代码
2013/01/17 Python
Python工程师面试题 与Python基础语法相关
2016/01/14 Python
Python实现更改图片尺寸大小的方法(基于Pillow包)
2016/09/19 Python
Python 共享变量加锁、释放详解
2019/08/28 Python
有趣的Python图片制作之如何用QQ好友头像拼接出里昂
2020/04/22 Python
Python selenium爬虫实现定时任务过程解析
2020/06/08 Python
python爬取代理ip的示例
2020/12/18 Python
HTML+CSS+JavaScript实现图片3D展览的示例代码
2020/10/12 HTML / CSS
美国最大的宠物用品零售商:PetSmart
2016/11/14 全球购物
微软澳洲官方网站:Microsoft Australia
2017/01/10 全球购物
Martinelli官方商店:西班牙皮鞋和高跟鞋品牌
2019/07/30 全球购物
英语硕士生求职简历的自我评价
2013/10/15 职场文书
亮剑精神演讲稿
2014/05/23 职场文书
2014年党建工作总结
2014/11/11 职场文书
2015年语文教研组工作总结
2015/05/23 职场文书
学会感恩主题班会
2015/08/12 职场文书
浅谈Redis的事件驱动模型
2022/05/30 Redis