你不得不知的日志级别

news2024/9/21 0:43:26

前言

写日志是一项具有挑战性的任务,在工作中我们常常面临一些困境,比如:

  • 开发人员在编写代码时常常陷入纠结,不确定在何处打印日志才是最有意义的;
  • SRE人员在调查生产问题时可能因为缺乏必要的日志信息而束手无策;
  • 运维人员在面对处理海量日志时往往需要耗费大量的精力进行维护;
  • 项目管理者面对大量的无实际业务价值的日志,往往不愿投入过多人力和财力进行管理。

这些问题导致了许多矛盾的产生。然而,当问题出现时,我们需要依赖日志记录来建立一种**“不在场证明”,**找出哪一方有问题。

正是由于这种需求,我们在开发应用程序时需要遵循良好的实践,选择成熟的日志收集机制和管理方案,从而缓解这些矛盾。

请在此添加图片描述

矛盾的起因

  • 首先,我们探讨为何需要记录日志以及日志的作用。

实际上,对于大多数开发人员来说,在调试代码问题、解决不同环境的 Bug 时,日志的价值是显而易见的。作为调试的得力助手和生产环境中不可或缺的救星。

通过查询日志,我们能够确定代码的执行过程API请求的正确性核心业务数据的准确性以及是否存在错误的堆栈信息等等操作,这些条件也构成了开发和运维人员判断代码和生产问题的首要手段。在一个复杂庞大的系统中,如果没有记录任何日志,那么在排查生产环境中的 Bug 时将变得极为困难。

  • 若每一行代码都记录上下文,是否就能解决所有问题呢?

理论上确实是可行的,但目前仍存在一些无法解决的问题。

首先是日志存储量的问题,典型的中大型系统日志可能达到TB级,而超大型系统的日志规模甚至可能达到PB级。

这对于存储而言是一个巨大的挑战。其次是搜索性能的下降,常见的日志存储方案如Elasticsearch数据库在面对海量日志时,可能导致维护的映射关系急剧增长,即使划分不同的索引、分布式管理不同的ElasticSearch集群,也难以做到搜索性能不随数据量增加而下降。最后,海量日志的生成可能在峰值时拖慢系统性能,增加出现故障的风险。

因此,日志既不能记录过多导致存储和管理困难,也不能因记录过少而导致运维人员无法排查问题。尽管听起来似乎自相矛盾,但这正是关于日志重要所在!在日志记录中,我们需要在**“太多”“太少”**之间找到平衡点,以确保既能有效排查问题同时又能够高效管理和存储日志。

日志级别

在决定记录日志之前,通常需要考虑选择适当的日志级别。在讨论如何确定日志级别之前,我们先来了解一下日志级别的作用。

  • 确定日志信息的优先级: 通过设定不同的日志级别,我们可以对日志信息进行优先级排序,从而有效减少信息噪音和警报疲劳。不同的日志级别对应不同的信息重要性,开发人员可以根据当前需求选择适当的级别,确保在解决问题或分析系统行为时能够集中关注最重要的信息。
  • 在查询日志时进行过滤: 添加日志级别的过滤可以在查询日志时更加精准地获取所需的信息。例如,在调试阶段可能需要详细的调试信息,而在生产环境中可能只关心警告和错误级别的日志。通过合理使用日志级别,可以提高日志的可读性和查询效率,同时降低处理冗余信息的成本。

因此,选择适当的日志级别是一项关键决策,它能够在不同场景中平衡信息的详细程度,帮助开发人员和运维人员更好地理解和管理系统的行为。

常见的日志级别有以下几类,并且从高到低的顺序是:致命(FATAL)、错误(ERROR)、警告(WARN)、信息(INFO)、调试(DEBUG)、痕迹(TRACE)和全部(ALL)

