日志问题精要:分析与总结

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 该文档讲述了应用系统日志记录的重要性和规则。主要目的是记录操作轨迹、监控系统状态和回溯故障。日志记录点包括系统入口、调用其他模块、调用结束、出口和出错时。内容应遵循UTF-8编码,避免敏感信息,按INFO级别记录,及时、完整且安全。日志输出要控制频率和长度,不影响系统性能,并按策略备份和清理。日志等级分为DEBUG、INFO、WARN、ERROR和FATAL。日志文件应有明确目录结构,大小有限制,并定期清理。注意事项包括输出异常堆栈、避免打印对象实例的hashCode、选择合适的日志框架和格式,并支持动态修改日志级别。还要实现链路追踪,确保在多线程环境中正确记录日志。

 记录应用系统日志主要有三个原因:记录操作轨迹、监控系统运行状况、回溯系统故障。 记录操作轨迹:可以数据化分析用户偏好,有助于优化系统业务逻辑,为用户提供个性化服务。如:通过access.log记录用户的操作频率和跳转链接,有助于分析用户后续行为。监控系统运行状况:全面有效的日志系统有助于建立完善的应用监控体系。通过应用监控体系,可以实时监控系统运行状况,及时预警,避免故障发送。系统运行状况是指服务器的运行状态,如内存、CPU等使用情况;应用运行状况,如接口RT(响应时间)、QPS等。应用错误信息,如NPE、SQL异常、数据转换失败等。回溯系统故障:完整的现场日志方便快速定位问题,并迅速处理

一、日志的记录点要求

在程序执行过程中,以下5类日志记录点必须记录日志:

本系统接受到外部请求时(本地入口);

本系统调用其他模块或系统时(调用其他);

本系统调用其他模块或系统结束时(调用结束);

本系统处理结束时(本地出口);

本系统捕捉到错误时(出错时);

初始化参数时

初始化参数在各种框架里面可以看到一些内容,而在自己开发的业务中则使用打印业务参数阅读相关内容 系统核心角色,组件关键动作 :主要是核心业务的触发动作,但是需要避免非常高频率的打印,同时对于日志进行提炼 上述日志记录点,除出错时,均应该按[INFO]级别登记

二、日志的记录内容规则

应用程序日志原则上使用UTF-8字符编码,以便于将来的日志文件分析。 不要使用系统输出记录日志,如System.out.print, printStackTrace。不能将应用日志写入生产环境基础系统的日志。(如SystemErr.log、SystemOut.log); 日志记录应及时、完整,日志应该符合安全规范,不要在日志信息里包含安全敏感信息,敏感信息主要有客户身份信息如客户账号、名称、证件号、交易核心信息如交易金额、交易备注、安全控制信息如安全认证方式、密码。

1.日志输出不允许影响系统正常运行。

2.日志输出需符合安全审计要求,不允许产生安全问题,不允许输出敏感信息,支持保密机制。

3.日志输出格式严格按照要求、合理的打印信息,如对于交易日志,必须记录,对于程序调试中非关键节点的日志交付前进行删除,无需记录

4.日志输出内容能够提供开发和运维人员快速定位到故障问题原因。

5.日志按照一定的策略支持备份,如日期、时间等。

6.最小10M,缺省情况下,每个日志文件的大小限制为100M,超过限制,则必须写入到另一个带新序号的日志文件中

7.一定要控制日志输出量,以免出现磁盘空间不足。同时要为日志设置合理的生命周期,及时清理过期日志。避免重复打印,务必在日志配置文件中设置additivity=false

三、日志的性能要求

1、输出日志记录不能过于频繁。一般情况下10毫秒内不能输出3条以上日志信息;

2、输出的日志内容不能过长。一般情况下每行日志信息原则上不能超过2K字节,一条日志输出代码产生的日志内容不能超过40行;

3、输出日志信息的函数代码不能包含复杂的CPU计算,导致产生过多的CPU。

4.不建议打印查询list,尤其没有分页的

5.控制日志输出的长度在一定范围内,比如请求参数,避免打印大量的业务日志 如日志layout中 msg配置为 %.-4096msg,输出日志长度最长为4096字节,多余的将从后面截断不打印;

