什么是RootMessageId?

为了理解RootMessageId先简单介绍一下CAT的数据结构设计。CAT客户端会将所有消息都封装为一个完整的消息树(MessageTree),消息树可能包括Transaction、Event、Heartbeat、Metric等类型的消息。具体如下:

  • Transaction:适合记录跨越系统边界的程序访问行为,比如远程调用,数据库调用,也适合执行时间较长的业务逻辑监控,Transaction用来记录一段代码的执行时间和次数
  • Event:用来记录一件事发生的次数,比如记录系统异常,它和transaction相比缺少了时间的统计,开销比transaction要小
  • Heartbeat:表示程序内定期产生的统计信息, 如CPU利用率, 内存利用率, 连接池状态, 系统负载等
  • Metric:用于记录业务指标、指标可能包含对一个指标记录次数、记录平均值、记录总和,业务指标最低统计粒度为1分钟

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

其中,Transaction类型的消息可作为消息树节点,而其他消息只可作为消息树的叶子节点,也就是Transaction是一个可嵌套的递归结构。比如:

消息树的每一节点都有一个属性messageId,用来唯一表示节点本身,其构成为:{domain}-{ip}-{timestamp}-{自增index}。另外还有两个属性,分别是parentMessageId, rootMessageId。parentMessageId表示父节点的messageId;rootMessageId则表示整个消息树的根节点的messageId。这两个属性在之后CAT的调用链分析与分布式调用链分析中发挥了关键作用。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

为什么在日志中记录?

根据RootMessageId可以追踪某一个请求的整个分布式调用链,结合每一条日志快速定位耗费性能的症结,做针对性的性能优化。更加方便地做性能优化,特别是TP95、TP99等指标。

遇到偶尔发生的bug,是最让人头疼的,只有先从日志中找线索,但是在海量的日志中找到出现bug的那一个请求是很困难的。有了上游API提供的RootMessageId,就可以快速过滤出那次请求的所有日志, 更快速更方便地定位线上bug。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

在日志的什么地方记录?

当然是每一句日志上都记录RootMessageId了。有的同学会说,这日志也记录的太多了。当发现线上问题无法定位时,你就会狠日志太少了。其实记录日志不怕多,就怕不全。现在硬盘很便宜了,搞个几T没有问题,另外还可以设置日志清理策略。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

怎么记录到日志中?

前面说了那么多,终于到了今天的压轴大戏了。实现记录到日志有很多种方式,这里使用的是MDC(Mapped Diagnostic Contexts)。顾名思义,其目的是为了便于我们诊断线上问题而出现的方法工具类,目前我们经常使用的logback和log4j都是支持的。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

只需要在每个请求的入口调用MDC.put方法,把rootMessageId赋值进去就可以了,是不是很简单?示例代码:

//在Filter里,从header里获取上下文信息,包括messageId、parentMessageId、rootMessageId
CatContext catContext = new CatContext();
catContext.addProperty(Cat.Context.ROOT, request.getHeader(CatConstants.CAT_HTTP_HEADER_ROOT_MESSAGE_ID));
catContext.addProperty(Cat.Context.PARENT, request.getHeader(CatConstants.CAT_HTTP_HEADER_PARENT_MESSAGE_ID));
catContext.addProperty(Cat.Context.CHILD, request.getHeader(CatConstants.CAT_HTTP_HEADER_CHILD_MESSAGE_ID));
if (catContext.getProperty(Cat.Context.ROOT) == null) {
//如果调用链的顶端,没有上下文信息,需要生成上下文信息
Cat.logRemoteCallClient(catContext);
} else {
Cat.logRemoteCallServer(catContext);
}
MDC.put("traceId", catContext.getProperty(Cat.Context.ROOT));

如果你还不知道怎么集成CAT调用链,可以看看之前的《SpringBoot集成CAT调用链实例

然后,在设置日志输出格式的配置文件里增加[%X{traceId}]

Logback的xml配置示例:

<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true">
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%thread] [%X{traceId}] [%-5level] [%-40.36logger{40}:%-4.4line] - %msg%n</pattern>
</layout>
</appender> <root level="INFO">
<appender-ref ref="CONSOLE" />
</root>
</configuration>

log4j的properties配置示例:

log4j.rootCategory=INFO,stdout,info,error
log4j.rootLooger=warn,stdout,info,error
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%-5p] [%thread] [%X{traceId}] method:%l - %m%n

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

