当前位置: 首页 > article >正文

Alibaba开发规范_异常日志之日志规约:最佳实践与常见陷阱

文章目录

    • 引言
    • 1. 使用SLF4J日志门面
      • 规则
      • 解释
      • 代码示例
        • 正例
        • 反例
    • 2. 日志文件的保存时间
      • 规则
      • 解释
    • 3. 日志文件的命名规范
      • 规则
      • 解释
      • 代码示例
        • 正例
        • 反例
    • 4. 使用占位符进行日志拼接
      • 规则
      • 解释
      • 代码示例
        • 正例
        • 反例
    • 5. 日志级别的开关判断
      • 规则
      • 解释
      • 代码示例
        • 正例
        • 反例
    • 6. 避免重复打印日志
      • 规则
      • 解释
      • 代码示例
        • 正例
        • 反例
    • 7. 记录异常信息
      • 规则
      • 解释
      • 代码示例
        • 正例
        • 反例
    • 8. 谨慎记录日志
      • 规则
      • 解释
    • 9. 使用`warn`记录用户输入错误
      • 规则
      • 解释
      • 代码示例
        • 正例
        • 反例
    • 10. 使用英文描述日志错误信息
      • 规则
      • 解释
      • 代码示例
        • 正例
        • 反例
    • 总结

在这里插入图片描述

引言

日志是软件开发中不可或缺的一部分,合理的日志记录可以帮助开发者快速定位问题、监控系统运行状态。本文将深入探讨Java日志规约的最佳实践,并通过反例和正例代码来更好地理解和应用这些规则。


1. 使用SLF4J日志门面

规则

  • 应用中不可直接使用日志系统(Log4j、Logback)中的API,而应依赖使用日志框架SLF4J中的API

解释

SLF4J(Simple Logging Facade for Java)是一个日志门面框架,它提供了统一的API,允许应用程序在不修改代码的情况下切换底层日志实现(如Log4j、Logback)。使用SLF4J可以提高代码的可维护性和灵活性。

代码示例

正例
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class Test {private static final Logger logger = LoggerFactory.getLogger(Test.class);public void doSomething() {logger.info("This is an info message.");}
}
反例
import org.apache.log4j.Logger;public class Test {private static final Logger logger = Logger.getLogger(Test.class);public void doSomething() {logger.info("This is an info message.");}
}

在反例中,直接使用Log4j的API,导致代码与具体日志实现耦合,难以切换日志框架。


2. 日志文件的保存时间

规则

  • 所有日志文件至少保存15天,因为有些异常具备以“周”为频次发生的特点。网络运行状态、安全相关信息、系统监测、管理后台操作、用户敏感操作需要留存相关的网络日志不少于6个月

解释

日志文件的保存时间应根据业务需求和法律要求来确定。通常,日志文件至少保存15天,而涉及安全和敏感操作的日志需要保存更长时间(如6个月)。


3. 日志文件的命名规范

规则

  • 应用中的扩展日志(如打点、临时监控、访问日志等)命名方式:appName_logType_logName.log

解释

通过规范的日志文件名,可以快速识别日志的来源、类型和用途,便于日志的管理和查找。

代码示例

正例
force_web_timeZoneConvert.log
反例
log.txt

在反例中,日志文件名过于简单,无法快速识别日志的来源和用途。


4. 使用占位符进行日志拼接

规则

  • 在日志输出时,字符串变量之间的拼接使用占位符的方式

解释

使用占位符(如{})进行日志拼接可以避免不必要的字符串拼接操作,提高性能。

代码示例

正例
logger.debug("Processing trade with id: {} and symbol: {}", id, symbol);
反例
logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);

在反例中,使用字符串拼接会导致性能损耗,尤其是在日志级别较高时(如INFOWARN)。


5. 日志级别的开关判断

规则

  • 对于trace/debug/info级别的日志输出,必须进行日志级别的开关判断

解释

在输出日志之前进行级别判断,可以避免不必要的字符串拼接和方法调用,提高性能。

代码示例

正例
if (logger.isDebugEnabled()) {logger.debug("Current ID is: {} and name is: {}", id, getName());
}
反例
logger.debug("Current ID is: " + id + " and name is: " + getName());

在反例中,即使日志级别高于DEBUG,仍然会执行字符串拼接和方法调用,造成性能浪费。


6. 避免重复打印日志

规则

  • 避免重复打印日志,浪费磁盘空间,务必在log4j.xml中设置additivity=false

解释

additivity属性控制子Logger是否继承父Logger的输出源。设置为false可以避免日志重复输出。

代码示例

