详解Java日志正确使用姿势

前言

关于日志,在大家的印象中都是比较简单的,只须引入了相关依赖包,剩下的事情就是在项目中“尽情”的打印我们需要的信息了。但是往往越简单的东西越容易让我们忽视,从而导致一些不该有的bug发生,作为一名严谨的程序员,怎么能让这种事情发生呢?所以下面我们就来了解一下关于日志的那些正确使用姿势。

正文

日志规范

命名

首先是日志文件的命名,尽量要做到见名知意,团队里面也必须使用统一的命名规范,不然“脏乱差”的日志文件会影响大家排查问题的效率。这里推荐以“projectName_logName_logType.log”来命名,这样通过名字就可以清晰的知道该日志文件是属于哪个项目,什么类型,有什么作用。例如在我们MessageServer项目中监控Rabbitmq 消费者相关的日志文件名可以定义成“messageserver_rabbitmqconsumer_monitor.log”。

保存时间

关于日志保存的时间,普通的日志文件建议保留15天,若比较重要的可根据实际情况延长,具体请参考各自服务器磁盘空间以及日志文件大小作出最优选择。

日志级别

常见的日志级别有以下:

  1. DEBUG级别:记录调试程序相关的信息。
  2. INFO级别:记录程序正常运行有意义的信息。
  3. WARN级别:记录可能会出现潜在错误的信息。
  4. ERROR级别:记录当前程序出错的信息,需要被关注处理。
  5. Fatal级别:表示出现了严重错误,程序将会中断执行。

建议在项目中使用这四种级别, ERROR、WARN、INFO 、DEBUG。

正确姿势

1、提前判断日志级别

//条件判断
if(logger.isDebugEnabled){
  logger.debug("server info , id : " + id + ", user : " + user);
}

//使用占位符
logger.debug("server info , id : {}, user : {}",id,user);

对于DEBUG,INFO级别的日志,在我们的程序中是比较高频的存在,当我们的项目大了,日志变多了,这时候为了程序运行的效率,我们必须以条件判断或者占位符的方式来打印日志。为什么呢?假如我们项目中配置的日志级别为WARN,那么对于我们下面的日志输出语句‘ logger.debug("server info , id : " + id + ", user : " + user);',虽然该日志不会被打印,但是却会执行字符串拼接的操作,这里我们的user是一个实例对象,所以还会执行toString方法,这样就白白浪费了不少系统的资源。

2、避免多余日志输出

在我们的生产环境中,一般禁止DEBUG日志的输出,其打印的频率是非常高的,容易对正常运行的程序造成严重的影响,在我们最近的项目中就有遇到过类似的情况。

那么这时候该学会使用additivity属性

<logger name="xx" additivity="true">

在这边配置成true的话,也就是默认的情况,这时候当前Logger会继承父Logger的Appender,说白了就是当前日志的输出除了输出在当前日志文件以外,还会输出至父文件里。所以一般情况下,我们为了避免重复打印,会将这个参数设置成false,以减少不必要的输出。

3、保证日志记录信息完整

在我们的代码中,日志记录的内容要包含异常的堆栈,请勿随意输出“XX出错”等简单的日志,这对于错误的调试毫无帮助。所以我们在记录异常的时候一定要带上堆栈信息,例如

logger.error("rabbitmq consumer error,cause : "+e.getMessage(),e);

切记在输出对象实例的时候,须确保对象重写了toString方法,否则只会输出其hashCode值。

4、定义logger变量为static

private static final Logger logger = LoggerFactory.getLogger(XX.class);

确保一个对象只使用一个Logger对象,避免每次都重新创建,否则可能会导致OOM。

5、正确使用日志级别

try{
  //..
}catch(xx){
  logger.info(..);
}

这样一来,本来是ERROR的信息,全都打印在INFO日志文件里了,不知情的同事还会在死盯着错误日志,而且还找不出问题,多影响工作效率是吧?

6、推荐使用slf4j+logback组合

logback库里自身就已经实现了slf4j的接口,就无需引入多余的适配器了,而且logback也具有更多的优点,建议新项目可以使用这个组合。
还有一点需要注意,当引入slf4j后,要注意其实际使用的日志库是否是由我们引入的,也有可能会使用了我们第三方依赖包所带入的日志库,这样就可能会导致我们的日志失效。

7、日志的聚合分析

日志的聚合可以把位于不同服务器之间的日志统一起来分析处理,如今ELK技术栈亦或者的EFG(fluentd+elasticsearch+grafana)等都是一些比较成熟的开源解决方案。

