规范的打印日志

Keil MDK编译错误#541解决方案与ARM_Compiler包解析 在嵌入式开发中,编译器工具链的依赖管理是确保项目顺利构建的关键环节。以Keil MDK为例,其软件包依赖机制通过组件化设计实现功能解耦,其中ARM_Compiler包专门处理系统IO重定向等编译器扩展功能。这种架构既提升了模块复用性,也带来了版本兼容性挑战。当出现'Error #541: component missing'报错时,通常是由于中间件组件(如文件系统)在新版本中显式依赖了ARM_Compiler包。开发者需要通过Pack Installer安装该包,并在Run-Time Environment 阅读详情

一、使用 slf4j

使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一
实现方式统一使用:Logback 框架。

二、什么时候应该打日志

1️⃣当遇到问题的时候,只能通过 debug 功能来确定问题,应该考虑打日志,良好的系统,是可以通过日志进行问题定位的。
2️⃣当碰到 if…else 或者 switch 这样的分支时,要在分支的首行打印日志,用来确定进入了哪个分支。
3️⃣经常以功能为核心进行开发,应该在提交代码前,可以确定通过日志可以看到整个流程。

三、基本格式

1️⃣必须使用参数化信息的方式:

logger.debug("Processing trade with id:[{}] and symbol : [{}] ", id, symbol);

2️⃣对于 debug 日志,必须判断是否为 debug 级别后,才进行使用:

if (logger.isDebugEnabled()) {
  logger.debug("Processing trade with id: " +id + " symbol: " + symbol);
}

3️⃣不要进行字符串拼接,那样会产生很多 String 对象,占用空间,影响性能。
反例:

logger.debug("Processing trade with id: " + id + " symbol: " + symbol);

4️⃣使用[]进行参数变量隔离。如有参数变量,应该写成如下写法:

logger.debug("Processing trade with id:[{}] and symbol : [{}] ", id, symbol);

这样的格式写法,可读性更好,对于排查问题更有帮助。

四、不同级别的使用

1️⃣ERROR

影响到程序正常运行、当前请求正常运行的异常情况:

  1. 打开配置文件失败
  2. 所有第三方对接的异常(包括第三方返回错误码)
  3. 所有影响功能使用的异常,包括:SQLException 和除了业务异常之外的所有异常(RuntimeException 和 Exception)

##不应该出现的情况:
比如要使用 Azure 传图片,但是 Azure 未响应。如果有 Throwable 信息,需要记录完成的堆栈信息:

log.error("获取用户[{}]的用户信息时出错",userName,e);

说明:

如果进行了抛出异常操作,请不要记录 error 日志,应该由最终处理方进行处理。

反例(不要这么做):

try{
 ....
}catch(Exception ex){
 String errorMessage=String.format("Error while reading information of user [%s]",userName);
 logger.error(errorMessage,ex);
 throw new UserServiceException(errorMessage,ex);
}

2️⃣WARN

不应该出现但是不影响程序、当前请求正常运行的异常情况:

  1. 有容错机制的时候出现的错误情况
  2. 找不到配置文件,但是系统能自动创建配置文件
  3. 即将接近临界值的时候。例如缓存池占用达到警告线业务异常的记录。当接口抛出业务异常时,应该记录此异常。

3️⃣INFO

系统运行信息

  1. Service 中对于系统/业务状态的变更。
  2. 主要逻辑中的分步骤。

外部接口部分

  1. 客户端请求参数(REST/WS)
  2. 调用第三方时的调用参数和调用结果

说明

  1. 并不是所有的 service 都进行出入口打点记录,单一、简单 service 是没有意义的(job 除外,job 需要记录开始和结束)

反例:

public List listByBaseType(Integer baseTypeId) {
 log.info("开始查询基地");
 BaseExample ex=new BaseExample();
 BaseExample.Criteria ctr = ex.createCriteria();
 ctr.andIsDeleteEqualTo(IsDelete.USE.getValue());
 Optionals.doIfPresent(baseTypeId, ctr::andBaseTypeIdEqualTo);
 log.info("查询基地结束");
 return baseRepository.selectByExample(ex);
}
  1. 对于复杂的业务逻辑,需要进行日志打点,以及埋点记录,比如电商系统中的下订单逻辑,以及 OrderAction 操作(业务状态变更)。

  2. 对于整个系统的提供出的接口(REST/WS),使用 info 记录入参。

  3. 如果所有的 service 为 SOA 架构,那么可以看成是一个外部接口提供方,那么必须记录入参。

  4. 调用其他第三方服务时,所有的出参和入参是必须要记录的(因为很难追溯第三方模块发生的问题)。