致命错误警告信息调试痕迹全部
致命X
错误XX
警告XXX
信息XXXX
调试XXXXX
痕迹XXXXXX
全部XXXXXXX
  • **FATAL:**严重错误级别,表示系统无法继续运行。
  • **ERROR:**错误级别,用于记录错误信息。
  • **WARN:**警告级别,表示潜在的问题,但不影响程序的运行。
  • **INFO:**信息级别,用于记录程序的正常运行信息。
  • **DEBUG:**调试级别,用于详细记录调试信息。
  • **TRACE:**追踪级别,提供比DEBUG更详细的信息。
  • **ALL:**最低级别,用于启用所有日志记录。

常见场景

场景

某工程师在调查生产环境中某个创建资源的 API 性能问题时,发现该 API 接口中打印了INFO 级别的日志,导致业务峰期时出现海量日志,耗尽 Buffer 区内存,拖慢主线程,影响服务性能。

后续功能优化中工程师删除了写业务INFO级别日志的操作以解决性能问题。

然而,由于某天修改了 API 服务调用链路上的某服务代码,导致 API 创建出的对象存在错误。但是在生产环境中缺少了该资源的日志,工程师无法准确排查问题。在这种情况下,工程师可能需要重新修改日志级别,将业务日志重新启用,并重新构建发布上线,

场景

假设将生产环境的日志设置为 ERROR 级别。某一时刻,依赖的下游服务故障,导致请求大量超时。由于业务峰期 QPS 非常高,短时间内集中产生大量错误日志,导致磁盘 IO ****急剧提高,消耗大量 CPU,导致整个服务瘫痪。

场景

某工程师在排查生产问题时,发现 INFO 级别的日志无法满足排查根本原因。他需要 DEBUG 级别的日志,但生产环境只配置为 INFO 级别。

日志级别规范与动态调整

日志级别的规范和动态调整有助于在开发、调试和生产环境中更有效地管理日志信息。

日志级别规范

  • **TRACE:**在开发期间可以使用,但确保不要将它们提交到版本控制系统中,以避免不必要的日志信息混入生产环境。
  • **DEBUG:**在进入生产阶段之前,对调试语句进行审查和缩减,只保留最关键、最有意义的调试信息。
  • **INFO:**记录用户驱动的事件或系统的特定操作。这可以包括定期计划的任务、用户登录等。保持信息简洁明了,避免过多的冗余信息。
  • **WARN:**记录可能成为错误的事件。例如,耗时较长的操作、接近容量的内存缓存等。允许设置自动警报,以及在故障排除期间更好地了解系统在故障之前的行为。
  • **ERROR:**记录每个错误条件,包括 API 调用返回的错误或内部错误条件。
  • **FATAL:**只用于表示整个服务已经无法工作的情况。通常,FATAL 级别记录表示程序的结束。

动态调整日志级别

配置文件动态调整

使用配置文件(如 logback.xml 或 log4j2.xml)来配置日志级别。这样,可以在不重新启动应用程序的情况下调整日志级别。

  • logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>

    <!-- 使用springProperty引用配置文件中的属性 -->
    <!-- <property resource="application.properties" /> -->

    <!-- 定义一个变量,用于动态设置日志级别 -->
    <property name="logLevel" value="INFO" />

    <!-- 控制台输出 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <!--
            日志输出格式:
                %d表示日期时间,
                %thread表示线程名,
                %-5level:级别从左显示5个字符宽度
                %logger{50} 表示logger名字最长50个字符,否则按照句点分割。
                %msg:日志消息,
                %n是换行符
        -->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 指定日志级别为变量引用的值 -->
    <root level="${logLevel}">
        <appender-ref ref="console" />
    </root>

    <!-- 添加一个TurboFilter,用于动态更改日志级别 -->
    <turboFilter class="com.example.demo.config.LoggerNameChangeFilter" />

