日志

前言

我是一名后台程序员,接触后台只有一年时间,在这期间一共做过四个项目,分别是:

  • 工作室招新系统
  • 视频学习网站
  • 创客网站
  • 打印机项目

由于之前做项目的时候没有好好重视日志,所以导致在开发与维护项目出现了很多问题,现在分享分享我的惨痛经历:

  做第一个项目的时候,这个是我第一次开始学习后台时做的第一个项目,使用最原始的 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(……) }

解析:

  1. 避免输出 ‘%C’, ‘%f’, ‘%L’, ‘%M’ 等位置信息 
    当配置文件中的配置项包含 Location 信息会非常昂贵

    • %C 输出类名
    • %F 输出文件名
    • %L 输出行号
    • %M 输出函数名

注:当配置为异步输出的时候,以上位置信息可能会显示不出来,因为实在另外的一个线程记录的调用信息。此时,我们可以使用下面的方法来获取类名和函数名:

StackTraceElement se = Thread.currentThread().getStackTrace()[2];
String msg = se.getClassName() + "-[" + se.getMethodName() + "] " + errorMessage;
  1. 使用异步 
    要使用异步在于要在配置文件中配置 appender,为什么要使用异步来记录日志,前面说过记录日志信息会产生文件 IO,这会影响一定的性能,使用异步可以避免因为需要同步记录日志而产生的等待时间。

  2. 为每个模块设置单独的输出文件 
    根据模块来区分日志文件,在调试和维护某个模块时,可以更方便。

  3. 每次调用前检查 if(logger.isDebugEnabled()) { logger.debug(……) } 
    前面已说过

总结

  日志机制对于开发来说是非常重要的,它关系到调试与维护,在开发一个项目前期,应该提前部署好日志环境。同时,在开发的过程中,要想好如何去记录日志信息,要用哪种级别去记录,权衡性能与维护,选择一种较好的日志实施方案。

本文只是个人观点,如有不同意,可以说出来大家一起讨论讨论。之后再补充一篇使用 slf4j + logback 搭建日志机制的博文。

关于 logger的更多相关文章

  1. ABP源码分析八:Logger集成

    ABP使用Castle日志记录工具,并且可以使用不同的日志类库,比如:Log4Net, NLog, Serilog... 等等.对于所有的日志类库,Castle提供了一个通用的接口来实现,我们可以很方 ...

  2. org.apache.log4j.Logger详解

    org.apache.log4j.Logger 详解 1. 概述 1.1. 背景 在应用程序中添加日志记录总的来说基于三个目的 :监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析工 ...

  3. Java程序日志:java.util.logging.Logger类

    一.Logger 的级别 比log4j的级别详细,全部定义在java.util.logging.Level里面.各级别按降序排列如下:SEVERE(最高值)WARNINGINFOCONFIGFINEF ...

  4. [LeetCode] Logger Rate Limiter 记录速率限制器

    Design a logger system that receive stream of messages along with its timestamps, each message shoul ...

  5. .Net Core Logger 实现log写入本地文件系统

    .net core 自带一个基础的logger框架Microsoft.Extensions.Logging. 微软默认实现了Microsoft.Extensions.Logging.Console.d ...

  6. Android源码——Logger日志系统

    Android的Logger日志系统是基于内核中的Logger日志驱动程序实现的. 日志保存在内核空间中 缓冲区保存日志   分类方法:日志的类型  +   日志的输出量   日志类型:   main ...

  7. java.lang.NoClassDefFoundError: Lorg/slf4j/Logger;

    如果你出现类似如下错误 1. Install tomcat7 in my home directory and set up `CATALINA_HOME` environment variable ...

  8. LeetCode 359 Logger Rate Limiter

    Problem: Design a logger system that receive stream of messages along with its timestamps, each mess ...

  9. 你的日志组件记录够清晰嘛?--自己开发日志组件 Logger

    现在现成的日志组件实在是太多太多,为什么我还需要自己实现呢????? 需求来源于java的log4j, [07-31 16:40:00:557:WARN : com.game.engine.threa ...

  10. log4j2 不使用配置文件,动态生成logger对象

    大家平时使用Log4j一般都是在classpath下放置一个log4j的配置文件,比如log4j.xml,里面配置好Appenders和Loggers,但是前一阵想做某需求的时候,想要的效果是每一个任 ...

随机推荐

  1. Steeltoe

    谈谈Circuit Breaker在.NET Core中的简单应用 http://www.cnblogs.com/catcher1994/p/8975192.html 前言 由于微服务的盛行,不少公司 ...

  2. UVa 11400 - Lighting System Design(线性DP)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  3. PHP------知识复习

    PHP概述 (1)PHP(Hypertext  Perprocessor)超级文本预处理器 (2) PHP是一种在服务器端执行的嵌入HTML文档的脚本语言 (3) 是一种网站开发语言(B/S结构) ( ...

  4. REG小探

    根键名称缩写对照表   常用数据类型

  5. select下拉框之默认选项清空

    最近和小伙伴发现,select默认选项一般是提示信息,怎么才能让当我们点击下拉框时,可选的选项中没有默认的提示信息呢? 思路: 1.当点击下拉框时,让默认提示信息,即下拉框第一个选项移除. 2.当没有 ...

  6. 用Java+xml配置方式实现Spring数据事务(编程式事务)

    一.用Java配置的方式 1.实体类: Role public class Role { private int id; private String roleName; private String ...

  7. [转]java中文乱码的解决

    在基于Java的编程中,经常会碰到汉字的处里及显示的问题,比如一大堆乱码或问号. 这是因为JAVA中默认的编码方式是UNICODE,而中国人通常使用的文件和DB都是基于GB2312或者BIG5等编码, ...

  8. HTML5学习总结——相关练习与项目

    一.小米商城项目 第一天示例代码: <!DOCTYPE html> <html lang="en"> <head> <meta chars ...

  9. Web—04-详解HTML5与CSS3

    CSS权重 CSS权重指的是样式的优先级,有两条或多条样式作用于一个元素,权重高的那条样式对元素起作用,权重相同的,后写的样式会覆盖前面写的样式. 权重的等级 可以把样式的应用方式分为几个等级,按照等 ...

  10. Oracle语句(一)之简单查询

    1.查询数据表的所有列: select * from 表名; 程序员正常用法:select 列名,列名... form 表名; 2.起别名: select 列名 [AS 别名],列名 别名...fro ...