4️⃣DEBUG

  1. 可以填写所有的想知道的相关信息(但不代表可以随便写,debug 信息要有意义,最好有相关参数)。
  2. 生产环境需要关闭 DEBUG 信息。
  3. 如果在生产情况下需要开启 DEBUG,需要使用开关进行管理,不能一直开启。

说明

如果代码中出现以下代码,可以进行优化:

//1. 获取用户基本薪资
//2. 获取用户休假情况
//3. 计算用户应得薪资

优化后的代码:

logger.debug("获取员工[{}] [{}]年基本薪资",employee,year);
logger.debug("获取员工[{}] [{}]年的基本薪资为[{}]",employee,year,basicSalary);
logger.debug("获取员工[{}] [{}]年[{}]月休假情况",employee,year,month);
logger.debug("员工[{}][{}]年[{}]月年假/病假/事假为[{}]/[{}]/[{}]",employee,year,month,annualLeaveDays,sickLeaveDays,noPayLeaveDays);
logger.debug("计算员工[{}][{}]年[{}]月应得薪资",employee,year,month);
logger.debug("员工[{}] [{}]年[{}]月应得薪资为[{}]",employee,year,month,actualSalary);

5️⃣TRACE

特别详细的系统运行完成信息,业务代码中,不要使用(除非有特殊用意,否则请使用 DEBUG 级别替代)

规范示例说明:

@Override
@Transactional
public void createUserInfo(@NotBlank String mobile, @NotNull User user) throws CreateConflictException {
    boolean debug = log.isDebugEnabled();
    if (debug) {
        log.debug("创建用户并绑定手机号. args[mobile=[{}],user=[{}]]", mobile, LogObjects.toString(user));
    }
    try {
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        userRepository.insertSelective(user);
        if (debug) {
            log.debug("创建用户信息成功. insertedUser=[{}]", LogObjects.toString(user));
        }
        UserMobileRelationship relationship = new UserMobileRelationship();
        relationship.setMobile(mobile);
        relationship.setOpenId(user.getOpenId());
        relationship.setCreateTime(new Date());
        relationship.setUpdateTime(new Date());
        userMobileRelationshipRepository.insertOnDuplicateKey(relationship);
        if (debug) {
            log.debug("绑定手机成功. relationship=[{}]", LogObjects.toString(relationship));
        }
        log.info("创建用户并绑定手机号. userId=[{}],openId=[{}],mobile=[{}]", user.getId(), user.getOpenId(), mobile);
    } catch (DuplicateKeyException e) {
        log.info("创建用户并绑定手机号失败,已存在相同的用户. openId=[{}],mobile=[{}]", user.getOpenId(), mobile);
        throw new CreateConflictException("创建用户发生冲突, openid=[%s]", user.getOpenId());
    }
}
PaddleOCR全版本完整指南:从入门到精通,全面解析安装部署与高级应用 摘要 本文详细介绍了PaddleOCR的完整安装与使用指南。首先讲解了环境准备步骤,包括Python 3.11虚拟环境创建和PaddlePaddle框架的CPU/GPU版本安装。接着介绍了PaddleOCR库的安装方式,可选功能模块(文档解析、信息抽取、翻译等)及其依赖组。通过示例代码演示了PPStructureV3文档解析功能的基本用法,并提供了安装验证方法。最后针对常见问题(Windows中文用户名报错、模型下载问题)给出解决方案。文章为从入门到精通的PaddleOCR用户提供了全面的技术指导。 阅读详情

相关推荐

【论文阅读1】机理引导的残差学习用于电池全生命周期状态监测 | Nature Communications

本文提出了一种机理引导的残差学习框架,用于提升电池全生命周期内荷电状态(SOC)和健康状态(SOH)的监测精度。该方法融合等效电路模型的先验知识与机器学习,设计了修正模型和补偿模型两种通用框架。实验验证表明,该方法在三种不同类型电池数据集上均表现出色,SOC和SOH估计误差较传统方法降低50%以上,且在未见工况下仍保持良好外推能力。模型具有强鲁棒性,在减少训练数据量和降低采样频率时性能稳定,并兼具物理可解释性。该框架无需离线测试和运行中校准,为电池安全监测提供了有效解决方案。

qq_21843433的博客 615

日志打印规范

日志打印规范

m0_38068812的博客 2244

【图文步骤】EC-Engineer部分操作详细步骤

EC-Engineer部分功能详细使用手册

weixin_42212468的博客 6172