</configuration>
  • log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info">
    <!-- 定义日志输出的方式,这里使用控制台输出 -->
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <!-- 定义日志输出的格式 -->
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
    </Appenders>

    <!-- 配置日志级别 -->
    <Loggers>
        <!-- 根日志级别设置为info -->
        <Root level="info">
            <AppenderRef ref="Console"/>
        </Root>

        <!-- 设设置特定包(com.example.myapp)的日志级别为debug,additivity="false"表示不向父Logger传递日志。 -->
        <Logger name="com.example.myapp" level="debug" additivity="false">
            <AppenderRef ref="Console"/>
        </Logger>
    </Loggers>
</Configuration>

  • logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <!-- 引入Spring Boot基础日志配置 -->
    <include resource="org/springframework/boot/logging/logback/base.xml"/>

    <!-- 自定义Logback配置开始 -->

    <!-- 示例:添加一个自定义的控制台输出appender -->
    <appender name="customConsoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 示例:将自定义的控制台appender添加到根logger -->
    <root level="INFO">
        <appender-ref ref="customConsoleAppender"/>
    </root>

    <!-- 自定义Logback配置结束 -->

</configuration>

logback-spring.xml 可以通过配置,定时地检测配置修改,但是这会带来额外的资源消耗。

<configuration scan="true" scanPeriod="30 seconds" > 
 <!-- ... 具体配置 -->
</configuration>
  • 使用外部配置中心,例如 Spring Cloud Config,可以通过远程配置动态更改日志级别。
<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <!-- 引入Spring Boot基础日志配置 -->
    <include resource="org/springframework/boot/logging/logback/base.xml"/>

    <!-- 使用Spring表达式动态配置根logger的日志级别 -->
    <root level="${LOG_LEVEL:-INFO}">
        <appender-ref ref="CONSOLE"/>
    </root>

</configuration>

在这里,${LOG_LEVEL:-INFO} 使用了Spring表达式,它会从Spring Cloud Config中获取名为LOG_LEVEL的配置,如果未配置则默认为INFO级别。

JMX(Java Management Extensions)

使用 JMX 允许在运行时修改日志级别。

通过 JConsole,VisualVM 或其他 JMX 工具,可以直接管理日志框架的运行时配置。

application.propertiesapplication.yml 中启用 JMX:

spring.jmx.enabled=true

远程管理工具

使用远程管理工具,例如 Spring Boot Actuator,可以通过 HTTP 端点或其他远程管理手段动态调整日志级别。

Spring Boot Actuator 为Spring Boot应用程序提供了丰富的监控和管理功能。通过使用HTTP Endpoint(端点)或JMX(Java Management Extensions)来监视和管理应用程序,从而更好地理解其运行状况并进行调整。

确保在pom.xml中添加了Spring Boot Actuator的依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

配置application.yml文件

# 设置日志级别为INFO
logging:
  level:
    root: INFO

# 允许Actuator修改日志配置
management:
  endpoints:
    web:
      exposure:
        include: loggers

最后,使用curl命令查看和修改日志级别:

  • 查看日志配置:
curl -X GET http://localhost:8080/actuator/loggers

你会看到根日志记录器的级别是INFO。

  • 修改日志级别:
curl -X POST http://localhost:8080/actuator/loggers/com.example -H 'Content-Type: application/json' -d '{"configuredLevel": "DEBUG"}'

这会将com.example包下的日志级别设置为DEBUG。

条件日志

在关键代码路径中使用条件日志,根据配置的条件来决定是否记录日志。这样可以更灵活地控制日志输出。

在 application.properties 或 application.yml 中添加一个属性,表示是否启用条件日志:

myapp.logging.enabled=true

创建一个类来进行条件日志,使用 @ConditionalOnProperty 注解来根据配置的条件来判断是否创建这个类的 Bean。这个类可以用于条件日志记录。

@Configuration
@ConditionalOnProperty(name = "myapp.logging.enabled", havingValue = "true")
public class ConditionalLoggerConfig

集成监控系统

