Arthas logger 命令完全指南:查看 logger 信息与动态更新日志级别
Arthas logger 命令完全指南查看 logger 信息与动态更新日志级别【免费下载链接】arthasAlibaba Java Diagnostic Tool Arthas/Alibaba Java诊断利器Arthas项目地址: https://gitcode.com/gh_mirrors/ar/arthaslogger是 ArthasAlibaba Java Diagnostic Tool内置的核心诊断命令之一用于实时查看目标 JVM 中已加载的日志框架Log4j、Logback、Log4j2的 logger 配置信息并支持在不重启应用的前提下动态调整日志级别。本指南以官方文档 logger.md 为骨架结合 core 模块中 LoggerCommand.java 及其配套 Helper 类的源码实现完整讲解该命令的每个参数、典型输出与底层原理帮助你在生产环境排障时快速定位日志为什么没打出来如何临时打开 DEBUG等实际问题。命令能力概览logger命令一句话总结查看 logger 信息更新 logger level。它由 LoggerCommand.java 通过注解声明注册在 BuiltinCommandPack.java 的内置命令列表中支持以下四类操作查看所有 logger 信息默认只打印带有 appender 的 logger查看指定名字的 logger 信息-n查看指定 ClassLoader 下的 logger 信息-c/--classLoaderClass更新指定 logger 的 level--name--level从源码可以看到命令支持的框架自动探测基于三个已知类名org.apache.log4j.Logger、ch.qos.logback.classic.Logger、org.apache.logging.log4j.Logger因此它对 Log4j 1.x、Logback、Log4j 2.x 三大家族均可生效见 LoggerCommand.java。参数速查表根据 LoggerCommand.java 中的注解定义logger命令的全部参数如下参数长参数说明默认值-n--name指定 logger 名称如org.springframework.web空查看全部-c--classloader指定 ClassLoader 的 hashcodeSystemClassLoader无--classLoaderClass用 ClassLoader 的类名定位需唯一实例无-l--level设置 logger 级别如debug、info无无--include-no-appender同时打印没有 appender 的 loggerfalse其中--level选项单独使用时无意义必须与--name组合才会触发更新级别分支process方法中只有name ! null level ! null时才走level(process)更新逻辑否则一律走loggers(process)查看逻辑见 LoggerCommand.java。查看所有 logger 信息准备一份 logback.xml以下面的logback.xml为例包含滚动文件 appender、异步 appender 和控制台 appender 三种典型形态?xml version1.0 encodingUTF-8? configuration appender nameAPPLICATION classch.qos.logback.core.rolling.RollingFileAppender fileapp.log/file rollingPolicy classch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy fileNamePatternmylog-%d{yyyy-MM-dd}.%i.txt/fileNamePattern maxFileSize100MB/maxFileSize maxHistory60/maxHistory totalSizeCap2GB/totalSizeCap /rollingPolicy encoder pattern%logger{35} - %msg%n/pattern /encoder /appender appender nameASYNC classch.qos.logback.classic.AsyncAppender appender-ref refAPPLICATION / /appender appender nameCONSOLE classch.qos.logback.core.ConsoleAppender encoder pattern%-4relative [%thread] %-5level %logger{35} - %msg %n /pattern charsetutf8/charset /encoder /appender root levelINFO appender-ref refCONSOLE / appender-ref refASYNC / /root /configuration执行命令与输出解读在 Arthas 控制台直接输入logger[arthas2062]$ logger name ROOT class ch.qos.logback.classic.Logger classLoader sun.misc.Launcher$AppClassLoader2a139a55 classLoaderHash 2a139a55 level INFO effectiveLevel INFO additivity true codeSource file:/Users/hengyunabc/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar appenders name CONSOLE class ch.qos.logback.core.ConsoleAppender classLoader sun.misc.Launcher$AppClassLoader2a139a55 classLoaderHash 2a139a55 target System.out name APPLICATION class ch.qos.logback.core.rolling.RollingFileAppender classLoader sun.misc.Launcher$AppClassLoader2a139a55 classLoaderHash 2a139a55 file app.log name ASYNC class ch.qos.logback.classic.AsyncAppender classLoader sun.misc.Launcher$AppClassLoader2a139a55 classLoaderHash 2a139a55 appenderRef [APPLICATION]从appenders信息中可以确认三件事CONSOLEappender 的target是System.out控制台输出APPLICATION是RollingFileAppender其file为app.log滚动文件输出ASYNC的appenderRef是APPLICATION即异步包装后输出到文件输出字段与 LoggerHelper.java 中定义的常量一一对应name、class、classLoader、classLoaderHash、codeSource、level、effectiveLevel、additivity、appendersappender 级还有file、blocking、appenderRef、target。字段填充逻辑见 LogbackHelper.javalevel取 logger 自身配置的级别effectiveLevel取向上继承后的有效级别两者不一致说明该 logger 自身未显式配置 levelcodeSource来自类所在的 jar 包路径可用来确认应用实际加载的日志框架版本。无 appender 过滤规则getLoggers的实现中遍历loggerContext.getLoggerList()时默认会过滤掉没有 appender 的 logger见 LogbackHelper.java。这正是直接执行logger输出不会很长的原因。查看指定名字的 logger当需要聚焦某个具体 logger例如排查 Spring Web 层的日志级别时使用-n指定名称[arthas2062]$ logger -n org.springframework.web name org.springframework.web class ch.qos.logback.classic.Logger classLoader sun.misc.Launcher$AppClassLoader2a139a55 classLoaderHash 2a139a55 level null effectiveLevel INFO additivity true codeSource file:/Users/hengyunabc/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar注意此处level为null、effectiveLevel为INFO说明org.springframework.web这个 logger 自身没有显式配置级别实际生效的INFO是从 ROOT 继承来的。这一组字段能直接解释为什么我改了配置但日志级别没变——很可能改动落在了一个未显式配置的 logger 上。从源码看-n传入的name会透传给各 Helper 的getLoggers(name, includeNoAppender)Logback 通过loggerContext.exists(name)精确查找见 LogbackHelper.javaLog4j2 通过configuration.getLoggerConfig(name)查找且对非 ROOT 名称会排除查不到时回落到 ROOT的误匹配见 Log4j2Helper.java。指定 ClassLoader 查看 logger使用 -c 指定 hashcode注意 hashcode 是动态变化的需要先通过classloader命令或sc -d查看当前 ClassLoader 信息提取对应 ClassLoader 的 hashcode 后手动输入[arthas2062]$ logger -c 2a139a55 name ROOT class ch.qos.logback.classic.Logger classLoader sun.misc.Launcher$AppClassLoader2a139a55 classLoaderHash 2a139a55 level DEBUG effectiveLevel DEBUG additivity true codeSource file:/Users/hengyunabc/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar appenders name CONSOLE class ch.qos.logback.core.ConsoleAppender classLoader sun.misc.Launcher$AppClassLoader2a139a55 classLoaderHash 2a139a55 target System.out name APPLICATION class ch.qos.logback.core.rolling.RollingFileAppender classLoader sun.misc.Launcher$AppClassLoader2a139a55 classLoaderHash 2a139a55 file app.log name ASYNC class ch.qos.logback.classic.AsyncAppender classLoader sun.misc.Launcher$AppClassLoader2a139a55 classLoaderHash 2a139a55 appenderRef [APPLICATION]在loggers(process)中-c的 hashcode 用于过滤getAllLoadedClasses()返回的每个类只有当类的StringUtils.classLoaderHash(clazz)与指定 hashcode 一致时才纳入统计见 LoggerCommand.java从而只展示该 ClassLoader 体系内的 logger。使用 --classLoaderClass 指定类名对于只有唯一实例的 ClassLoader可以更直观地通过类名指定无需查询动态 hashcodelogger --classLoaderClass sun.misc.Launcher$AppClassLoader两点注意事项这里的classLoaderClass是 ClassLoader 的类名Java 8 下是sun.misc.Launcher$AppClassLoaderJava 11 下则是jdk.internal.loader.ClassLoaders$AppClassLoader--classLoaderClass只有在匹配到唯一ClassLoader 实例时才能工作匹配到多个实例时命令会返回失败并提示改用-c classloader hash精确定位。该逻辑在 LoggerCommand.java 中实现通过ClassLoaderUtils.getClassLoaderByClassName查找恰好 1 个时自动换算成 hashcode 继续执行多于 1 个时输出匹配列表并报错Found more than one classloader by class name...。更新 logger level基本更新将 ROOT logger 的级别临时调整为debug[arthas2062]$ logger --name ROOT --level debug update logger level success.更新成功后日志立即生效无需重启应用。该操作走level(process)分支先确定目标 ClassLoader再调用对应框架 Helper 的updateLevel(name, level)。以 Logback 为例内部通过loggerContext.exists(name)找到 Logger 后执行logger.setLevel(l)level 字符串经Level.toLevel(level, Level.ERROR)解析未识别时兜底为ERROR见 LogbackHelper.java。指定 classloader 更新 level默认情况下logger命令会在SystemClassLoader下执行见 LoggerCommand.java。如果应用是传统war应用或由 spring boot fat jar 启动日志框架可能加载在自定义 ClassLoader 中此时需要先定位其 hashcode先执行sc -d yourClassName查看具体类的 ClassLoader hashcode更新 level 时通过-c指定该 hashcode[arthas2062]$ logger -c 2a139a55 --name ROOT --level debug如果未指定正确的 ClassLoader更新可能失败命令会提示Update logger level fail. Try to specify the classloader with the -c option. Use sc -d CLASSNAME to find out the classloader hashcode.该提示正是 LoggerCommand.java 中更新失败的输出文案。查看没有 appender 的 logger默认情况下logger命令只打印有 appender 的 logger。如果想了解全部 logger 的继承关系与有效级别例如确认某个包是否因为继承了过高级别而静默丢日志可以加上--include-no-appender参数[arthas2062]$ logger --include-no-appender name ROOT class ch.qos.logback.classic.Logger classLoader sun.misc.Launcher$AppClassLoader2a139a55 classLoaderHash 2a139a55 level DEBUG effectiveLevel DEBUG additivity true codeSource file:/Users/hengyunabc/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar appenders name CONSOLE class ch.qos.logback.core.ConsoleAppender classLoader sun.misc.Launcher$AppClassLoader2a139a55 classLoaderHash 2a139a55 target System.out name APPLICATION class ch.qos.logback.core.rolling.RollingFileAppender classLoader sun.misc.Launcher$AppClassLoader2a139a55 classLoaderHash 2a139a55 file app.log name ASYNC class ch.qos.logback.classic.AsyncAppender classLoader sun.misc.Launcher$AppClassLoader2a139a55 classLoaderHash 2a139a55 appenderRef [APPLICATION] name com class ch.qos.logback.classic.Logger classLoader sun.misc.Launcher$AppClassLoader2a139a55 classLoaderHash 2a139a55 level null effectiveLevel DEBUG additivity true codeSource file:/Users/hengyunabc/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar name com.alibaba class ch.qos.logback.classic.Logger classLoader sun.misc.Launcher$AppClassLoader2a139a55 classLoaderHash 2a139a55 level null effectiveLevel DEBUG additivity true codeSource file:/Users/hengyunabc/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar ...注意通常输出结果会很长因为像com、com.alibaba这类仅作为命名空间存在、没有配置任何 appender 的 logger 也会被全部列出。建议与-n组合使用以缩小范围。源码级原理命令如何跨 ClassLoader 工作logger命令最精巧的地方在于Arthas 自身通过独立 ClassLoader 加载而目标应用中的日志框架位于业务 ClassLoader 内两者互不可见。源码用三步解决了注入 反射调用的问题类型探测遍历Instrumentation.getAllLoadedClasses()分别以ch.qos.logback.core.Appender.class、org/apache/logging/log4j/core/LoggerContext.class等资源是否可加载来判断该 ClassLoader 中实际存在哪种日志框架见 LoggerCommand.javaHelper 类重命名注入LogbackHelper、Log4jHelper、Log4j2Helper的字节码被读取后经 AsmRenameUtil.java 重命名追加 Arthas ClassLoader 与目标 ClassLoader 的 hashcode 后缀再通过ReflectUtils.defineClass定义到目标业务 ClassLoader中避免类冲突见 LoggerCommand.java反射调用通过getLoggers(String, boolean)或updateLevel(String, String)方法反射执行结果以 LoggerModel 形式返回并渲染模型类型为logger。各框架 Helper 的实现差异也值得注意LogbackLogbackHelper.java通过 SLF4J 的ILoggerFactory获取LoggerContext还会反射读取PatternLayoutBase.head与ThrowableProxyConverter.lengthOption字段Log4j 1.xLog4jHelper.java通过LogManager.getLoggerRepository()操作 logger 仓库更新时优先exists(name)名称匹配 ROOT 时直接设置根 logger 级别Log4j 2.xLog4j2Helper.java基于LogManager.getContext(false)拿到LoggerContext与Configuration更新时若目标LoggerConfig不存在则动态创建最后调用updateLoggers()刷新同时通过反射读取LoggerConfig.config字段输出配置对象。这一机制保证了logger命令面对复杂部署形态fat jar、war、OSGi、多个 ClassLoader 并存时依然能够准确读写目标框架的状态。实战建议排查日志突然不打了先logger -n 你的Logger名查看level与effectiveLevel再确认 appender 是否还在快速区分级别过滤与appender 丢失两类问题临时放开 DEBUGlogger --name 包名 --level debug排障结束后用同样命令改回原级别避免线上日志量暴涨多 ClassLoader 应用统一先sc -d 目标类拿到 hashcode再配合-c操作避免误改到 SystemClassLoader 下并不生效的配置批量巡检logger --include-no-appender输出较长配合-n或终端管道过滤查看聚焦关键包路径。【免费下载链接】arthasAlibaba Java Diagnostic Tool Arthas/Alibaba Java诊断利器Arthas项目地址: https://gitcode.com/gh_mirrors/ar/arthas创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →