logback-spring.xml详解

本文来写说下logback-spring.xml相关的知识与概念

文章目录

  • 概述
  • configuration元素
  • 定义上下文名称
  • 定义变量
  • appender组件
  • RollingFileAppender配置
  • logger配置
  • root配置
  • ELK的配置
  • 输出logback状态数据
  • 异步输出日志
  • 代码中的日志格式
  • 本文小结


概述

对于xml日志文件的配置,大多数人第一次接触时有一种望而生畏的感觉,其实如果仔细分析,会发现核心的部分只有三个元素:appender、logger、root

在这里插入图片描述
通过上图我们可以清晰的了解整个xml文件的元素及功能。

其中configuration是根元素,必须的;logger和root可视为同一类,都是日志组件;logger定义日志从哪里(包)获取以及级别;appender配置日志格式、如何过滤、文件处理等。property和contextName元素,分别用来定义变量和应用上下文名称,非必须。

先通过一个简单的日志模板,从视觉上感受一下:

<configuration><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><logger name="chapters.configuration" level="INFO"/><root level="DEBUG">          <appender-ref ref="STDOUT" /></root>  
</configuration>

上述实例定义了控制台输出debug级别日志的配置。下面对相关的元素进行逐一讲解。


configuration元素

logback.xml配置文件的基本结构可以描述为configuration元素,包含零个或多个appender元素,后跟零个或多个logger元素,后跟最多一个root元素(也可以没有)。

根元素configuration有三个属性:

  • debug:默认为false,若设置为true,则打印出logback内部日志信息。
  • scan:默认值为true,若设置为true,配置文件如果发生改变,将会被重新加载。
  • scanPeriod:与scan配合使用,当scan为true时,此属性生效,默认的时间间隔为1分钟,设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。如可以设置为scanPeriod="30 seconds"每30秒检测一次。

定义上下文名称

contextName元素,每一个日志组件(logger)都会关联到日志上下文,默认上下文名称是’default’,用于标识应用,如果多个应用输出到同一个地方,就有必要使用%contextName来区别。

上线文的配置直接在configuration元素下:

<configuration><contextName>HelloWorld-log</contextName>
</configuration>

经过定义之后,在其他property属性或appender中便可通过“%contextName”来获取和使用该上下文名称了。


定义变量

通过property元素可定义变量。它有name和value两个属性。变量可以使“${name}”来使用变量。作用类似于代码中的常量字符串,定义之后公共地方便可以统一使用。如日志文件名称前缀、日志路径、日志输出格式等。

<configuration><property name="log.path" value="./log" />
</configuration>

上面便是定义了日志的根路径的变量。

如果是在Spring或SpringBoot项目当中,想让value值是通过配置文件获取,可使用springProperty来定义。

<springProperty scope="context" name="log.path" 
source="catalina.base"/>

其中source指定的catalina.base便是在application.properties当中配置变量。此配置还是比较常用的,可以做到灵活区分环境。


appender组件

appender组件用来定义日志输出格式,日志如何过滤以及日志文件的处理。appender的结构如下:

在这里插入图片描述
appender的属性有name和class。name指定appender名称,后面使用该appender是也是通过名称来指定。

class属性指定要实例化的appender类的完全限定名称。appender类默认有以下几种:

  • ConsoleAppender:日志输出到控制台,类名ch.qos.logback.core.ConsoleAppender。
  • FileAppender:日志输入到文件,类名ch.qos.logback.core.FileAppender。
  • RollingFileAppender:滚动记录文件,FileAppender的子类,当符合条件(大小、时间),日志进行切分处理。类名:ch.qos.logback.core.rolling.RollingFileAppender。

appender元素可以包含零个或一个layout元素,零个或多个encoder元素以及零个或多个filter元素。

实战中ConsoleAppender及RollingFileAppender使用较多,若需要自定义如把日志输出到消息队列,可以自定义实现AppenderBase接口。

ConsoleAppender上面已经有示例,主要作用就是将日志输出到控制台,并通过pattern元素指定了输出的格式。下面重点看一下RollingFileAppender的配置。


RollingFileAppender配置

RollingFileAppender是FileAppender的子类,扩展了FileAppender,具有翻转日志文件的功能。

例如,RollingFileAppender可以记录到名为log.txt文件的文件,并且一旦满足某个条件,就将其日志记录目标更改为另一个文件。

RollingFileAppender通常包括File、filter,rollingPolicy,encoder和layout元素。

encoder用来指定日志的输出格式及编码等:

<!-- 文件输出日志格式 -->
<property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} 
%contextName [%thread] %-5level %logger{36} - %msg%n" />
<appender><!--日志文件输出格式--><encoder><pattern>${FILE_LOG_PATTERN}</pattern><charset class="java.nio.charset.Charset">UTF-8</charset></encoder>
</appender>

