关于 logger
日志
前言
我是一名后台程序员,接触后台只有一年时间,在这期间一共做过四个项目,分别是:
- 工作室招新系统
- 视频学习网站
- 创客网站
- 打印机项目
由于之前做项目的时候没有好好重视日志,所以导致在开发与维护项目出现了很多问题,现在分享分享我的惨痛经历:
做第一个项目的时候,这个是我第一次开始学习后台时做的第一个项目,使用最原始的 servlet + jsp 技术,当时没有任何经验,没有把系统的需求和实现方式思考清楚就开始动工,做的过程遇到很多问题,但今天的主题不在这些问题上,而是关于日志,当时我们并没有在项目使用日志技术记录日志信息,因为该项目没有进行上线发布,所以后面做完了大部分功能之后就没继续完善和维护,所以没有意识到日志的重要性。
做第二个项目与第三个项目时,这是一个商业项目,由于第一次没有意识到日志的重要性,所以开发时是没有打日志的,等到项目开发完后,我们需要上线测试,部署到服务器时,发现出现了很多个 bug,但以前我们找 bug 都是通过调试或者在控制台输出错误信息来查看,部署到服务器上根本调试不了也看不到错误信息,这就导致一直找不到导致出现 bug 的地方。后面在项目添加了,但只是在 servlet 层后面添加一个全局的try catch,再记录错误信息而已,但这并没起多大作用。
做第四个项目时,当时有要打日志的想法,但是由于之前没做过,所以对于要如何打日志根本不理解,应该在什么地方记录日志,应该使用哪种日志级别。所以最后在项目的时候就随便乱打日志,导致最后输出的日志信息时,也是一团乱。
在基于前面的经历,觉得有必要去好好学习如何使用日志机制。
为什么要使用日志机制
就如我之前所说的,开发以后应用服务时,如果你没有使用日志机制,那么当你将服务部署上去时,系统出 bug 了,因为没有错误信息可以查看,所以你找不到错误出现的地方,这样会不方便测试与维护。使用日志及时记录错误的信息,会更方便我们定位到错误的地方以及错误的原因,方便我们修复系统。
日志机制
日志信息级别
日志信息一般有五种级别,分别是:
DEBUG
DEBUG 级别是最低的级别,一般是为了用于测试应用程序而输出日志信息,它只能用于开发环境与测试环境,不能用于线上环境。INFO
INFO 级别比 DEBUG 级别要高,一般用此级别来记录服务正在开启、从请求接收的信息、响应返回的信息等等WARN
WARN 级别 比 INFO 级别要高,一般是用于记录客户端与服务端连接丢失,数据库连接丢失、Scoket 连接达到限制等一些表示 server 运行时的状态信息ERROR
ERROR 级别 比 WARN 级别要高,一般是用于记录系统出现错误的异常错误信息,在开发时候,通过记录 ERROR 级别的信息,可以方便地定位到系统出错的地方,从而更方便地修复系统FATAL
FATAL 级别的信息一般是用于记录非常严重的错误事件信息,该事件可能会导致应用崩溃或者停止
如何使用日志
- 在输出 DEBUG 级别的日志信息前加一层 isDebugEnabled() 的判断,因为这是为了避免系统发布到运行环境上之后输出过多的日志信息,也避免需要为了发布而删掉或注释掉输出的 DEBUG 信息,因为这会影响日后的系统维护
- 认真考虑好哪些信息要用哪种级别去记录日志。如果在发布环境上记录太多日志信息会影响性能,因为这会产生很多文件 IO ;但如果不记录重要的信息如接收的信息、响应的信息,将会非常困难找出错误的问题和异常在何处
- 使用配置文件来加载日志的信息,这会方便地改变系统的日志记录级别,从而避免重启应用
- 对于记录的日志信息,需要格式化;在高并发的系统时,需要记录当前的线程名以及当前处理类的完全限定名;记录的日志格式应一致、有用,必要的时候还要输出时间
- 使用一系列后缀来区分不同的层次的信息。比如与数据库有关,就记录 DB_LOG,与 Session 有关,记录 SESSION_LOG,这样有利于通过后缀查找匹配出那个层次的所有日志信息,方便管理和差错
- 如果没有为一个日志指定级别,应该让他从他的父类继承,所以我们一般通过配置文件为根日志配置级别为 DEBUG
- 没有日志或过多的日志都是非常不好的,所以在性能和维护差错方面做好一个平衡,仔细选择要用哪些级别记录哪些信息
- 记录的日志信息应当是简单、易懂并且对于团队来说是有效的
Log4j
为系统性能考虑,使用 Log4j 注意下列几点:
- 避免输出 ‘%C’, ‘%f’, ‘%L’, ‘%M’ 等位置信息
- 尽量使用异步
- 为每个模块设置单独的输出文件
- 每次调用前检查 if(logger.isDebugEnabled()) { logger.debug(……) }
解析:
- 避免输出 ‘%C’, ‘%f’, ‘%L’, ‘%M’ 等位置信息
当配置文件中的配置项包含 Location 信息会非常昂贵- %C 输出类名
- %F 输出文件名
- %L 输出行号
- %M 输出函数名
注:当配置为异步输出的时候,以上位置信息可能会显示不出来,因为实在另外的一个线程记录的调用信息。此时,我们可以使用下面的方法来获取类名和函数名:
StackTraceElement se = Thread.currentThread().getStackTrace()[2];
String msg = se.getClassName() + "-[" + se.getMethodName() + "] " + errorMessage;
使用异步
要使用异步在于要在配置文件中配置 appender,为什么要使用异步来记录日志,前面说过记录日志信息会产生文件 IO,这会影响一定的性能,使用异步可以避免因为需要同步记录日志而产生的等待时间。为每个模块设置单独的输出文件
根据模块来区分日志文件,在调试和维护某个模块时,可以更方便。每次调用前检查 if(logger.isDebugEnabled()) { logger.debug(……) }
前面已说过
总结
日志机制对于开发来说是非常重要的,它关系到调试与维护,在开发一个项目前期,应该提前部署好日志环境。同时,在开发的过程中,要想好如何去记录日志信息,要用哪种级别去记录,权衡性能与维护,选择一种较好的日志实施方案。
本文只是个人观点,如有不同意,可以说出来大家一起讨论讨论。之后再补充一篇使用 slf4j + logback 搭建日志机制的博文。
关于 logger的更多相关文章
- ABP源码分析八:Logger集成
ABP使用Castle日志记录工具,并且可以使用不同的日志类库,比如:Log4Net, NLog, Serilog... 等等.对于所有的日志类库,Castle提供了一个通用的接口来实现,我们可以很方 ...
- org.apache.log4j.Logger详解
org.apache.log4j.Logger 详解 1. 概述 1.1. 背景 在应用程序中添加日志记录总的来说基于三个目的 :监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析工 ...
- Java程序日志:java.util.logging.Logger类
一.Logger 的级别 比log4j的级别详细,全部定义在java.util.logging.Level里面.各级别按降序排列如下:SEVERE(最高值)WARNINGINFOCONFIGFINEF ...
- [LeetCode] Logger Rate Limiter 记录速率限制器
Design a logger system that receive stream of messages along with its timestamps, each message shoul ...
- .Net Core Logger 实现log写入本地文件系统
.net core 自带一个基础的logger框架Microsoft.Extensions.Logging. 微软默认实现了Microsoft.Extensions.Logging.Console.d ...
- Android源码——Logger日志系统
Android的Logger日志系统是基于内核中的Logger日志驱动程序实现的. 日志保存在内核空间中 缓冲区保存日志 分类方法:日志的类型 + 日志的输出量 日志类型: main ...
- java.lang.NoClassDefFoundError: Lorg/slf4j/Logger;
如果你出现类似如下错误 1. Install tomcat7 in my home directory and set up `CATALINA_HOME` environment variable ...
- LeetCode 359 Logger Rate Limiter
Problem: Design a logger system that receive stream of messages along with its timestamps, each mess ...
- 你的日志组件记录够清晰嘛?--自己开发日志组件 Logger
现在现成的日志组件实在是太多太多,为什么我还需要自己实现呢????? 需求来源于java的log4j, [07-31 16:40:00:557:WARN : com.game.engine.threa ...
- log4j2 不使用配置文件,动态生成logger对象
大家平时使用Log4j一般都是在classpath下放置一个log4j的配置文件,比如log4j.xml,里面配置好Appenders和Loggers,但是前一阵想做某需求的时候,想要的效果是每一个任 ...
随机推荐
- Steeltoe
谈谈Circuit Breaker在.NET Core中的简单应用 http://www.cnblogs.com/catcher1994/p/8975192.html 前言 由于微服务的盛行,不少公司 ...
- UVa 11400 - Lighting System Design(线性DP)
链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- PHP------知识复习
PHP概述 (1)PHP(Hypertext Perprocessor)超级文本预处理器 (2) PHP是一种在服务器端执行的嵌入HTML文档的脚本语言 (3) 是一种网站开发语言(B/S结构) ( ...
- REG小探
根键名称缩写对照表 常用数据类型
- select下拉框之默认选项清空
最近和小伙伴发现,select默认选项一般是提示信息,怎么才能让当我们点击下拉框时,可选的选项中没有默认的提示信息呢? 思路: 1.当点击下拉框时,让默认提示信息,即下拉框第一个选项移除. 2.当没有 ...
- 用Java+xml配置方式实现Spring数据事务(编程式事务)
一.用Java配置的方式 1.实体类: Role public class Role { private int id; private String roleName; private String ...
- [转]java中文乱码的解决
在基于Java的编程中,经常会碰到汉字的处里及显示的问题,比如一大堆乱码或问号. 这是因为JAVA中默认的编码方式是UNICODE,而中国人通常使用的文件和DB都是基于GB2312或者BIG5等编码, ...
- HTML5学习总结——相关练习与项目
一.小米商城项目 第一天示例代码: <!DOCTYPE html> <html lang="en"> <head> <meta chars ...
- Web—04-详解HTML5与CSS3
CSS权重 CSS权重指的是样式的优先级,有两条或多条样式作用于一个元素,权重高的那条样式对元素起作用,权重相同的,后写的样式会覆盖前面写的样式. 权重的等级 可以把样式的应用方式分为几个等级,按照等 ...
- Oracle语句(一)之简单查询
1.查询数据表的所有列: select * from 表名; 程序员正常用法:select 列名,列名... form 表名; 2.起别名: select 列名 [AS 别名],列名 别名...fro ...