2026/9/20 19:31:17

CAT 与 Logback 集成实战:通过 CatLogbackAppender 将业务日志无缝上报至 CAT

CAT 与 Logback 集成实战:通过 CatLogbackAppender 将业务日志无缝上报至 CAT CAT 与 Logback 集成实战通过 CatLogbackAppender 将业务日志无缝上报至 CAT【免费下载链接】catCAT 作为服务端项目基础组件提供了 Java, C/C, Node.js, Python, Go 等多语言客户端已经在美团点评的基础架构中间件框架MVC框架RPC框架数据库框架缓存框架等消息队列配置系统等深度集成为美团点评各业务线提供系统丰富的性能指标、健康状况、实时告警等。项目地址: https://gitcode.com/gh_mirrors/ca/cat本文以 CAT大众点评开源的实时应用监控平台为服务端、Logback 为应用侧日志框架讲解如何通过 CAT 官方提供的CatLogbackAppender将业务系统日志接入 CAT 监控链路。读完本文你将掌握logback.xml的完整接入配置、Appender 的源码级执行原理ERROR 日志自动上报、Trace 模式全量上报两种路径以及如何借助请求头X-CAT-TRACE-MODE开启链路追踪级日志采集。一、为什么需要 CAT 自定义的 Logback AppenderCAT 是服务端项目的基础监控组件提供了 Java、C/C、Node.js、Python、Go 等多语言客户端被深度集成进美团点评基础架构中间件框架MVC 框架、RPC 框架、数据库框架、缓存框架、消息队列、配置系统等用于为各业务线提供性能指标、健康状况、实时告警等能力。在 Java 服务中Logback 是最主流的日志实现之一。若希望在既有 Logback 日志体系下把程序中的异常与关键日志同步上报到 CAT最轻量的方式就是引入 CAT 官方实现的 Appendercom.dianping.cat.logback.CatLogbackAppender。它位于本仓库的 integration/logback/CatLogbackAppender.java完整实现仅约 70 行却完成了「Logback 日志事件 → CAT 消息树Message Tree」的桥接让每条 ERROR 日志都能在 CAT 控制台形成可检索的异常事件。二、logback.xml 接入配置原文档核心配置官方说明位于 integration/logback/README.md如果需要使用 CAT 自定义的 Appender需要在logback.xml中添加如下配置appender nameCatAppender classcom.dianping.cat.logback.CatLogbackAppender/appender root levelinfo appender-ref refCatAppender / /root2.1 配置要点拆解nameCatAppenderAppender 的引用名称可自定义但appender-ref refCatAppender /必须与之一致。classcom.dianping.cat.logback.CatLogbackAppender指向 CAT 提供的 Appender 实现类Logback 会通过反射实例化它。注意该类位于integration目录下的独立工程接入时需要把该模块或对应的 jar纳入依赖。root levelinforoot logger 的级别门槛。从源码看Appender 内部会独立判断日志级别是否达到ERROR因此这里把级别设为INFO时INFO、WARN级别日志只有在开启 Trace 模式时才会被上报见下文「Trace 模式」一节ERROR及以上始终会上报。2.2 一份更完整的可运行示例为了实际可运行可以在上述配置基础上补充 CAT 客户端所需的appenders与encoder仅用于日志输出格式不影响 CAT 上报configuration !-- CAT 自定义 Appender把日志桥接到 CAT 监控平台 -- appender nameCatAppender classcom.dianping.cat.logback.CatLogbackAppender/appender !-- 业务日志文件输出可选用于本地留存 -- appender nameFILE classch.qos.logback.core.rolling.RollingFileAppender filelogs/app.log/file encoder pattern%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n/pattern /encoder /appender root levelinfo appender-ref refCatAppender / appender-ref refFILE / /root /configuration其中CatAppender不依赖encoder——它直接消费ILoggingEvent从事件对象上取级别、消息与异常堆栈而不是读取格式化后的文本因此上报内容与你的输出 pattern 无关。三、源码解析CatLogbackAppender 的两条上报路径CatLogbackAppender继承自 Logback 核心类ch.qos.logback.core.AppenderBaseILoggingEvent所有 Logback 日志事件ILoggingEvent都会进入重写的append(ILoggingEvent event)方法。核心逻辑位于 integration/logback/CatLogbackAppender.java#L15-L28Override protected void append(ILoggingEvent event) { try { boolean isTraceMode Cat.getManager().isTraceMode(); Level level event.getLevel(); if (level.isGreaterOrEqual(Level.ERROR)) { logError(event); } else if (isTraceMode) { logTrace(event); } } catch (Exception ex) { throw new LogbackException(event.getFormattedMessage(), ex); } }由此可以看出 Appender 的分流策略日志级别 ≥ ERROR无条件进入logError将异常上报为 CAT 的Event级别 ERROR 且当前线程处于 Trace 模式进入logTrace将日志上报为 CAT 的Trace级别 ERROR 且未开启 Trace 模式直接丢弃不做任何上报避免低频业务日志刷爆 CAT。整个append被try/catch包裹一旦内部出现异常会包装为LogbackException抛出——这是 Logback 官方推荐的异常处理方式保证 Appender 自身的故障不会静默吞掉。3.1 logError异常日志上报为 CAT Event见 integration/logback/CatLogbackAppender.java#L30-L42private void logError(ILoggingEvent event) { ThrowableProxy info (ThrowableProxy) event.getThrowableProxy(); if (info ! null) { Throwable exception info.getThrowable(); Object message event.getFormattedMessage(); if (message ! null) { Cat.logError(String.valueOf(message), exception); } else { Cat.logError(exception); } } }关键细节从event.getThrowableProxy()取出ThrowableProxy再解包得到真正的Throwable。只有当日志事件携带异常对象时才会走 ERROR 上报路径如果ERROR级别日志没有携带异常这里不会上报。因此业务侧应尽量使用logger.error(xxx, exception)这种带异常参数的写法。最终调用Cat.logError(message, exception)或Cat.logError(exception)。这两个静态方法定义在客户端 cat-client/src/main/java/com/dianping/cat/Cat.java#L93-L105内部通过TraceContextHelper.threadLocal().newEvent(message, cause)创建异常Event并complete()从而把异常记入当前线程的 CAT 消息树。3.2 logTraceTrace 模式下全量日志上报见 integration/logback/CatLogbackAppender.java#L44-L61private void logTrace(ILoggingEvent event) { String type Logback; String name event.getLevel().toString(); Object message event.getFormattedMessage(); String data; if (message instanceof Throwable) { data buildExceptionStack((Throwable) message); } else { data event.getFormattedMessage().toString(); } ThrowableProxy info (ThrowableProxy) event.getThrowableProxy(); if (info ! null) { data data \n buildExceptionStack(info.getThrowable()); } Cat.logTrace(type, name, 0, data); }关键细节type固定为Logback所有经此路径上报的 Trace 在 CAT 控制台上统一归入Logback类型便于检索聚合。name取日志级别字符串INFO、WARN、DEBUG等会作为 Trace 名称方便区分不同级别的日志。status固定为0表示上报的日志视为成功状态这是Cat.logTrace(type, name, status, nameValuePairs)四参重载的约定用法见 cat-client/src/main/java/com/dianping/cat/Cat.java#L279-L289。data为日志文本若日志消息本身是Throwable或事件携带ThrowableProxy则会拼接异常堆栈。异常堆栈的格式化由buildExceptionStack完成见 integration/logback/CatLogbackAppender.java#L63-L71它使用初始容量 2048 的StringWriter配合PrintWriter调用exception.printStackTrace将完整堆栈转换为字符串避免大量堆栈文本造成多次扩容。四、Trace 模式何时开启、如何开启上述源码中Cat.getManager().isTraceMode()是决定低级别日志是否上报的开关。其实现位于客户端消息管理器 lib/java/src/main/java/com/dianping/cat/message/internal/DefaultMessageManager.java#L183-L191本质是查询当前线程上下文Context.isTraceMode()因此Trace 模式是按请求/线程维度生效的。在 Web 应用中最常见的开启方式是携带请求头。CAT 的 Servlet 过滤器 lib/java/src/main/java/com/dianping/cat/servlet/CatFilter.java#L223-L230 会读取请求头private void logTraceMode(HttpServletRequest req) { String traceMode X-CAT-TRACE-MODE; String headMode req.getHeader(traceMode); if (true.equals(headMode)) { Cat.getManager().setTraceMode(true); } }也就是说当某个请求携带X-CAT-TRACE-MODE: true请求头时该请求线程上的 Logback 日志即使级别低于 ERROR也会全部上报为Logback类型的 Trace。这在排查单次问题请求时非常有用平时日志量可控需要深挖某个请求时再打开 Trace 开关。同类逻辑也出现在 integration/URL/CatFilter.java#L68-L81 等接入示例中。五、与其他日志框架接入的横向对照本仓库在integration目录下还提供了 Log4j 1.x 与 Log4j 2 的同类实现它们与 Logback 版本共享同一套设计日志框架实现类文件路径Logbackcom.dianping.cat.logback.CatLogbackAppenderintegration/logback/CatLogbackAppender.javaLog4j 1.xCatAppenderintegration/log4j/CatAppender.javaLog4j 2Log4j2Appenderintegration/log4j2/Log4j2Appender.java三者的核心分支完全一致先判断Cat.getManager().isTraceMode()ERROR及以上走logErrorTrace 模式下走logTrace。因此本文的配置与原理同样适用于其他日志框架的接入。六、接入步骤与最佳实践6.1 接入三步走引入依赖将integration/logback模块含com.dianping.cat.logback.CatLogbackAppender以及 CAT 客户端com.dianping.cat.Cat对应 cat-client 模块或 lib/java 客户端加入工程 classpath。由于CatLogbackAppender依赖ch.qos.logback.core.AppenderBase、ch.qos.logback.classic.spi.ILoggingEvent等类工程本身需使用 Logback 1.x 的logback-classic/logback-core。配置logback.xml按上文「接入配置」一节添加CatAppender并挂到root。验证上报在代码中主动抛出一条带异常的logger.error(..., e)在 CAT 控制台对应 domain 下检索到该异常 Event即接入成功。6.2 最佳实践建议ERROR 日志务必携带异常对象logError仅在getThrowableProxy() ! null时才上报纯文本logger.error(msg)不会被上报。若希望纯文本 ERROR 也进入 CAT可结合 Trace 模式或改用显式Cat.logError调用。用 Trace 模式控制日志量默认情况下只有 ERROR 级异常会流入 CAT避免低级别日志造成消息量暴涨需要全量排查时再对目标请求开启X-CAT-TRACE-MODE: true。不要忘记 CAT 客户端的初始化Cat.getManager()依赖 CAT 客户端的CatBootstrap初始化domain、路由等配置Appender 本身不负责初始化客户端请确保 CAT 客户端配置如client.xml在应用启动时加载。区分文件日志与 CAT 上报CatAppender不会把日志写到本地文件本地留存仍需要RollingFileAppender等文件 Appender二者互不冲突、可并存。七、小结CatLogbackAppender用极简的配置和实现把 Logback 日志体系与 CAT 监控平台无缝衔接ERROR异常自动上报为 CAT 异常事件Trace 模式下全量日志以Logback类型上报为链路日志。配合请求头X-CAT-TRACE-MODE开发者可以在保持日常低开销的同时按需深入分析单条请求的完整日志轨迹。更多上下文可参阅官方配置说明 integration/logback/README.md 与实现源码 CatLogbackAppender.java。【免费下载链接】catCAT 作为服务端项目基础组件提供了 Java, C/C, Node.js, Python, Go 等多语言客户端已经在美团点评的基础架构中间件框架MVC框架RPC框架数据库框架缓存框架等消息队列配置系统等深度集成为美团点评各业务线提供系统丰富的性能指标、健康状况、实时告警等。项目地址: https://gitcode.com/gh_mirrors/ca/cat创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考