file元素用来配置日志的路径和名称,一般把路径和文件名前缀定义到变量(property中)。

<encoder><!-- 正在记录的日志文件的路径及文件名 --><file>${log.path}/log_error.log</file>
</appender>

${log.path}获取的便是前面属性中定义的变量。

appender中可以有多个filter元素,比如用ThresholdFilter来过滤低于指定临界值的日志;用LevelFilter来过滤日志级别。以LevelFilter为例:

<!-- 过滤器,只记录debug级别的日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter"><level>DEBUG</level><OnMismatch>DENY</OnMismatch><OnMatch>ACCEPT</OnMatch>
</filter>

其中level指定日志级别,onMath指定符合过滤条件的操作接收(ACCEPT),onMismatch指定不符合条件的拒绝(DENY)。

如果需要将不同级别的日志输出到不同的日志文件,那么就需要配置多个filter,每个filter像上面一样指定level级别:DEBUG,INFO,WARN和ERROR。

通常情况下,日志输出会配置三个,一个控制台输出用于开发阶段;一个INFO及以上级别的日志输出,可追踪相应的生产日志;一个单独ERROR级别的日志输出,方便快速检查出异常日志。

rollingPolicy用于配置滚动策略,支持TimeBasedRollingPolicy、SizeAndTimeBasedRollingPolicy、FixedWindowRollingPolicy、SizeBasedTriggeringPolicy。

分别是基于时间滚动、基于大小和时间滚动、固定窗口滚动和大小触发。其中FixedWindowRollingPolicy一般和SizeBasedTriggeringPolicy同时使用。下面以TimeBasedRollingPolicy为例,以天为单位输出日志,每天一个日志。

<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 日志输出格式 --><fileNamePattern>${log.path}/debug.%d{yyyy-MM-dd}.log</fileNamePattern><!-- 日志保留天数 --><maxHistory>30</maxHistory>
</rollingPolicy>

fileNamePattern指定日志的路径及名称,此处是按日期输出,即%d{yyyy-MM-dd}格式。maxHistory表示日志最多保留天数,存活超过30天的日志会被删除。


logger配置

logger用来设置某一个类或者某个包的日志输出级别、以及关联的appender。

logger包含三个属性:

  • name:要输出日志的包名或者类名,比如com.secbro2。必选项。
  • level:设置日志级别,允许一个不区分大小写的字符串值TRACE,DEBUG,INFO,WARN,ERROR,ALL或OFF。如果未设置,则logger会向上继承最近一个非空级别。可选项。
  • additivity:是否将日志向上级传递,默认为 true。可选项。

logger通过1个或多个子节点appender-ref来控制日志的输出。

<logger name="org.springframework" level="WARN"/>
<logger name="com" level="debug" />

上面示例表示org.springframework包下的日志以warn级别输出,com包下的日志以debug级别输出。

<logger name="com.secbro2" level="info" additivity="true"><appender-ref ref="CONSOLE" />
</logger>

上面的示例对指定包指定appender进行日志控制,由于设置了info级别,additivity为true,而且关联CONSOLE的appender,因此info以上级别的日志会输出到控制台。

同时会把日志上传到父级,即root。若root也有配置CONSOLE的输出的话,会在控制台输出两次。additivity为false,则不会。


root配置

root元素配置根记录器。它是一个特殊的logger,是所有logger的根节点,只有一个属性level,默认为DEBUG 。

<root level="info"><appender-ref ref="CONSOLE" /><appender-ref ref="LOGSTASH" /><appender-ref ref="INFO_FILE" /><appender-ref ref="ERROR_FILE" />
</root>

level属性的值可以是不区分大小写的字符串TRACE,DEBUG,INFO,WARN,ERROR,ALL或OFF之一。root元素可以包含零个或多个appender-ref元素;被引用的每个appender都被添加到根记录器中。

如果是基于SpringBoot项目,针对不同环境(profile)有不同的日志输出,比如开发(dev)环境只输出CONSOLE的,生产环境(prod)只输入info和error,那则可用到Spring支持的profile机制。对应的元素为springProfile。

profile的值与springboot中配置文件的spring.profiles.active值进行对照。

<!-- 开发环境 -->
<springProfile name="dev"><logger name="com" level="debug" /><root level="info"><appender-ref ref="CONSOLE" /></root>
</springProfile>
<!-- 测试环境+生产环境 -->
<springProfile name="test,prod"><logger name="com" level="info" /><root level="info"><appender-ref ref="INFO_FILE" /><appender-ref ref="ERROR_FILE" /></root>
</springProfile>