6.【建议】在循环,响应式编程中谨慎log

7.【建议】批量任务,大量mq,不建议每行均打印

8.【建议】gateway等网关中log需谨慎, gateway默认线程数很少,等你打印io线程消耗性能,遇到上传文件+报文解密+打印日志的时候,并发能力下降到2位数

9.【建议】报文加/解密 前后打印log,没必要 和第三方交互时,入参、出参可能是需要加密和解密,如果报文体积较大,明文和密文都打印没有意义,算法测试成功后,个人认为加解密成功的情况下打印明文,计算失败时异常中打印原文即可

10.【建议】如果开源jar包日志需要特别注意 如shardingsphere-jdbc等,需要关闭日志 如无法关闭,可以设置独立的logger,和其他应用日志分开 mybatis,eureka心跳等日志建议分开打印,不要和业务日志混在一起 日志按用途划分,避免业务日志,框架日志,混合,业务日志也应分模块打印: https://www.jb51.net/article/247048.htm,且日志使用rolling进行分割

11.在tps有高要求的场景应该异步打印,参考:https://www.cnblogs.com/yangyongjie/p/16230247.html

四、日志的等级分类

DEBUG 细粒度的、对出错(debug)、以及系统调试时候输出的信息、事件。

INFO 在正常运行状态中,粗粒度的、关于重要流程/事件的、可用来表示系统健康度的信息、事件。在INFO级别不允许把SQL语句、报文等这些作为日志内容输出。

WARN 有潜在风险的、不会造成大危害的错误(往往由应用外部因素造成,如不正确的输入数据)

ERROR 应用发生错误(包括业务错误和技术错误),但后续流程还能够继续进行 FATAL 应用发生严重错误(技术型异常),应用服务被终止。

五、日志的目录和文件名

1.应用日志输出至/app/logs目录下;

2.应用日志文件名以.log后缀结尾;

3.应用日志中每行以[LEVEL][yyyy-MM-dd HH:mm:ss,SSS]开头;

4.把不同类型的日志分离出去,应用中的扩展日志(如打点、临时监控、访问日志等)命名方式: appName_logType_logName.log。logType:日志类型,如 stats/monitor/access/error 等;logName:日志描述。这种命名的好处:通过文件名就可知道日志文件属于什么应用,什 么类型,什么目的,也有利于归类查找。说明:推荐对日志进行分类,如将错误日志和正常 日志分开存放,便于开发人员查看,也便于通过日志对系统进行及时监控。

六、日志的大小

日志文件的大小应该可以通过参数控制(log4j2 可配置),如果超过限制,则必须写入到另一个带新序号的日志文件中,且不能超过本次磁盘预警值: 参考:log4j2官网:Log4j – Log4j 2 Appenders 下面是一个示例配置,它使用滚动文件追加器,其时间和大小都基于时间 触发策略,将在同一天创建最多 100 个存档 (1-100) 存储在目录中 根据当前年份和月份,并将压缩每个 使用 gzip 存档,每小时滚动一次。 在每次翻转期间,此配置将删除与“/app-.log.gz”匹配的文件 并且出生 30 天或以上, 但保留最近的 100 GB 或最近的 10 个文件,以先到者为准 logback:官网:Chapter 4: Appenders 译文:第四章:Appenders - logback 中的maxHistory处 其他注意点:https://www.cnblogs.com/ZTPX/p/14090313.html

七、日志的清理

一般情况下,日志文件按照磁盘预警值和监控组对接需求定时清理一次,移出日志目录; 对于有审计需求的日志,按照审计规定对这些文件进行归档,归档数据转入存储服务器。

八、日志打印注意事项

1.记录异常时一定要输出异常堆栈。如下:logger.error("xxx"+e.getMessage(), e)

2.日志中如果输出对象实例,要确保实例类重写了toString方法,否则只会输出对象的hashCode值。 注:logger应被定义为static,与类绑定,防止浪费资源。 使用slf4j+日志库模式时,要防止日志库冲突,一旦发生则可能会出现日志打印功能失效问题

3.不要在打印日志时造成异常