正例
<logger name="com.taobao.dubbo.config" additivity="false"><appender-ref ref="FILE"/>
</logger>
反例
<logger name="com.taobao.dubbo.config"><appender-ref ref="FILE"/>
</logger>

在反例中,未设置additivity=false,可能导致日志重复输出。


7. 记录异常信息

规则

  • 异常信息应该包括两类信息:案发现场信息和异常堆栈信息

解释

记录异常时,应包含案发现场信息(如参数值、状态等)和异常堆栈信息,以便快速定位问题。

代码示例

正例
try {// 业务逻辑
} catch (Exception e) {logger.error("Error processing trade with id: " + tradeId, e);
}
反例
try {// 业务逻辑
} catch (Exception e) {logger.error("Error occurred");
}

在反例中,未记录异常堆栈信息,难以定位问题。


8. 谨慎记录日志

规则

  • 生产环境禁止输出debug日志;有选择地输出info日志;使用warn记录业务行为信息时,注意日志输出量

解释

过多的日志输出会影响系统性能,并增加日志管理的难度。应根据实际需求谨慎记录日志。


9. 使用warn记录用户输入错误

规则

  • 可以使用warn日志级别来记录用户输入参数错误的情况,避免用户投诉时无所适从

解释

使用warn级别记录用户输入错误,可以在不频繁报警的情况下,提供足够的信息用于问题排查。

代码示例

正例
if (userInput == null) {logger.warn("User input is null");
}
反例
if (userInput == null) {logger.error("User input is null");
}

在反例中,使用error级别记录用户输入错误,可能导致频繁报警。


10. 使用英文描述日志错误信息

规则

  • 尽量用英文来描述日志错误信息,如果日志中的错误信息用英文描述不清楚的话使用中文描述即可

解释

使用英文描述日志错误信息可以提高日志的通用性,特别是在国际化团队或海外部署的场景中。

代码示例

正例
logger.error("Failed to process trade: tradeId={}", tradeId);
反例
logger.error("处理交易失败:tradeId={}", tradeId);

在反例中,使用中文描述日志错误信息,可能导致国际化团队难以理解。


总结

通过遵循日志规约的最佳实践,开发者可以编写出高效、易维护的日志代码。

在这里插入图片描述

相关文章:

Alibaba开发规范_异常日志之日志规约:最佳实践与常见陷阱

文章目录 引言1. 使用SLF4J日志门面规则解释代码示例正例反例 2. 日志文件的保存时间规则解释 3. 日志文件的命名规范规则解释代码示例正例反例 4. 使用占位符进行日志拼接规则解释代码示例正例反例 5. 日志级别的开关判断规则解释代码示例正例反例 6. 避免重复打印日志规则解释…...

【数据分析】案例03:当当网近30日热销图书的数据采集与可视化分析(scrapy+openpyxl+matplotlib)

当当网近30日热销图书的数据采集与可视化分析(scrapy+openpyxl+matplotlib) 当当网近30日热销书籍官网写在前面 实验目的:实现当当网近30日热销图书的数据采集与可视化分析。 电脑系统:Windows 使用软件:Visual Studio Code Python版本:python 3.12.4 技术需求:scrapy、…...

需求分析应该从哪些方面来着手做?

需求分析一般可从以下几个方面着手&#xff1a; 业务需求方面 - 与相关方沟通&#xff1a;与业务部门、客户等进行深入交流&#xff0c;通过访谈、问卷调查、会议讨论等方式&#xff0c;明确他们对项目的期望、目标和整体业务需求&#xff0c;了解项目要解决的业务问题及达成的…...

申博经验贴

1. 所谓申博&#xff0c;最重要的就是定制的海投 分成两个部分 1. 定制 要根据每个教授去写不同的&#xff0c;一定不要泛泛的去写&#xff0c;一定要非常非常的具体&#xff0c;要引起教授的兴趣。每个教授每天都会收到几十封邮件&#xff0c;所以要足够的引起教授的注意&a…...

SpringAI 人工智能

随着 AI 技术的不断发展&#xff0c;越来越多的企业开始将 AI 模型集成到其业务系统中&#xff0c;从而提升系统的智能化水平、自动化程度和用户体验。在此背景下&#xff0c;Spring AI 作为一个企业级 AI 框架&#xff0c;提供了丰富的工具和机制&#xff0c;可以帮助开发者将…...

虚幻基础17:动画层接口

能帮到你的话&#xff0c;就给个赞吧 &#x1f618; 文章目录 animation layer interface animation layer interface 动画层接口&#xff1a;动画图表的集。仅有名字。 添加到动画蓝图中&#xff0c;由动画蓝图实现动画图表。...

