java日志打印使用指南
一、简介
- 日志打印是java代码开发中不可缺少的重要一步。
- 日志可以排查问题,可以搜集数据
二、常用日志框架
比较常用的日志框架就是logback, 一些老项目会使用log4j,他们用的都是slf4j-api统一接口。
(1) 使用log4j
log4j使用:
1. slf4j-api-1.5.11.jar
2. slf4j-log4j12-1.5.11.jar
3. log4j-1.2.15.jar
4. log4j.properties
代码中
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Logger logger = LoggerFactory.getLogger(xx.class);
(2) 使用logback
logback使用:
1. slf4j-api-1.5.11.jar
2. logback-core.jar
3. logback-classic.jar
4. logback.xml
代码同log4j
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Logger logger = LoggerFactory.getLogger(xx.class);
三、日志级别
TRACE < DEBUG < INFO < WARN < ERROR
日常使用较多的是error, info , debug
四、logback简单介绍
简单介绍下常用的logback,logback优点:
- 比log4j更快
- 和log4j使用了同一个接口,slf4j-api,可以非常方便切换
- 定义了功能非常丰富的appender
- 支持日志压缩
logback要正确理解xml配置文件
- configuration:总的父节点
- property:自定义属性
- appender:输出控制器,可以输出到控制台,自定义文件等
- logger:日志级别
- root:控制器级别
一个例子:
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds">
<contextName>XXXXXXXX</contextName>
<property name="log.path" value="./log/"/>
<!-- 日志最大的历史 30天 -->
<property name="maxHistory" value="30"/>
<property name="log.pattern"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%-5level] [%logger{30}:%line] %msg%n"/>
<!--输出到控制台-->
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
<!--LevelFilter: 级别过滤器,根据日志级别进行过滤。如果日志级别等于配置级别,过滤器会根据onMath 和 onMismatch接收或拒绝日志。-->
<!--例如:将过滤器的日志级别配置为INFO,所有INFO级别的日志交给appender处理,非INFO级别的日志,被过滤掉。-->
<!--<filter class="ch.qos.logback.classic.filter.LevelFilter">-->
<!--<level>INFO</level>-->
<!--<onMatch>ACCEPT</onMatch>-->
<!--<onMismatch>DENY</onMismatch>-->
<!--</filter>-->
<!--ThresholdFilter: 临界值过滤器,过滤掉低于指定临界值的日志。当日志级别等于或高于临界值时,过滤器返回NEUTRAL;当日志级别低于临界值时,日志会被拒绝。-->
<!-- 过滤掉所有低于 DEBUG 级别的日志,留下DEBUG及以上级别的日志 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 时间滚动输出 level为 INFO 日志 -->
<appender name="errorFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--LevelFilter: 级别过滤器,根据日志级别进行过滤。如果日志级别等于配置级别,过滤器会根据onMath 和 onMismatch接收或拒绝日志。-->
<!--例如:将过滤器的日志级别配置为INFO,所有INFO级别的日志交给appender处理,非INFO级别的日志,被过滤掉。-->
<!--<filter class="ch.qos.logback.classic.filter.LevelFilter">-->
<!--<level>INFO</level>-->
<!--<onMatch>ACCEPT</onMatch>-->
<!--<onMismatch>DENY</onMismatch>-->
<!--</filter>-->
<!--ThresholdFilter: 临界值过滤器,过滤掉低于指定临界值的日志。当日志级别等于或高于临界值时,过滤器返回NEUTRAL;当日志级别低于临界值时,日志会被拒绝。-->
<!-- 过滤掉所有低于 DEBUG 级别的日志,留下DEBUG及以上级别的日志 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/error.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${log.path}/error-%d{yyyyMMdd}.%i.log.zip</fileNamePattern>
<!--日志文件保留天数-->
<maxHistory>${maxHistory}</maxHistory>
<!-- 日志总保存量为2GB -->
<totalSizeCap>2GB</totalSizeCap>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!--文件达到 最大100MB时会被压缩和切割 -->
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 时间滚动输出 level为 INFO 日志 -->
<appender name="infoFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--LevelFilter: 级别过滤器,根据日志级别进行过滤。如果日志级别等于配置级别,过滤器会根据onMath 和 onMismatch接收或拒绝日志。-->
<!--例如:将过滤器的日志级别配置为INFO,所有INFO级别的日志交给appender处理,非INFO级别的日志,被过滤掉。-->
<!--<filter class="ch.qos.logback.classic.filter.LevelFilter">-->
<!--<level>INFO</level>-->
<!--<onMatch>ACCEPT</onMatch>-->
<!--<onMismatch>DENY</onMismatch>-->
<!--</filter>-->
<!--ThresholdFilter: 临界值过滤器,过滤掉低于指定临界值的日志。当日志级别等于或高于临界值时,过滤器返回NEUTRAL;当日志级别低于临界值时,日志会被拒绝。-->
<!-- 过滤掉所有低于 DEBUG 级别的日志,留下DEBUG及以上级别的日志 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/info.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${log.path}/info-%d{yyyyMMdd}.%i.log.zip</fileNamePattern>
<!--日志文件保留天数-->
<maxHistory>${maxHistory}</maxHistory>
<!-- 日志总保存量为10GB -->
<totalSizeCap>2GB</totalSizeCap>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!--文件达到 最大100MB时会被压缩和切割 -->
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 时间滚动输出 level为 INFO 日志 -->
<appender name="debugFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--LevelFilter: 级别过滤器,根据日志级别进行过滤。如果日志级别等于配置级别,过滤器会根据onMath 和 onMismatch接收或拒绝日志。-->
<!--例如:将过滤器的日志级别配置为INFO,所有INFO级别的日志交给appender处理,非INFO级别的日志,被过滤掉。-->
<!--<filter class="ch.qos.logback.classic.filter.LevelFilter">-->
<!--<level>INFO</level>-->
<!--<onMatch>ACCEPT</onMatch>-->
<!--<onMismatch>DENY</onMismatch>-->
<!--</filter>-->
<!--ThresholdFilter: 临界值过滤器,过滤掉低于指定临界值的日志。当日志级别等于或高于临界值时,过滤器返回NEUTRAL;当日志级别低于临界值时,日志会被拒绝。-->
<!-- 过滤掉所有低于 DEBUG 级别的日志,留下DEBUG及以上级别的日志 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/debug.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${log.path}/debug-%d{yyyyMMdd}.%i.log.zip</fileNamePattern>
<!--日志文件保留天数-->
<maxHistory>${maxHistory}</maxHistory>
<!-- 日志总保存量为2GB -->
<totalSizeCap>2GB</totalSizeCap>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!--文件达到 最大100MB时会被压缩和切割 -->
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<logger name="com.baomidou" level="debug"/>
<root level="info">
<appender-ref ref="consoleAppender"/>
<appender-ref ref="errorFileAppender"/>
<appender-ref ref="infoFileAppender"/>
<appender-ref ref="debugFileAppender"/>
</root>
</configuration>
五、常见问题
- 1、日志打的少,不好排查问题?
我们经常会遇到一个生产问题,去看日志,啥都没有,只能重新加日志,发包,再排查问题;
所以我们要养成打日志的习惯,开发环境可以debug看,生产看不了,只能加日志,在开发的时候就把必要的日志加上;
比较重要的是接口的入参,返回,重要节点开始,结束,mq发送接收等。
- 2、error, info , debug分别都什么时候使用?
error: 捕获异常的时候使用,这个没有异议
info: 比较重要的信息,使用频次不是非常高的场景,比如入参出参
debug: 一个是不是特别重要的信息,但是又不能少,还有数据量大的数据,比如大量mq信息,访问频繁的接口入参出参
- 3、开启debug好多无用的debug信息怎么办?
把项目的目录定为debug,其它定成info。这样只有本项目的debug日志会打印了
logging.level.root=info
logging.level.cn.mypackage=debug
- 4、需要自定义日志文件吗?
logback可以把日志写进自定义文件,debug,info,error分开存储,历史数据还能压缩;
按自己项目的需求来,大型项目建议分开存储。
- 5、springboot启动命令自带的日志和自定义日志文件的日志重复怎么办?
我们一般启动springboot项目命令为:nohup java -jar XXXXXXXX.jar >> XXXXXXX.log 2>&1 &
这个会生成一个日志文件,logback配置也会生成自己的日志文件,就会重复,造成空间浪费,如何取舍?
如果你们公司统一打包脚本的话,就用命令生成的日志文件吧,把logback配置去掉;
如果你们公司自由度比较高,就用logback生成的日志,把命令改成 >/dev/null 就可以了
- 6、debug日志正确写法?
有些人可能打debug日志直接logger.debug("****");
如果项目的日志级别比较高,就比较浪费性能,可以加一个
if (log.isDebugEnabled()) {
log.debug("XXXXXXXXXXXXX");
}
- 7、动态日志级别?
有些公司支持动态配置文件,比如diamond,nacos等,可以修改配置文件的级别,动态生效
logging.level.root=info
#logging.level.root=debug
日常开在info,出了问题开debug找,资源有限可以这样做,不推荐生产使用
欢迎关注微信公众号:丰极,更多技术学习分享。
java日志打印使用指南的更多相关文章
- Java日志打印方法
一.使用log4j打印日志 1. 下载log4j.jar和commons-logging.jar. log4j.jar下载地址:http://logging.apache.org/log4j/ ...
- [翻译]Java日志终极指南
本文由 ImportNew - Wing 翻译自 loggly.欢迎加入翻译小组.转载请见文末要求. Java日志基础 Java使用了一种自定义的.可扩展的方法来输出日志.虽然Java通过java.u ...
- Java日志终极指南
Java日志基础 Java使用了一种自定义的.可扩展的方法来输出日志.虽然Java通过java.util.logging包提供了一套基本的日志处理API,但你可以很轻松的使用一种或者多种其它日志解决方 ...
- java中的日志打印
java中的日志打印: 日志工具类: #获取日志 INFO:表示获取日志的等级 A1:表示日志存器,可以自定义名称 #===DEBUG INFO log4j.rootLogger=DEBUG,A1,A ...
- Java编码常见的Log日志打印问题
前言 本文总结了作者在Java代码检视中遇到的一些关于日志打印的问题,并给出修改建议.因能力有限,难免存在错漏,欢迎指正. 一. 不规范的异常打印 使用slf4j日志组件时,logger.error( ...
- Java中打印日志,这4点很重要!
目录 一.预先判断日志级别 二.避免无效日志打印 三.区别对待错误日志 四.保证记录完整内容 打印日志,要注意下面4点. 一.预先判断日志级别 对DEBUG.INFO级别的日志,必须使用条件输出或者使 ...
- Java如何打印日志
以下为<正确的打日志姿势>学习笔记. 什么时候打日志 1.程序出现问题,只能通过 debug 功能来定位问题,很大程度是日志没打好.良好的系统,通过日志就能进行问题定位. 2.if-els ...
- 涨姿势:Java 分业务、分级别实现自定义日志打印
自定义日志级别 通常的日志框架都有以下几个级别,从低到高TRACE,DEBUG,INFO,WARN,ERROR,FATAL. 默认情况,假如我们定义日志打印级别INFO,它会把大于等于INFO级别的日 ...
- java中日志打印
目录 一.预先判断日志级别 二.避免无效日志打印 三.区别对待错误日志 四.保证记录完整内容 打印日志,要注意下面4点. 一.预先判断日志级别 对DEBUG.INFO级别的日志,必须使用条件输出或者使 ...
随机推荐
- uni-app + Cloudbase——uni-app 项目中如何使用腾讯云开发后端服务
1 基本介绍 uni-app 是一个基于 Vue.js 的跨端开发框架,一套代码可以发布到 App.小程序.Web 等不同平台 腾讯云开发平台 Cloudbase 提供的 @cloudbase/js- ...
- C# 脚本
有些情况下,需要在程序运行期间动态执行C#代码,比如,将某些经常改变的算法保存在配置文件中,在运行期间从配置文件中读取并执行运算.这时可以使用C#脚本来完成这些工作. 使用C#脚本需要引用库Micro ...
- CF950A Left-handers, Right-handers and Ambidexters 题解
Content 有 \(l\) 个人是左撇子,有 \(r\) 个人是右撇子,另外有 \(a\) 个人既惯用左手又惯用右手.现在想组成一个队伍,要求队伍中惯用左手的人和惯用右手的人相等,试求出团队里面的 ...
- TCP 长连接保活机制&HTTP长连接设置
TCP KeepAlive Wireshark抓包分析机制 -------------------------------- 如上图所示,TCP保活报文总是成对出现,包括TCP保活探测报文和TCP保活 ...
- CentOS系统 python3+python2 & Ipython安装
https://www.cnblogs.com/albertrui/p/8093384.html 一.安装依赖环境 输入命令: yum -y install zlib-devel bzip2-deve ...
- 【LeetCode】100. Same Tree 解题报告(Java & Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 [LeetCode] 题目地址:https:/ ...
- 【LeetCode】239. Sliding Window Maximum 解题报告(Python&C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 单调递减队列 MultiSet 日期 题目地址:ht ...
- 【LeetCode】102. Binary Tree Level Order Traversal 二叉树的层序遍历 (Python&C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 BFS DFS 日期 题目地址:https://lee ...
- 教你Python字符串的基本操作:拆分和连接
摘要:由于字符串数据几乎无处不在,因此掌握有关字符串的交易工具非常重要.幸运的是,Python 使字符串操作变得非常简单,尤其是与其他语言甚至旧版本的 Python 相比时. 本文分享自华为云社区&l ...
- 第三十六个知识点:Index Calculus算法
第三十六个知识点:Index Calculus算法 我们这篇博客继续描述一种数学攻击,这种数学攻击被叫做Index Calculus(IC)算法. 注意这里Index Calculus算法没有找到合适 ...