Log日志规范

1 日志等级 TRACE/DEBUG :记录和追踪整个程序的运行过程,针对不是非常重要的信息。 INFO:记录关键的步骤 WARN:警告信息,磁盘已满等信息,预期的错误 ERROR:普通错误,程序还可以运行 FATAL:严重错误,表示程序已经无法运行了。 2 打印规范 2.1 TRACE/DEBUG 级别的日志不打印,只打印INFO及以上级别的日志 2.2 日志的容量应控制在一定范...

飞鸟慕鱼的博客 636

不只是CPU主频:深入解析英飞凌Aurix TC3xx各外设时钟树(CAN、以太网、Flash时序如何配置)

本文深入解析英飞凌Aurix TC3xx系列微控制器的外设时钟树配置,涵盖CAN、以太网和Flash时序的优化方法。通过详细分析时钟系统架构、关键外设配置及多外设协同设计策略,帮助工程师实现高性能汽车电子控制单元(ECU)开发。特别关注系统时钟的灵活配置与EMC优化技巧,提升系统实时性和可靠性。

weixin_29189373的博客 401

GD32F303开发实战(一):从零搭建MDK工程与时钟配置详解

本文详细介绍了如何从零开始为GD32F303微控制器搭建一个清晰、可维护的MDK工程模板。内容涵盖开发环境准备、工程目录结构规划、文件分组管理、关键工程配置,并重点解析了时钟树原理,手把手指导配置108MHz系统时钟。通过实战步骤与常见问题排查,帮助开发者构建一个稳定可靠的开发基础,便于后续功能扩展。

weixin_29174141的博客 270

日志打印的规范以及实现方式

1. WHY 为什么要做日志? 原因1:跟踪应用的警告和错误,标识程序运行中的危险操作、错误操作,进而便于在出现问题时排查问题 原因2:跟踪崩溃bug,在开发过程中,日志可以帮助开发者和软件测试人员跟踪程序崩溃的原因 原因3:跟踪性能下降的问题范围,产品所反映出来的性能问题,很难在开发过程中暴露出来,这需要进行全方位的测试跟踪,而通过日志提供的详细执行时间记录可以很方便的找出应用的性能瓶颈 原因...

大圣即大盗 1万+

FPGA SPI驱动ADC避坑指南:以ADC128S022为例,详解时序设计与代码调试

本文以ADC128S022为例,详细解析FPGA通过SPI驱动ADC的时序设计与代码调试中的常见问题。从时钟分频计算、SPI模式选择到状态机实现,提供避坑指南和实战技巧,帮助工程师解决数据采集系统中的时序匹配难题。特别针对FPGA与ADC通信中的微妙差异,给出精确的Verilog代码示例和ModelSim仿真验证方法。

weixin_42522374的博客 458

业务知识——Logger日志打印规范

初期,我们的系统比较简单,在这个过程中,加上大家平时都不注意,所以Logger日志一直是打印的随心所欲,什么是随心所欲的,就是大家想在哪里打日志就在哪里打印日志,想输出什么就输出什么,毫无规范可言,在系统的流量和业务量变得越来越复杂的情况下,良好的日志才能帮助我们更快地找到问题,更好地解决问题。   首先来看一下比较常用的Logger日志级别(部分未列出): error - 运行期错误日志记...

一个想写小说的程序员 6883

CubeMX配置ADC+DMA避坑实战:如何避免采样过快导致的系统崩溃

本文针对STM32开发中常见的ADC采样过快导致程序卡死问题,提供了基于CubeMX的实战避坑指南。通过分析ADC与DMA协作机制,详解时钟配置、采样时间、DMA缓冲区长度及中断设置等关键步骤,帮助开发者从源头规避系统崩溃风险,实现稳定可靠的数据采集。

weixin_28273593的博客 324

基于STM32设计的太阳能智慧路灯_444

本文设计并实现了一种基于 STM32 的太阳能智慧路灯系统。系统以 STM32F103C8T6 单片机为核心,集成温湿度检测、空气质量检测、环境光照检测、行人检测和路灯故障检测等功能,实现对路灯运行环境和工作状态的实时感知。

462

打印 log 日志规范与实践

用于可视化和分析日志数据,提供灵活的查询和可视化工具,可以创建仪表板、图表和报表来展示日志数据的统计和趋势。:日志应该记录足够详细的信息,包括时间、触发事件、相关参数和上下文等,方便我们快速理解时间的发生和上下文。:日志应该使用易于阅读和理解的格式,日志信息能够被其它开发人员快速理解,而不需要费力解析复杂的日志内容。需要注意的是,日志记录的频率和打印量应根据具体情况进行评估和调整,避免日志过于频繁或过于庞大。:日志应该保护敏感信息的安全性,避免将敏感数据记录在日志中,以防止信息泄露的风险。

