网站首页 > java教程 正文
本文参考自阿里孤尽老师的《码出高效代码》一书的第五章,为了节省大家学习时间,在这里对重要知识进行了总结,如果有知识点不明白的可以关注作者,找作者要相关的具体学习资料(免费送上)。
为什么要记录日志
记录应用系统日志主要有三个原因:记录操作轨迹、监控系统运行状况、回溯系统故障。
日志规范
- 日志文件命名规则:推荐appName_logType_logName.log。其中appName表示应用名词,logType表示日志类型,如stats(统计)、monitor(监控)、visit(访问)等。如sc-job-soa应用的sql监控日志名词定义为:scjob_monitor_sql.log。
- 日志存储时间:推荐日志文件至少保存15天,可以根据日志文件的重要程度、文件大小以及磁盘空间自行延迟时间(注意:是延迟时间,不是自定义时间)。
日志的五种级别(按重要程度从低到高排序):
由于日志级别不同,重要程度不同,所以针对不同日志级别有不同的处理方式,如下:
1.预先判断日志级别:对于DEBUG、INFO级别日志,必须使用条件输出或者使用占位符的方式打印。由于生产环境是禁止输出DEBUG日志且有选择地输出INFO日志,所以不使用上述方式则需要多执行一步使用字符串拼接/字符串格式化操作,影响程序执行效率。
//直接字符串拼接打印(错误) logger.debug("DemoApplication is start, startTime:" + System.currentTimeMillis()); //使用条件判断形式(正确) if (logger.isDebugEnabled()){ logger.debug("DemoApplication is start, startTime:" + System.currentTimeMillis()); } //使用占位符形式(正确) logger.debug("DemoApplication is start, startTime:{}", System.currentTimeMillis());
2.避免无效日志打印:生产环境是禁止DEBUG日志且有选择地输出INFO日志。使用INFO、WARN级别来记录业务行为信息时,一定要控制日志输出量,以免出现磁盘空间不足。同时要为日志设置合理的生命周期,及时清理过期日志。避免重复打印,务必在日志配置文件中设置additivity=false,示例如下:
<logger name="com.example.demo" additivity="false" />
3.避免无效日志打印:
WARN日志:记录一些业务异常可以通过引导重试就能恢复正常的日志信息,如用户输入参数错误。
ERROR日志:记录系统逻辑错误、异常或违法重要业务规则的日志信息(需要人工干预)。
4.避免无效日志打印:
日志记录的内容包括现场上下文信息与异常堆栈信息。打印时需要注意下面两点:
- 记录异常时一定要输出异常堆栈。如下:logger.error("xxx"+e.getMessage(), e)
- 日志中如果输出对象实例,要确保实例类重写了toString方法,否则只会输出对象的hashCode值。
日志框架
日志框架分为三大部分,包括日志门面、日志适配器、日志库。利用门面设计模式,即Facade进行解耦,使日志使用变得更加简单。
- 日志门面:日志门面采用门面设计模式提供了一套接口规范,自身不负责日志功能的实现,目的是让使用者不需要关注底层具体是哪个日志库来负责日志打印及具体使用细节。比较常用的日志门面有两种:slf4j和 commons-logging。
- 日志库:负责实现日志相关功能,主流日志库有三个,分别为:log4j、log-jdk(java.util.logging.Logger)、logback。logback是最晚出现的,与log4j同一个作者,是log4j的升级版且本身实现了slf4j的接口。
- 日志适配器:分为:日志门面适配器(日志库适配slf4j),日志库适配器(slf4j适配日志库)。
- 日志门面适配器:老工程用的日志库没有实现slf4j接口,如log4j;这时候工程里想使用slf4j+log4j的模式,就额外需要一个适配器(slf4j+log4j12)来解决接口不兼容问题。
- 日志库适配器:老工程直接使用日志库API完成日志打印,要改成业界标准的门面模式(如slf4j+logback),但是老工程代码打印日志地方太多难以改动,这是就需要一个适配器来完成从旧日志库的API到slf4j的路由,这样在不改动原有代码的情况下也能使用slf4j来统一管理日志(如:log4j-over-slf4j),后续自由替换具体日志库也不成问题。
工程中日志集成(Maven):
新工程,推进使用slf4j+logback模式。logback自身实现了slf4j的接口,无须额外引入适配器,同时logback是log4j的升级版。可通过如下配置进行集成:
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j-api.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback-classic.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>${logback-core.version}</version> </dependency>
老工程,需要根据使用的日志库来确定门面适配器。以log4j日志库为例,可通过如下配置进行集成:
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j-api.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j-log4j12.version}</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency>
老工程,代码中直接使用了log4j日志库提供的API来打印日志,则还需要引入日志库适配器,配置如下:
<dependency> <groupId>org.slf4j</groupId> <artifactId>log4j-over-slf4j</artifactId> <version>${log4j-over-slf4j.version}</version> </dependency>
注:logger应被定义为static,与类绑定,防止浪费资源。如:
private static final Logger logger = LoggerFactory.getLogger(SettlementCalculateManager.class);
注:使用slf4j+日志库模式时,要防止日志库冲突,一旦发生则可能会出现日志打印功能失效问题。
END
点赞+转发+关注,私信作者“读书笔记”即可获得BAT大厂面试资料、高级架构师VIP视频课程等高质量技术资料。
猜你喜欢
- 2024-11-12 java日志那些事儿-日志野史(java 日志包)
- 2024-11-12 大厂都是如何解决Java日志级别,重复记录、丢日志问题?
- 2024-11-12 五年Java经验,面试还是说不出日志该怎么写更好?
- 2024-11-12 Java常用日志框架总结(java的日志框架)
- 2024-11-12 java日志组件(java 日志系统)
- 2024-11-12 java打日志超简单(java如何输出日志)
- 2024-11-12 Java企业级项目的日志规范(java企业级项目的日志规范有哪些)
- 2024-11-12 小白也能看懂Java 日志体系(SLF4J)
- 2024-11-12 开发须知:开发者须知的4类Java日志
- 2024-11-12 谈谈日志的最佳实践(谈谈日志的最佳实践方式)
你 发表评论:
欢迎- 06-15Linux中如何通过Shell脚本来控制Spring Boot的Jar包启停服务?
- 06-15推荐一款超棒的SpringCloud 脚手架项目
- 06-15IDEA将项目打包成jar包(idea打包普通java项目)
- 06-15Spring Boot3 项目 jar 包打包成 Docker 镜像全攻略
- 06-15记录Dockerfile将jar包构建成部署所需的镜像
- 06-15项目基础部署汇总八---linux下xxl-job安装
- 06-15Spring Boot Jar 包秒变 Docker 镜像实现多环境部署
- 06-15终端执行 java -jar example.jar 时报错:“没有主清单属性” 的解决
- 最近发表
-
- Linux中如何通过Shell脚本来控制Spring Boot的Jar包启停服务?
- 推荐一款超棒的SpringCloud 脚手架项目
- IDEA将项目打包成jar包(idea打包普通java项目)
- Spring Boot3 项目 jar 包打包成 Docker 镜像全攻略
- 记录Dockerfile将jar包构建成部署所需的镜像
- 项目基础部署汇总八---linux下xxl-job安装
- Spring Boot Jar 包秒变 Docker 镜像实现多环境部署
- 终端执行 java -jar example.jar 时报错:“没有主清单属性” 的解决
- 如何将本地JAR文件添加到Maven项目中
- Java 类隔离应用:多 Jar 包支持(java接口隔离原则)
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)