将日志级别调整集成到监控系统中,例如 Prometheus、Grafana 等,以便在需要时能够通过监控界面进行动态调整。

总结

综合利用这些方法,可以在不同的环境和阶段更好地管理日志级别,既保持足够的信息用于排查问题,又避免在生产环境中过度记录冗余信息。

参考链接:

  • Spring Boot Actuator 官方文档:https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html
  • Spring Boot Actuator GitHub 仓库:https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-actuator

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

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

相关文章

基于SSM的“高校学生社团管理系统”的设计与实现(源码+数据库+文档)

基于SSM的“高校学生社团管理系统”的设计与实现&#xff08;源码数据库文档) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SSM 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统结构图 首页 注册 登录 后台首页界面 社团公告页面 留…

Engage2024用户大会成功举办,数聚股份携手销售易共绘数字化转型新篇章

2024年9月5日&#xff0c;销售易第六届用户大会Engage2024在上海盛大举行。销售易&#xff0c;作为唯一一家入选Gartner SFA魔力象限、且产品能力全球前四的国产CRM软件&#xff0c;当之无愧是国产CRM软件的龙头&#xff0c;其用户大会自然就是CRM领域盛会&#xff0c;汇聚了众…

生命周期函数

所有继承MonoBehavior的脚本 最终都会挂载到Gameobiject游戏对象上 1.生命周期西数 就是该脚本对象依附的Gameobject对象从出生到消亡整个生命周期中 会通过反射自动调用的一些特殊函数 2.Unity帮助我们记录了一个Gameobject对象依附了哪些脚本 会自动的得到这些对象&#x…

视频监控系统中的云镜控制PTZ详细介绍,以及视频监控接入联网平台相关协议对PTZ的支持

目录 一、PTZ概述 二、PTZ 控制的应用场景 1、公共场所 2、安全监控 3、交通监控 4、工业生产环境中的质量监控 5、大型活动的现场直播或录制 三、PTZ摄像的优缺点 1、优点 2、缺点 四、PTZ控制的基本原理 1、云台控制 2、镜头控制 五、 PTZ 控制协议 1. Pelco-…

深度学习时遇到tensor([0.], device=‘cuda:0‘)等输出

更改了数据集后进行训练遇到了以下输出&#xff0c;精度正常提升&#xff0c;训练正常&#xff0c;就是精度和map之间又很多输出&#xff0c;如下&#xff1a; tensor([0.], devicecuda:0), tensor([0.], devicecuda:0), tensor([0.], devicecuda:0), tensor([0.], devicecuda…

NAT技术+代理服务器+内网穿透

NAT技术 IPv4协议中&#xff0c;会存在IP地址数量不充足的问题&#xff0c;所以不同的子网中会存在相同IP地址的主机。那么就可以理解为私有网络的IP地址并不是唯一对应的&#xff0c;而公网中的IP地址都是唯一的&#xff0c;所以NAT&#xff08;Network Address Translation&…

往复密封问题的两个问题

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

使用ChatGPT高质量撰写文献综述全攻略实操指南,五步轻松搞定!

大家好,感谢关注。我是七哥,一个在高校里不务正业,折腾学术科研AI实操的学术人。关于使用ChatGPT等AI学术科研的相关问题可以和作者七哥(yida985)交流,多多交流,相互成就,共同进步,为大家带来最酷最有效的智能AI学术科研写作攻略。 在学术研究中,文献综述很重要,但…

无线感知会议系列【2】【智能无感感知 特征,算法,数据集】

前言&#xff1a; 这篇来自 2022 泛在可信智能感知 论坛 作者&#xff1a; 清华大学杨铮教授 视频&#xff1a; 2.智能无线感知&#xff1a;特征、算法、数据集&#xff1b; 杨峥 清华大学 副教授_哔哩哔哩_bilibili 这篇论文前面有讲过,我前面的博客也有基于提供的数据集做了…

关于打不开SOAMANAGER如何解决