KevinChen2019的博客 1260

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

常见日志框架使用及日志打印规范设计

slf4j 是各种日志框架的 facade 抽象,log4j、logback、java.util.logging 是 slf4j 不同的实现方式,另外 slf4j-simple 是 slf4j 提供的简单实现。commons-logging 和 slf4j 类似,是 apache 最早提供的日志的门面接口,log4j 和 java.util.logging 也提供了相应的实现方式。

聚焦AI技术前沿,深度解析大模型原理与多场景应用,探索最新突破与落地实践,助力行业洞悉趋势,驱动智能转型,赋能千行百业。 2112

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

代码日志打印规范分享

来记录刚上线时的业务行为信息,一定要注意日志输出量的问题,避免把服务器磁盘撑爆,并记得及时删除这些观察日志。但是一旦出现了也需要关注,因此一般该级别的日志达到一定的阈值之后,就得提示给用户或者需要关注的人了。,若代码中缺少必要的日志打印,或者打印的日志过多过频繁,不仅不好定位问题,还有磁盘存储爆满的问题出现。,想想,我们的维护时间往往是项目周期的两三倍以上,而维护的对象本质上是什么呢?日志打印往往在一个时间较为紧急的项目中被忽视,而你可能会发现,我们遇到的项目,涉及扫描数据的任务,务必打印扫描范围。

554

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

客户端日志打印规范

/ 正例:重写toString()方法,将实体类转换为JSON字符串@Override}

hunter800421的专栏 1574

JAVA打印日志规范实践

JAVA日志打印规范实践

今天又是充满希望的一天 3652

日志打印不规范,被CTO骂了一顿~

文章来源:【公众号:技术奇妙物语】目录前言利器一:规范先行利器二:服务至上利器三:度量为王写在最后前言如果你是一名优秀的应用系统开发人员,想必应该非常清楚在应用系统运行期间,打印日志有多么重要。它不但能够记录应用系统运行情况及轨迹,还有助于提升故障排查及定位问题的效率,甚至还可以对其进行分析及监控,洞察系统隐患,提前预警防范。但并不是说只要打印尽可能多的日志,就能轻松获得...

石杉的架构笔记 422

工程实践:如何规范地打印程序日志?

工程实践:如何规范地打印程序日志? 很久之前,有个朋友问我,如果一个老项目让你接手去进行后续维护,你会先从哪里入手、让自己更快地上手项目?当时我没有特别正面去回答这个朋友的问题,我说:一个老项目是否容易上手,一个非常关键的地方就是这个项目的日志是否打得足够好。因为通常来说,一个老项目相对比较稳定了,后续大概率不会有比较大的变更和改动,那么对于这样的项目,核心就是“维稳”。但是任何人都无法保证项目在线上运行时不会出线上故障,在出现线上问题或者故障时,如何快速止损就是第一要义,而日志在止损过程中就扮演..

小猴子的博客 574

java打印日志规范建议

2, 如何打印堆栈日志,在何处打印堆栈日志?1, 如何打印日志?

m0_46393656的博客 208

最简日志打印规范

个人认为,如果在公司的野蛮生长阶段,一些基础类库不做约束,很可能“埋坑”,形成技术债务,最终为此付出代价。本文讲解一个最简的日志打印规范。事实上,日志打印规范互联网上已有很多,但大多比较冗长(记不住),也不太契合我们团队(关注点不契合)。所以,我又造了个轮子,写了个简单易懂、容易记的“最简日志打印规范”,后续随着团队实力的增长,和项目的演进,会逐步增加新的条例。

weixin_45700531的博客 547

java 日志打印规范

日志要求: 重要日志一定要打印到日志文件 日志文件应该每天滚动一次,日志多的可以每个小时滚动一次 日期必须精确到毫秒,而不是秒 确保日志是按事件顺序输出 【推荐】最好能打印调用方信息,比如访问者ip等信息 日志文件要可以方便使用grep语句查看 日志文件归档:需要告知运维归档 日志预警,通过ES实现 对于无法预知的异常,一定要打印堆栈:LOGGER.er...

时间道的博客 7196
上一篇: JavaScript Object Notation
下一篇: replace与replaceAll的区别
JFS_Study
博客等级 码龄6年 363粉丝 359原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JFS_Study

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值