拿ELK来说,可以在我们的服务器上直接通过logstash来读取应用打印的日志文件,或者也可以在我们项目中的日志配置文件里配置好相关的socket信息,打印的时候直接把日志信息输出至logstash。再交由elasticsearch存储,kibana展示。

结语

好了,关于日志先聊这么多~ 大家有需要补充或者交流的可以在下方留言哦。

以上所述是小编给大家介绍的Java日志正确使用姿势详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • 浅谈java日志格式化

    1.日志的重要性 不管我们使用何种语言开发,一旦程序发生异常,日志是一个很重要的数据.但是并不是意味着打印的日志越多越好,我们需要的是有用的日志. 曾经参与一个很重要的项目优化,他们的日志没有进行规范,开发.运维也没有把这个事情放在心上.等到压测的时候TPS和响应时间一直上不去.通过jstack分析发现,大部分的log数据在阻塞! 今天我们不讨论具体的日志规范,我从日志中心的角度来聊下LOG的规范 2.日志采集分析 -ELK 目前主流的ELK系统应该都是通过agent端(filebeat/flu

  • 浅谈Java slf4j日志简单理解

    一.理解 slf4j(Simple Logging Facade for Java),表示为java提供的简单日志门面,更底层一点说就是接口.通过将程序中的信息导入到日志系统并记录,实现程序和日志系统的解耦 日志门面接口本身通常并没有实际的日志输出能力,它底层还是需要去调用具体的日志框架API的,也就是实际上它需要跟具体的日志框架结合使用.由于具体日志框架比较多,而且互相也大都不兼容,日志门面接口要想实现与任意日志框架结合可能需要对应的桥接器,就好像JDBC与各种不同的数据库之间的结合需要对应的

  • Java日志组件间关系详解

    一. 总览 本文章不对日志组件进行优劣评价,只是对关系进行对比.在日志中组件中存在这样的几种关系, 这几种关系理解清楚, 有助于我们对日志的引入和使用. 二. 日志门面 日志门面就是指直接引入我们程序中进行记录日志的日志组件,作为日志门面的这些组件会在程序中直接依赖, 上图中就列举的几种常见的日志门面的组件.像一些软件直接回默认使用一些组件, 比如Spring使用的就是commons-logging, activiti使用的日志门面就是slf4j, 其他的软件也都会选用自己认为好用的日志门面.

  • java 日志的数据脱敏的实现方法

    数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护.在涉及客户安全数据或者一些商业性敏感数据的情况下,在不违反系统规则条件下,对真实数据进行改造并提供测试使用,如身份证号.手机号.卡号.客户号等个人信息都需要进行数据脱敏,数据库安全技术之一. 比如我们现在有个user表,含有名字,性别,邮箱,电话号码等字段,但是当查看这些数据时,我们又不希望这些数据被暴露,这时可以对这些数据进行脱敏处理,当然可以根据需要选择哪些字段需要脱敏,然后再输出,至于怎么选择的,是另外一回事

  • 详解Java日志正确使用姿势

    前言 关于日志,在大家的印象中都是比较简单的,只须引入了相关依赖包,剩下的事情就是在项目中"尽情"的打印我们需要的信息了.但是往往越简单的东西越容易让我们忽视,从而导致一些不该有的bug发生,作为一名严谨的程序员,怎么能让这种事情发生呢?所以下面我们就来了解一下关于日志的那些正确使用姿势. 正文 日志规范 命名 首先是日志文件的命名,尽量要做到见名知意,团队里面也必须使用统一的命名规范,不然"脏乱差"的日志文件会影响大家排查问题的效率.这里推荐以"proj

  • 详解java如何正确使用volatile

    volatile关键字在java多线程中有着比较重要作用,volatile主要作用是可以保持变量在多线程中是实时可见的,是java中提供的最轻量的同步机制. 可见性 在Java的内存模型中所有的的变量(这里的变量是类全局变量,并不是局部变量,局部变量在方法内并没有线程安全的问题,因为变量随方法调用完成而销毁)都是存放在主内存中的,而每个线程有自己的工作内存,每次线程执行时,会从主内存获取变量的拷贝,对变量的操作都在线程的工作内存中进行,不同线程之间也不能共享工作内存,只能从主内存读取变量的拷贝.

  • 详解Java中两种分页遍历的使用姿势

    在日常开发中,分页遍历迭代的场景可以说非常普遍了,比如扫表,每次捞100条数据,然后遍历这100条数据,依次执行某个业务逻辑:这100条执行完毕之后,再加载下一百条数据,直到扫描完毕 那么要实现上面这种分页迭代遍历的场景,我们可以怎么做呢 本文将介绍两种使用姿势 常规的使用方法 借助Iterator的使用姿势 1. 数据查询模拟 首先mock一个分页获取数据的逻辑,直接随机生成数据,并且控制最多返回三页 public static int cnt = 0; private static List

  • 详解Java中List的正确的删除方法

    目录 简介 实例 正确方法 法1:for的下标倒序遍历 法2: list.stream().filter().collect() 法3: iterator迭代器 错误方法 法1:for(xxx : yyy)遍历 法2:for的下标正序遍历 原因分析 简介 本文介绍Java的List的正确的删除方法. 实例 需求:有如下初始数据,将list中的所有数据为"b"的元素删除掉.即:填充removeB()方法 package com.example.a; import java.util.Ar

  • 详解Java编写并运行spark应用程序的方法

    我们首先提出这样一个简单的需求: 现在要分析某网站的访问日志信息,统计来自不同IP的用户访问的次数,从而通过Geo信息来获得来访用户所在国家地区分布状况.这里我拿我网站的日志记录行示例,如下所示: 121.205.198.92 - - [21/Feb/2014:00:00:07 +0800] "GET /archives/417.html HTTP/1.1" 200 11465 "http://shiyanjun.cn/archives/417.html/" &qu

  • 详解Java使用JDBC连接MySQL数据库

    一:什么是数据库,为什么要有数据库? 数据,数据库,数据库管理系统和数据库系统是与数据库技术密切相关的四个基本概念. 数据库相信大家都耳熟能详了,其实数据库顾名思义就是存放数据的仓库,只不过这个仓库是在计算机存储设备上,而且数据是按一定的格式存放的~ 可能有朋友就要打断我施法了,停停停,我们Java程序猿在IDEA里面和控制台你侬我侬,没有对象new个对象存储在内存JVM的堆上就行了,学数据库干啥啊? 这时候我们就需要了解到:内存(Memory)也被称为内存储器,其作用是用于暂时存放CPU中的运

  • 详解Java中自定义注解的使用

    目录 什么是注解 注解的注意事项 注解的本质 自定义注解使用 使用方式 1 使用方式 2 什么是注解 在早期的工作的时候 ,自定义注解写的比较多,可大多都只是因为 这样看起来 不会存在一堆代码耦合在一起的情况,所以使用了自定义注解,这样看起来清晰些, Annontation是Java5开始引入的新特征,中文名称叫注解. 它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素(类.方法.成员变量等)进行关联.为程序的元素(类.方法.成员变量)加上更直观.更明了的说

  • 详解Java中@Override的作用

    详解Java中@Override的作用 @Override是伪代码,表示重写(当然不写也可以),不过写上有如下好处: 1.可以当注释用,方便阅读: 2.编译器可以给你验证@Override下面的方法名是否是你父类中所有的,如果没有则报错.例如,你如果没写@Override,而你下面的方法名又写错了,这时你的编译器是可以编译通过的,因为编译器以为这个方法是你的子类中自己增加的方法. 举例:在重写父类的onCreate时,在方法前面加上@Override 系统可以帮你检查方法的正确性. @Overr

  • 详解Java 本地接口 JNI 使用方法

    详解Java 本地接口 JNI 使用方法 对于Java程序员来说,Java语言的好处和优点,我想不用我说了,大家自然会说出很多一套套的.但虽然我们作为java程序员,但我们不得不承认java语言也有一些它本身的缺点.比如在性能.和底层打交道方面都有它的缺点.所以java就提供了一些本地接口,他主要的作用就是提供一个标准的方式让java程序通过虚拟机与原生代码进行交互,这也就是我们平常常说的java本地接口(JNI--java native Interface).它使得在 Java 虚拟机 (VM

  • log4j 详解异步日志的配置和测试

     log4j 详解异步日志的配置和测试 日志可以帮助我们分析故障原因,做些数据挖掘的工作.最简单的日志方法,就是自己写个写文件的方法,在需要打日志的时候调用下,但是这显然不可能在实际工程上用.还有个问题,就是频繁地打日志,会增加磁盘I/O,使得系统性能下降.这里用log4j这个库来部署一个含有日志管理的轻量级的系统,主要支持日志的异步写和等级分类的功能,完成最低限度的日志需求. 首先,我们建立一个Maven工程,并且在pom.xml文件里面引入log4j的依赖: <dependency> &l

随机推荐