MDC日志logback整合使用

MDC日志logback整合使用

为什么使用MDC记录日志?

场景:

由于我的搜索服务并发量比较高,而处理一次搜索请求需要记录多个日志,因此日志特别多的情况下去查一次搜索整个日志打印情况会比较复杂。

解决方案:

  1. 可以使用用户id作为唯一标识,但是这种方案每次打印日志都需要传入用户id,并且如果一次请求涉及多线程场景下用户id传递会特别复杂,并且有的用户没有登录拿不到用户id
  2. 每来一次搜索请求根据UUID生成一个标识作为traceId然后通过MDC记录这个traceId

效果:
在这里插入图片描述

入门指南:

maven pom.xml配置

        <dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.7</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId><version>1.1.7</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-access</artifactId><version>1.1.7</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.1.7</version></dependency>

logback.xml 配置:

注意:将需要打印的traceId配置到pattern中,可以根据你业务配置成userId、sessionId等等

    <appender name="console" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern><!-- 设置日志输出格式 -->[%date{ISO8601}] [%-5level] - [%thread] [%X{traceId}] - %msg %rootException %n</pattern></encoder></appender>

完整配置:

<!-- 级别从高到低 OFF 、 FATAL 、 ERROR 、 WARN 、 INFO 、 DEBUG 、 TRACE 、 ALL -->
<!-- 日志输出规则 根据当前ROOT 级别,日志输出时,级别高于root默认的级别时 会输出 -->
<!-- 以下 每个配置的 filter 是过滤掉输出文件里面,会出现高级别文件,依然出现低级别的日志信息,通过filter 过滤只记录本级别的日志 -->
<!-- scan 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。 -->
<!-- scanPeriod 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="60 seconds" debug="false"><!-- 动态日志级别 --><jmxConfigurator /><!-- 定义日志文件 输出位置 --><!-- <property name="log_dir" value="C:/test" />--><property name="log_dir" value="/app" /><!-- 日志最大的历史 30天 --><property name="maxHistory" value="30" /><!-- ConsoleAppender 控制台输出日志 --><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern><!-- 设置日志输出格式 -->[%date{ISO8601}] [%-5level] - [%thread] [%X{traceId}] - %msg %rootException %n</pattern></encoder></appender><!-- ERROR级别日志 --><!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 RollingFileAppender --><appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 过滤器,只记录WARN级别的日志 --><!-- 果日志级别等于配置级别,过滤器会根据onMath 和 onMismatch接收或拒绝日志。 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 设置过滤级别 --><level>ERROR</level><!-- 用于配置符合过滤条件的操作 --><onMatch>ACCEPT</onMatch><!-- 用于配置不符合过滤条件的操作 --><onMismatch>DENY</onMismatch></filter><!-- 最常用的滚动策略,它根据时间来制定滚动策略.既负责滚动也负责出发滚动 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!--日志输出位置 可相对、和绝对路径 --><fileNamePattern>${log_dir}/error/%d{yyyy-MM-dd}/error-log.log</fileNamePattern><!-- 可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件假设设置每个月滚动,且<maxHistory>是6, 则只保存最近6个月的文件,删除之前的旧文件。注意,删除旧文件是,那些为了归档而创建的目录也会被删除 --><maxHistory>${maxHistory}</maxHistory></rollingPolicy><encoder><pattern><!-- 设置日志输出格式 -->%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger - %msg%n</pattern></encoder></appender><!-- WARN级别日志 appender --><appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 过滤器,只记录WARN级别的日志 --><!-- 果日志级别等于配置级别,过滤器会根据onMath 和 onMismatch接收或拒绝日志。 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 设置过滤级别 --><level>WARN</level><!-- 用于配置符合过滤条件的操作 --><onMatch>ACCEPT</onMatch><!-- 用于配置不符合过滤条件的操作 --><onMismatch>DENY</onMismatch></filter><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!--日志输出位置 可相对、和绝对路径 --><fileNamePattern>${log_dir}/warn/%d{yyyy-MM-dd}/warn-log.log</fileNamePattern><maxHistory>${maxHistory}</maxHistory></rollingPolicy><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger - %msg%n</pattern></encoder></appender><!-- INFO级别日志 appender --><appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender"><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>INFO</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${log_dir}/info/%d{yyyy-MM-dd}/info-log.log</fileNamePattern><maxHistory>${maxHistory}</maxHistory></rollingPolicy><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger - %msg%n</pattern></encoder></appender><!-- DEBUG级别日志 appender --><appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender"><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>DEBUG</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${log_dir}/debug/%d{yyyy-MM-dd}/debug-log.log</fileNamePattern><maxHistory>${maxHistory}</maxHistory></rollingPolicy><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger - %msg%n</pattern></encoder></appender><!-- TRACE级别日志 appender --><appender name="TRACE" class="ch.qos.logback.core.rolling.RollingFileAppender"><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>TRACE</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${log_dir}/trace/%d{yyyy-MM-dd}/trace-log.log</fileNamePattern><maxHistory>${maxHistory}</maxHistory></rollingPolicy><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger - %msg%n</pattern></encoder></appender><!-- root级别 DEBUG --><root><!-- 打印debug级别日志及以上级别日志 --><level value="debug" /><!-- 控制台输出 --><appender-ref ref="console" /><!-- 文件输出 --><appender-ref ref="ERROR" /><appender-ref ref="INFO" /><appender-ref ref="WARN" /><appender-ref ref="DEBUG" /><appender-ref ref="TRACE" /></root>
</configuration>

java使用:

    @Testpublic void traceIdTest(){MDC.put("traceId", "traceId:f9e287fad9e84cff8b2c2f2ed92adbe6");logger.info("级别从高到低");MDC.clear();}

控制台打印:

[2021-05-11 17:43:53,804] [INFO ] - [main] [traceId:f9e287fad9e84cff8b2c2f2ed92adbe6] - 级别从高到低

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/508791.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何合理的配置线程数?

文章目录题记Java并发编程实战美团技术团队追求参数设置合理性线程池参数动态化题记 我想不管是在面试中、还是工作中&#xff0c;我们总会面临这种问题&#xff0c;那么到底有没有一种计算公式去告诉我们如何去配置呢&#xff1f; 答案是&#xff1a;没有 想要合理的配置线…

基于CompletableFuture并发任务编排实现

文章目录并发任务编排实现不带返回值/参数传递任务串行执行并行执行并行执行-自定义线程池阻塞等待&#xff1a;多并行任务执行完再执行任意一个任务并发执行完就执行下个任务串并行任务依赖场景带返回值/参数传递任务带返回值实现串行执行多线程任务串行执行对任务并行执行&am…

搜索研发工程师需要掌握的一些技能

文章目录基础语言数据结构与算法工程方面搜索相关搜索主要模块电商搜索流程分词相关搜索召回相似度算法相关词推荐排序相关国美搜索搜索算法工程师需要掌握的技能基础 语言 大部分公司用的是Solr、ElasticSearch&#xff0c;都是基于Java实现的&#xff0c;因此熟悉掌握Java语…

Flink入门看完这篇文章就够了

文章目录第一章&#xff1a;概述第一节&#xff1a;什么是Flink&#xff1f;第二节&#xff1a;Flink特点&#xff1f;第三节&#xff1a;Flink应用场景&#xff1f;第四节&#xff1a;Flink核心组成第五节&#xff1a;Flink处理模型&#xff1a;流处理和批处理第六节&#xff…

管理实践-教练技术的应用

文章目录简介课程学习的工具总结深度倾听3R原则倾听地图&#xff1a;开放式提问层次提问和SMART提问框架BIA积极性反馈GROW模型简介 最近在参加管理培训课程&#xff0c;学习《教练式指导》一课&#xff0c;现将内容总结分享一下。 课程学习的工具总结 深度倾听3R原则 工具…

spark整合MySQL

spark整合MySQL <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.38</version></dependency>import java.sql.{Connection, DriverManager, PreparedStatement} import org…

DataFrame不同风格比较

DataFrame不同风格比较 一&#xff0c;DSL风格语法 //加载数据 val rdd1sc.textFile("/person.txt").map(x>x.split(" ")) //定义一个样例类 case class Person(id:String,name:String,age:Int) //把rdd与样例类进行关联 val personRDDrdd1.map(x>…