当引入了springProfile,我们可以看到root元素可以出现多次了,但还是保证了一个环境只有一个root元素的要求。springProfile的name对应spring.profiles.active的值,多个值用逗号分隔。


ELK的配置

如果项目中的日志采用的是基于ELK(Elasticsearch,Logstash,Kibana三个开源软件的缩写)来进行日志管理。则可以在pom文件中引入logstash-logback-encoder依赖。

<dependency><groupId>net.logstash.logback</groupId><artifactId>logstash-logback-encoder</artifactId><version>5.1</version>
</dependency>

然后在logback-spring.xml中配置对应的appender:

<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender"><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>debug</level></filter><destination>192.168.0.11:5061</destination><encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder"><customFields>{"project": "springboot-logback-elk"}</customFields></encoder>
</appender>

该appender的使用与其他appender的使用无异。主要使用了LogstashTcpSocketAppender类来完成与Logstash的通信。其中destination为Logstash提供的服务地址。customFields为自定义的参数,便于Logstash识别日志是从哪个业务系统传输过来的。


输出logback状态数据

某些时候为了了解logback配置文件加载情况,配置中对应的appender、logger的装载情况等,我们需要启用logback状态数据的输出。这也是logback官网强烈推荐的,可以帮助我们排除诊断一些问题。

启用状态数据输出有两种方式:

  • 在根元素(configuration) 中设置属性debug=“true”。
  • 添加元素(statusListener),class使用OnConsoleStatusListener。如下:
<!-- 输出logback的本身状态数据 -->
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />

两种方式选其一即可。第一种方式的debug与配置文件中的日志级别没有关系,只用于表示输出状态数据。


异步输出日志

前面讲到的appender,日志输出到文件是同步输出的,即每次输出都会直接写IO到磁盘文件。对于高并发的应用,会产生一定的阻塞,造成不必要的性能损耗。

logback提供了日志异步输出的AsyncAppender。处理方式也很简单,添加一个基于异步写日志的appender,并指向原配置的appender即可:

<!-- 异步输出 -->
<appender name="ASYNCDEBUG" class="ch.qos.logback.classic.AsyncAppender"><!-- 默认如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志,若要保留全部日志,设置为0 --><discardingThreshold>0</discardingThreshold><!-- 更改默认的队列的深度,该值会影响性能.默认值为256 --><queueSize>1024</queueSize><!-- 添加附加的appender,最多只能添加一个 --><appender-ref ref="DEBUGFILE"/><includeCallerData>true</includeCallerData>
</appender><!-- 异步输出关联到root -->
<root level="DEBUG"><appender-ref ref="STDOUT"/><appender-ref ref="ASYNCDEBUG" />//...
</root>

AsyncAppender的实现原理是通过阻塞队列(BlockingQueue)来避免日志直接输出到文件,先把日志事件输出到BlockingQueue中,然后启动一个新的worker线程,主线程不阻塞,worker线程则从队列中获取需要写的日志,异步输出到对应的位置。


代码中的日志格式

在日常使用日志时,可以通过最开始的示例定义Logger对象,然后调用其对应级别的日志输出。当然,如果采用Lombok的情况下,可直接类上使用@Slf4j注解来自动注入log属性,不用再声明:

private static final Logger log = LoggerFactory.getLogger(LogbackController.class);

替换为:

@Slf4j
@RestController
public class LogbackController {}

其他内容不变。

而在日志输出格式也有多种,其中最不可取的形式是如下模式的日志输出:

Object entry = new SomeObject(); 
logger.debug("The entry is " + entry);

这种模式会导致即使采用info基本输出,debug中的对象toString和字符串拼装依旧会处理。建议采用如下模式输出:

Object entry = new SomeObject(); 
logger.debug("The entry is {}.", entry);

此时,如果日志输出级别为info,则不会处理对象的toString和字符串的拼接。

logback作者进行测试得出:第一种和第二种写法输出结果相同。但在禁用日志记录语句的情况下,第二种将比第一种写法优于至少30倍。


本文小结

到此,关于logback日志框架的讲解告一段落,如果你还想了解更多底层原理和一些表达式,建议看一下官方的手册,虽然是英文的,但还是比较全面的。

本文用巨大篇幅,描述了logback日志常见的使用场景,想必读到此处时,原来在那复杂的日志配置文件已经变得十分简单吧。赶快尝试一下吧。用了两天写完这篇文章,多多支持,你懂得该怎么做的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/6042.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端web入门-移动web-day09

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 空间转换 空间转换 – 平移 视距 perspective 空间 – 旋转 立体呈现 – transform-style 空间转换…

Ubuntu下编译VTK