参考文章&#xff1a;https://blog.csdn.net/yannickdann/article/details/115396035 打开SE93

Python字典实战题目练习,巩固知识、检查技术

本文主要是作为Python中列表的一些题目&#xff0c;方便学习完Python的列表之后进行一些知识检验&#xff0c;感兴趣的小伙伴可以试一试&#xff0c;含选择题、判断题、实战题&#xff0c;答案在第四章。 在做题之前可以先学习或者温习一下Python的列表&#xff0c;推荐阅读下面…

沃尔玛测评防关联技术:自养号攻略全面解析

防关联技术 1.使用国外的服务器和防火墙&#xff1a;为了确保测评活动的隐蔽性和安全性&#xff0c;卖家应选择使用国外的服务器&#xff0c;并通过远程搭建一个安全终端防火墙。这样可以阻断硬件参数的关联问题&#xff0c;降低被沃尔玛平台检测到的风险。 2.创建住宅专线IP…

《食品安全导刊》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答 问&#xff1a;《食品安全导刊》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的正规学术期刊。 问&#xff1a;《食品安全导刊》级别&#xff1f; 答&#xff1a;国家级。主管单位&#xff1a; 中国商业联合会 主办单…

解析DNS查询报文,探索DNS工作原理

目录 1. 用 tcpdump工具监听抓包 2. 用 host 工具获取域名对应的IP地址 3. 分析DNS以太网查询数据帧 3.1 linux下查询DNS服务器IP地址 3.2 DNS以太网查询数据帧 &#xff08;1&#xff09;数据链路层 &#xff08;2&#xff09;网络层 &#xff08;3&#xff09;传输层…

NC 和为K的连续子数组

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 描述 给定一个无序…

基于SpringBoot+Vue+MySQL的影院购票系统

系统展示 用户前台界面 管理员后台界面 系统背景 基于SpringBoot、Vue.js与MySQL的影院购票系统&#xff0c;实现了从后端服务到前端展示及数据库管理的全栈开发。该系统通过SpringBoot构建高效稳定的RESTful API&#xff0c;处理用户注册登录、影片信息查询、座位选择、在线购…

无人直播好帮手,视频指定词语消音,消除违禁词,直播视频录制,音视频分离,分段

1.视频消音功能 一键删除或者静音视频中的词语 2.直播视频录制功能 可同时录制多个平台,多个主播,没有数量限制 3.音视频转码 支持多种音视频格式转换 4.视频频分离 分离视频中的音频和视频 5.视频合并分割 合并和按时间分割视屏 目前正在测试中…如有需要可以先使…

【C语言从不挂科到高绩点】16-作用域和自定义头文件

Hello&#xff01;彦祖们&#xff0c;俺又回来了&#xff01;&#xff01;&#xff01;&#xff0c;继续给大家分享 《C语言从不挂科到高绩点》课程!! 本节将为大家讲解C语言中的函数&#xff1a; 本套课程将会从0基础讲解C语言核心技术&#xff0c;适合人群&#xff1a; 大学…

LLM 大模型研习:当下热门 AI 大模型的生成原理与逻辑

前言 在过去数年里&#xff0c;人工智能领域迎来了前所未有的变革&#xff0c;其中大规模预训练模型的崛起尤为引人注目。像GPT系列、BERT、T5、DALLE和CLIP等模型&#xff0c;凭借强大的语言理解与生成能力&#xff0c;在自然语言处理&#xff08;NLP&#xff09;、计算机视觉…

Android Auto助力电动汽车智能驾驶

随着技术的飞速发展&#xff0c;电动汽车&#xff08;EVs&#xff09;成为未来出行的重要趋势。然而&#xff0c;EVs 的普及不仅仅代表环保选择&#xff0c;它们还推动了智能汽车技术的发展。Android Auto 的集成无疑为电动汽车用户带来了更便捷和智能的驾驶体验。 一、智能互联…