sparkSQL操作hiveSQL

sparkSQL操作hiveSQL <dependency><groupId>org.apache.spark</groupId><artifactId>spark-hive_2.11</artifactId><version>2.3.3</version></dependency>import org.apache.spark.sql.SparkSession//todo:利用sparksql操作h…

sparksql加载mysql表中的数据

sparksql加载mysql表中的数据 <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.38</version> </dependency>import java.util.Propertiesimport org.apache.spark.SparkCon…

sparksql保存数据常见操作

sparksql保存数据操作 import org.apache.spark.SparkConf import org.apache.spark.sql.{DataFrame, SparkSession}//todo:sparksql可以把结果数据保存到不同的外部存储介质中 object SaveResult {def main(args: Array[String]): Unit {//1、创建SparkConf对象val sparkCon…

sparksql自定义函数

sparksql中自定义函数 import org.apache.spark.sql.api.java.UDF1 import org.apache.spark.sql.types.StringType import org.apache.spark.sql.{DataFrame, SparkSession}//TODO:自定义sparksql的UDF函数 一对一的关系 object SparkSQLFunction {def main(args: Array[S…

sparksql整合hive

sparksql整合hive 步骤 1、需要把hive安装目录下的配置文件hive-site.xml拷贝到每一个spark安装目录下对应的conf文件夹中2、需要一个连接mysql驱动的jar包拷贝到spark安装目录下对应的jars文件夹中3、可以使用spark-sql脚本 后期执行sql相关的任务 启动脚本 spark-sql \ --…

hive的一些常见内置函数

hive行转列 selectt1.base,concat_ws(|, collect_set(t1.name)) namefrom(selectname,concat(constellation, "," , blood_type) basefromperson_info) t1group byt1.base;hive列转行 select movie, category_name from movie_info lateral view explode(category)…

hive的一些调优参数

hive的一些调优参数 set hive.exec.dynamic.partition.modenonstrict; 使用动态分区 set hive.exec.max.dynamic.partitions100000;自动分区数最大值 set hive.exec.max.dynamic.partitions.pernode100000; set hive.hadoop.supports.splittable.combineinputformattrue;支持切…

hive的SerDe序列化

hive使用Serde进行行对象的序列与反序列化。最后实现把文件内容映射到 hive 表中的字段数据类型。 HDFS files –> InputFileFormat –> <key, value> –> Deserializer –> Row objectRow object –> Serializer –> <key, value> –> Outp…

窗口函数和hive优化简记

窗口函数&#xff1a; &#xff08;1&#xff09; OVER()&#xff1a;指定分析函数工作的数据窗口大小&#xff0c;这个数据窗口大小可能会随着行的变而变化。常用partition by 分区order by排序。 &#xff08;2&#xff09;CURRENT ROW&#xff1a;当前行 &#xff08;3&…

Kafka一些参数配置

Producer消息发送 producer.send(msg); // 用类似这样的方式去发送消息&#xff0c;就会把消息给你均匀的分布到各个分区上去 producer.send(key, msg); // 订单id&#xff0c;或者是用户id&#xff0c;他会根据这个key的hash值去分发到某个分区上去&#xff0c;他可以保证相同…

hive避免MR的情况

什么情况下Hive可以避免进行MapReduce hive 为了执行效率考虑&#xff0c;简单的查询&#xff0c;就是只是select&#xff0c;不带count,sum,group by这样的&#xff0c;都不走map/reduce&#xff0c;直接读取hdfs目录中的文件进行filter过滤。 sql select * from employee; …

flink常见算子的一些操作

常见Transformation操作 map和filter /*** 数据源&#xff1a;1 2 3 4 5.....源源不断过来* 通过map打印一下接受到数据* 通过filter过滤一下数据&#xff0c;我们只需要偶数*/ public class MapDemo {public static void main(String[] args) throws Exception {StreamExecut…

flink的watermark参考配置

需求描述&#xff1a;每隔5秒&#xff0c;计算最近10秒单词出现的次数。 TimeWindow实现 /*** 每隔5秒计算最近10秒单词出现的次数*/ public class TimeWindowWordCount {public static void main(String[] args) throws Exception{StreamExecutionEnvironment env StreamExe…