怎么把CAT客户端的RootMessageId记录到每条日志中?的更多相关文章

  1. 深入详解美团点评CAT跨语言服务监控(三)CAT客户端原理

    cat客户端部分核心类 message目录下面有消息相关的部分接口 internal目录包含主要的CAT客户端内部实现类: io目录包含建立服务端连接.重连.消息队列监听.上报等io实现类: spi目 ...

  2. IOS客户端Coding项目记录导航

    IOS客户端Coding项目记录(一) a:UITextField设置出现清除按键 b:绘画一条下划线  表格一些设置 c:可以定义表头跟底部视图(代码接上面) d:隐藏本页的导航栏 e:UIEdge ...

  3. apache 日志中记录代理IP以及真实客户端IP

    vim /usr/local/apach2/conf/httpd.conf 默认情况下log日志格式为:LogFormat "%h %l %u %t \"%r\" %&g ...

  4. CAT客户端如何从Apollo中读取配置?

    运行环境 以下就是这个示例的运行环境,如果版本号不一样,区别也应该不会很大,可以根据实际情况做相应调整. JDK 8 spring boot 2.0.7.RELEASE cat-client 3.0. ...

  5. Entity framewok 如何实现多条记录作为一条取出, for xml path如何实现

    http://www.myexception.cn/linq/1288046.html Entity framewok 怎么实现多条记录作为一条取出, for xml path怎么实现News表:ID ...

  6. 如何让tomcat不记录catalina.out这个日志文件

    tomcat日志记录配置在conf/logging.properties中 有这5类日志 catalina,localhost,manager,admin(控制台),host-manager 还有8个 ...

  7. PHP 错误与异常 笔记与总结(5)配置文件中与错误日志相关的选项 && 将错误记录到指定的文件中

    [记录错误(生产环境)] php.ini: ① 开启 / 关闭 错误日志功能 log_errors = On ② 设置 log_errors 的最大字节数 log_errors_max_len = 其 ...

  8. Java日志记录的5条规则

    日志记录是在软件开发过程中常常需要考虑的关键因素. 当产品运行出错时,日志文件通常是我们进行错误分析的首要选择. 而且,在很多情况下,它们是我们手上唯一可以用来查明发生状况和问题根本原因的信息. 可见 ...

  9. 从客户端(ctl00$ContentPlaceHolder1$result="<?xml version="1.0" ...")中检测到有潜在危险的 Request.Form 值。

    ylbtech-Error-WebForm:从客户端(ctl00$ContentPlaceHolder1$result="<?xml version="1.0" . ...

随机推荐

  1. Jenkins源代码管理(SVN)

    Subversion 安装插件 1.首先将本地的自动化用例打包上传svn 2.配置jenkins源代码管理(每次执行jenkins时,会自动check-out配置地址中的代码到Jenkins的工作空间 ...

  2. [JZOJ5863] 【NOIP2018模拟9.11】移动光标

    Description

  3. 在Hadoop上用Python实现WordCount

    一.简单说明 本例中我们用Python写一个简单的运行在Hadoop上的MapReduce程序,即WordCount(读取文本文件并统计单词的词频).这里我们将要输入的单词文本input.txt和Py ...

  4. 关于vue使用的一些小经验

    这一年来说,vue的势头很猛,用户量“噌”“噌”“噌”的涨 为了不掉队不落伍.在后台大哥的胁迫下,不得不选择用了它 刚开始很难接受vue的写法,在编辑器里很容易报错,基本上每行都会出现红色的波浪线 这 ...

  5. jenkins中使用变量

    查看jenkins内置变量: 1.新建一个job: 2.构建-增加构建步骤-执行shell: 3.点击  可用的环境变量列表 即可查看 如WORKSPACE : 作为工作空间分配给构建目录的绝对路径 ...

  6. ASP.NET Core 使用 JWT 自定义角色/策略授权需要实现的接口

    目录 ① 存储角色/用户所能访问的 API ② 实现 IAuthorizationRequirement 接口 ③ 实现 TokenValidationParameters ④ 生成 Token ⑤ ...

  7. openflow流表项中有关ip掩码的匹配的问题(控制器为ryu)

    一.写在前面 唉,被分配到sdn安全方向,顶不住,顶不住,感觉搞不出来什么有搞头的东西.可若是让我水水的应付,我想我也是做不到的,世上无难事只怕有心人.好了,进入正题,本次要讨论的时一个比较细节的东西 ...

  8. springboot 打jar包时分离配置文件

    修改pom.xml文件 <build> <resources> <resource> <directory>src/main/resources< ...

  9. 【redis】redis的过期策略

    redis过期策略 在使用redis做缓存的时候,我们常常会设置过期时间.那么redis是如何清理这些过期的数据呢? 答案是: 定期删除 + 惰性删除 定期删除: redis每100ms就会随机抽查删 ...

  10. python的GIL锁

    进程:系统运行的一个程序,是系统分配资源的基本单位. 线程:是进程中执行运算的最小单位,是处理机调度的基本单位. 处理机:是计算机中存储程序和数据,并按照程序规定的步骤执行指令的部件.包括中央处理器. ...