SQLAlchemy 2.0的简单使用教程

SQLAlchemy 2.0相比1.x进行了很大的更新&#xff0c;目前网上的教程不多&#xff0c;以下以链接mysql为例介绍一下基本的使用方法 环境及依赖 Python:3.8 mysql:8.3 Flask:3.0.3 SQLAlchemy:2.0.37 PyMySQL:1.1.1使用步骤 1、创建引擎&#xff0c;链接到mysql engine crea…...

Codeforces Round 1002 (Div. 2) A-D

复活&#xff01;年后首场&#xff01;本期封面是我自己AI弄的图 A - Milya and Two Arrays 题意 给两个所有数字出现次数都大于2的数组&#xff0c;问能不能修改排序之后对应位置相加得到新的数组使不同数字个数达到3 思路 直接计数就行了&#xff0c;不同的数字匹配一下…...

OpenGL学习笔记(七):Camera 摄像机(视图变换、LookAt矩阵、Camera类的实现)

文章目录 摄像机/观察空间/视图变换LookAt矩阵移动相机&#xff08;处理键盘输入&#xff09;移动速度欧拉角移动视角&#xff08;处理鼠标输入&#xff09;缩放场景&#xff08;处理滚轮输入&#xff09;Camera类 摄像机/观察空间/视图变换 在上一节变换中&#xff0c;我们讨…...

『VUE』vue-quill-editor富文本编辑器添加按钮houver提示(详细图文注释)