1.先安装QT&#xff0c;不知道不装行不行&#xff0c;我们项目需要。 2.去VTK官网下载VTK源码。 3.解压源码。 4.编译需要用cmake-gui&#xff0c;装QT的一般都有&#xff0c;但需要把路径添加到PATH才能用。 5.打开cmake-gui&#xff0c;设置源码路径&#xff0c;编译输出路…

只要你会vue,5分钟学不会 svelte 你来找我

&#x1f33b; 前言 2023年了&#xff0c;国内前端领域基本被Vue、React占领市场&#xff0c;近几年似乎前端技术栈的迭代更新缓慢了下来。 当然近几年也出现了像svelte、solid.js等一些新兴的前端框架&#xff0c;这些框架有很多创新的点&#xff0c;比如svelte相比于vue,re…

JS文件UTF8格式乱码问题

UTF8格式的JS文件在IE中显示乱码问题的解决 这种情况通常是由于JS文件头缺少BOM标志引起的,解决方式: 方法1:用系统自带记事本,另存为 UTF-8,覆盖原文件,会自动加上BOM标志(就是文件开头的EF BB BF 三个字节) 方法2: 用notepad 打开,编码菜单,由UTF8编码改为 UTF8-BOM编码

利用RabbitMQ实现消息投递削峰填谷

目录 异步和同步如何选择 异步线程 同步收发消息 一、导入依赖库 二、创建RabbitMQ配置类 三、创建消息任务类 异步和同步如何选择 依靠多线程&#xff0c;Java代码可以同步执行也可以异步执行 RabbitMQ提供了同步和异步两种收发消息模式 我们采用 Java异步线程 MQ同步…

机器学习小结之决策树

文章目录 前言一、介绍1.1 原理1.2 流程1.3 信息熵&#xff0c;信息增益和基尼不纯度 二、构建决策树2.1 特征选择2.2 决策树生成2.3 剪枝 三、经典算法3.1 ID33.2 C4.53.3 CART 四、案例4.1 Iris 数据集 鸢尾花 分类4.2 基于决策树的英雄联盟游戏胜负预测 参考 前言 决策树(D…

盒马上市,即时零售最大“变量”

若盒马年内成功上市&#xff0c;等待完成下一轮融资的朴朴超市的处境恐将更加尴尬&#xff0c;另区域性中小商超或将迎来新一轮倒闭潮。 疫情过后&#xff0c;国内消费市场一直处于走弱态势。据商务大数据监测&#xff0c;今年端午假期&#xff0c;部分地区零售和餐饮数据远不及…

2023年前端面试汇总-React

1. 组件基础 1.1. React事件机制 <div onClick{this.handleClick.bind(this)}>点我</div> React并不是将click事件绑定到了div的真实DOM上&#xff0c;而是在document处监听了所有的事件&#xff0c;当事件发生并且冒泡到document处的时候&#xff0c;React将事…

【Linux】基础IO——文件描述符/缓冲区/重定向/文件系统

文章目录 一、文件描述符二、缓冲区三、重定向的原理四、文件系统 (Linux Ext2)1 认识磁盘的结构CHSLBABlock 2 认识文件系统2.1 分区2.2 文件系统的结构2.3 剖析inode2.4 文件的操作 3 软硬链接3.1 软链接3.2 硬链接 &#x1f4dd; 个人主页 &#xff1a;超人不会飞)&#x1f…

JVM 常量池、即时编译与解析器、逃逸分析

一、常量池 1.1、常量池使用 的数据结构 常量池底层使用HashTable key 是字符串和长度生成的hashValue&#xff0c;然后再hash生成index, 改index就是key&#xff1b;Value是一个HashTableEntry&#xff1b; 1、key hashValue hash string(name&#xff0c; len) i…

LVS负载均衡群集部署——NAT模式

LVS负载均衡群集部署——NAT模式 一、企业群集应用概述1、群集概述2、解决方法3、根据集群针对的目标差异分类 二、负载均衡群集架构三、LVS 的三种工作模式1、NAT 地址转换2、TUN IP隧道 IP Tunnel3、DR 直接路由 Direct Routing 四、LVS的负载调度算法五、ipvsadm工具六、NAT…

linux shell pgrep命令使用方法(pgrep指令)获取进程号、统计进程数量(学会区分Linux进程进程名)

文章目录 问题背景pgrep指令help文档使用示例1. 列出匹配进程的PID和进程名称&#xff08;-l&#xff09;&#xff08;默认只能从进程名的子集字符串匹配&#xff0c;如果要使用完整进程名的子集字符串匹配&#xff0c;请加-f参数&#xff0c;下同&#xff09;2. 列出匹配进程的…