4.日志框架选型 logback、log4j2 logback:推荐,Springboot默认的日志框架 log4j2:版本大于2.15.0

5.日志格式 日志输出基本格式(有任何需求按规范添加): •pid[级别] [时间][应用名称][调用链标识][调用层级标识][业务标识] [线程名] [线程上线映射变量] [类名] [行号] [日志内容] [换行] 即:[%-5p] [%d{yyyy-MM-dd HH:mm:ss,SSS}] [%t] [%-1X{变量名}] [%C:%L] [%m] %n

6.日志级别得支持动态修改,要么actuator通过post接口动态修改日志级别,要么放到配置中心来修改

7.链路追踪 通过 AOP 切面,日志框架 MDC 等技术结合,在日志中打印traceId,而后根据traceId可检索整个请求链路的日志

1)AOP切面结合MDC方式 ①、日志配置文件中配置traceId占位符 Gherkin <pattern>%date{yyyy-MM-dd HH:mm:ss.SSS}|%t|%-5level|%X{traceId}|%C{0}#%M:%L|%msg%n</pattern> ②、AOP切入要增强traceId的方法 ③、在增强类中往MDC中添加traceId字段,并赋值,并在finally块移除MDC中traceId字段

2)直接使用MDC方式

①、日志配置文件中配置traceId占位符,同上

②、在方法执行业务逻辑前往MDC中添加traceId字段,并赋值

③、在方法返回前移除MDC中的traceId字段

3)在线程池中没采取阿里ttl方式做mdc前线程池必须手动使用mdc打印,防止链路追踪失败

  1. 不要记录异常又抛出 记录之后抛出异常是非常危险的操作,因为外层可能会因为内层捕获异常之后不会再次处理,如果是自定义异常更是难以排查问题,此外这样做法会导致堆栈二次打印,非常浪费系统性能,
  2. 核心功能模块日志 如果是核心功能模块的日志,其实多打印一些内容是可以接受的,但是需要注意打印的日志必须要第一时间可以定位到问题所在。 监控系统集成:建议将日志和监控系统打通,将日志信息传递给监控系统,以便实时监控系统的运行状态和性能指标。
  3. 理想的日志中应该记录不多不少的信息 l 不要在日志中记录无用的信息,实践中常见到的无用的日志有: 1)能够放在一条日志里的东西,放在多条日志中输出; 2)预期会发生且能够被正常处理的异常,打印出一堆无用的堆栈; 3)开发人员在开发过程中为了调试方便而加入的“临时”日志 l 对于日志的使用者,能够从日志中得到所有需要的信息
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
13天前
|
存储 SQL 监控
|
13天前
|
运维 监控 安全
|
16天前
|
监控 关系型数据库 MySQL
分析慢查询日志
【10月更文挑战第29天】分析慢查询日志
35 3
|
16天前
|
监控 关系型数据库 数据库
怎样分析慢查询日志?
【10月更文挑战第29天】怎样分析慢查询日志?
32 2
|
1月前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1633 14
|
1月前
|
存储 消息中间件 大数据
大数据-69 Kafka 高级特性 物理存储 实机查看分析 日志存储一篇详解
大数据-69 Kafka 高级特性 物理存储 实机查看分析 日志存储一篇详解
35 4
|
1月前
|
SQL 分布式计算 Hadoop
Hadoop-19 Flume Agent批量采集数据到HDFS集群 监听Hive的日志 操作则把记录写入到HDFS 方便后续分析
Hadoop-19 Flume Agent批量采集数据到HDFS集群 监听Hive的日志 操作则把记录写入到HDFS 方便后续分析
45 2
|
2月前
|
缓存 监控 算法
分析慢日志文件来优化 PHP 脚本的性能
分析慢日志文件来优化 PHP 脚本的性能
08-06-06>pe_xscan 精简log分析代码 速度提升一倍
08-06-06>pe_xscan 精简log分析代码 速度提升一倍
|
3月前
|
SQL 监控 关系型数据库
使用 pt-query-digest 工具分析 MySQL 慢日志
【8月更文挑战第5天】使用 pt-query-digest 工具分析 MySQL 慢日志
66 3
使用 pt-query-digest 工具分析 MySQL 慢日志