目录 预览效果新建一个config.js存放标题编写添加提示的方法调用添加标题方法的生命周期总结 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 预览效果 新建一个config.js存放标题 export const titleConfig [{ Choice: .ql-bold…...

如何使用 DeepSeek 和 Dexscreener 构建免费的 AI 加密交易机器人?

我使用DeepSeek AI和Dexscreener API构建的一个简单的 AI 加密交易机器人实现了这一目标。在本文中&#xff0c;我将逐步指导您如何构建像我一样的机器人。 DeepSeek 最近发布了R1&#xff0c;这是一种先进的 AI 模型。您可以将其视为 ChatGPT 的免费开源版本&#xff0c;但增加…...

Kafka流式计算架构

引言 Kafka 凭借其卓越的架构设计&#xff0c;具备极为高效的流式计算能力&#xff0c;在海量数据环境下&#xff0c;依然能够以惊人的速度实现消息的高性能消费&#xff0c;轻松应对高并发、低延迟的严苛业务需求。无论是实时数据处理、复杂事件分析&#xff0c;还是大规模数…...

C++泛型编程06(默认模板实参)

文章目录 1.4 默认模板实参 (Default Template Arguments)示例&#xff1a;灵活定义返回类型 当然&#xff0c;这里是对关于默认模板实参(Default Template Arguments)的内容进行了改进和优化后的叙述&#xff1a; 1.4 默认模板实参 (Default Template Arguments) 在C中&…...

微信登录模块封装

文章目录 1.资质申请2.combinations-wx-login-starter1.目录结构2.pom.xml 引入okhttp依赖3.WxLoginProperties.java 属性配置4.WxLoginUtil.java 后端通过 code 获取 access_token的工具类5.WxLoginAutoConfiguration.java 自动配置类6.spring.factories 激活自动配置类 3.com…...

SRS代码目录

代码目录&#xff1a; src/目录下核心代码&#xff1a; core&#xff1a;核心功能模块&#xff0c;包括日志、配置、错误处理等&#xff1b;protocol&#xff1a;实现RTMP、HTTP-FLV、HLS等协议的模块&#xff1b;app&#xff1a;应用层的实现&#xff0c;包括流的发布、播放…...

C++STL(一)——string类

目录 一、string的定义方式二、 string类对象的容量操作三、string类对象的访问及遍历操作四、string类对象的修改操作五、string类非成员函数 一、string的定义方式 string是个管理字符数组的类&#xff0c;其实就是字符数组的顺序表。 它的接口也是非常多的。本章介绍一些常…...

机器学习--1.KNN机器学习入门

1、机器学习概述 1.1、什么是机器学习 机器学习&#xff08;Machine Learning&#xff09;是人工智能&#xff08;Artificial Intelligence&#xff09;领域的一个子集&#xff0c;它主要关注如何让计算机系统通过经验学习&#xff08;数据&#xff09;并自动改进性能。机器学…...

Adaptive LLM Transformer²

看到了一个不错的论文https://arxiv.org/pdf/2501.06252 TRANSFORMER-SQUARED: SELF-ADAPTIVE LLMS 挺有意思的&#xff0c;是一家日本AI公司SakanaAI的论文&#xff08;我以前写过他们的不训练提升模型的能力的文章&#xff0c;感兴趣可以去翻&#xff09;它家有Lion Jones坐镇…...

三路排序算法

三路排序算法 引言 排序算法是计算机科学中基础且重要的算法之一。在数据分析和处理中&#xff0c;排序算法的效率直接影响着程序的执行速度和系统的稳定性。本文将深入探讨三路排序算法&#xff0c;包括其原理、实现和应用场景。 一、三路排序算法的原理 三路排序算法是一…...

代码随想录day27

669. /** lc appleetcode.cn id669 langcpp** [669] 修剪二叉搜索树*/// lc codestart /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}…...

基于LabVIEW的Modbus-RTU设备通信失败问题分析与解决

在使用 LabVIEW 通过 Modbus-RTU 协议与工业设备进行通信时&#xff0c;可能遇到无法正常发送或接收指令的问题。常见原因包括协议参数配置错误、硬件连接问题、数据帧格式不正确等。本文以某 RGBW 控制器调光失败为例&#xff0c;提出了一种通用的排查思路&#xff0c;帮助开发…...

1. 【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--前言

在我们的专栏《单体开发》中&#xff0c;我们实现了一个简单的记账软件的服务端&#xff0c;并且成功上线。随着用户数量的不断增长&#xff0c;问题逐渐开始显现。访问量逐渐增加&#xff0c;服务端的压力也随之加大。随着访问量的攀升&#xff0c;服务端的响应时间变得越来越…...

直方图:摄影中的视觉数据指南

目录 一、直方图基础&#xff1a;揭开它的神秘面纱 二、解读直方图类型&#xff1a;亮度与色彩的密码 &#xff08;一&#xff09;亮度直方图 &#xff08;二&#xff09;RGB 直方图 三、拍摄中巧用直方图&#xff1a;优化曝光与效果 &#xff08;一&#xff09;精准判断曝…...

一份完整系统化提升信息输出密度与逻辑严谨性的训练素材

一、方法 1. 理论基础与核心概念 1.1 信息输出密度 定义 信息输出密度可以理解为单位表达中所包含的有效信息量。它要求在有限的篇幅或时间内传递更多有价值、低冗余的信息。衡量指标 信息熵&#xff08;Shannon Entropy&#xff09;&#xff1a;在信息论中&#xff0c;信息…...

CommonJS 和 ES6module 的区别

动态与静态 CommonJS 与 ES6 Module 最本质的区别在于前者对模块依赖的解决是“动态的”&#xff0c;而后者是“静态的”。在这里“动态”的含义是&#xff0c;模块依赖关系的建立发生在代码运行阶段&#xff1a;而“静态”则表示模块依赖关系的建立发生在代码编译阶段。 看一…...

IM 即时通讯系统-51-MPush开源实时消息推送系统

IM 开源系列 IM 即时通讯系统-41-开源 野火IM 专注于即时通讯实时音视频技术&#xff0c;提供优质可控的IMRTC能力 IM 即时通讯系统-42-基于netty实现的IM服务端,提供客户端jar包,可集成自己的登录系统 IM 即时通讯系统-43-简单的仿QQ聊天安卓APP IM 即时通讯系统-44-仿QQ即…...

前端 | JavaScript中的reduce方法

1. 什么是reduce reduce 方法是 JavaScript 中数组的重要方法之一&#xff0c;用于对数组中的元素进行累积计算。它接收一个回调函数作为参数&#xff0c;并返回一个最终计算结果。reduce 在许多场景下都非常有用&#xff0c;比如求和、数组扁平化、对象计数、数据转换等。 2…...

【Linux】从硬件到软件了解进程

个人主页~ 从硬件到软件了解进程 一、冯诺依曼体系结构二、操作系统三、操作系统进程管理1、概念2、PCB和task_struct3、查看进程4、通过系统调用fork创建进程&#xff08;1&#xff09;简述&#xff08;2&#xff09;系统调用生成子进程的过程〇提出问题①fork函数②父子进程关…...

2024-我的学习成长之路

因为热爱&#xff0c;无畏山海...

机试题——到邻国目标城市的最短距离

题目描述 A国与B国是相邻的两个国家&#xff0c;每个国家都有很多城市。国家内部有很多连接城市的公路&#xff0c;国家之间也有很多跨国公路&#xff0c;连接两个国家的边界城市。两个国家一共有N个城市&#xff0c;编号从1到N&#xff0c;一共有M条公路&#xff0c;包括国内…...