log4j2日志简单使用

news2024/10/7 5:30:31

log4j2日志使用

1、log4j2介绍

Apache Log4j2是对Log4j的升级版,
log4j2借鉴了logback的一些优秀的设计,并且修复了一些问题,因此带来了一些重大的提升,主要有:
1、异常处理:在logback中,Appender中的异常不会被应用感知到,但是在log4j2中,提供了一些异常处理机制。
2、性能提升:log4j2相较于log4j 1和logback都具有很明显的性能提升,在异步配置下是logback的10倍左右。
3、自动重载配置:参考了logback的设计,提供自动刷新参数配置,可以动态的修改日志的级别而不需要重启应用。
4、无垃圾机制,log4j2在大部分情况下,都可以使用其设计的一套无垃圾机制,避免频繁的日志收集导致的jvm gc。

详情可参考其官方文档:http://logging.apache.org/log4j/2.x/manual/configuration.html

log4j2既可以作为日志实现,也可以作为日志门面来使用,不过在日常开发中,习惯于将log4j2作为日志实现,slf4j作为日志门面来结合使用。

2、实践

2.1 pom依赖

  1. 若为本地maven工程的测试:

    在2.9之后,新增了对进程号的显示格式: %processId

    log4j2作为日志门面和 实现****所需导入如下依赖:

    <dependencies>
        <!--log4j依赖:api和core-->
        <!--log4j日志门面-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.13.3</version>
        </dependency>
        <!--log4j日志实现-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.13.3</version>
        </dependency>
    </dependencies>
    
    
    

    slf4j作为日志门面,log4j2作为日志实现所需导入依赖:

    <dependencies>
        <!--使用slf4j作为日志门面-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.28</version>
        </dependency>
        <!--使用log4j的适配器进行绑定-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.9.1</version>
        </dependency>
        <!--log4j日志实现-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.13.3 </version>
        </dependency>
    </dependencies>
    
  2. 若为Springboot工程,则需要引用如下依赖:

    如项目中有导入spring-boot-starter-web依赖包, 记得去掉spring自带的日志依赖spring-boot-starter-logging,如下:

    <dependencies>
       <!--springboot工程需要使用的log4j2的依赖--> 
    	<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
     	<!--如果引用由web的依赖,需要排除掉spring自带的logging日志依赖-->   
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>    
    
    

2.2 配置文件

添加上述依赖后,需要添加配置文件log4j2.xml,放置在resources目录下:

<?xml version="1.0" encoding="UTF-8"?>
<!-- status表示设置的日志级别,高于该级别的日志显示,monitorInterval配置成一个正整数,则每隔指定的时间(秒),
        log4j2会刷新一次配置。如果不配置则不会动态刷新 -->
<configuration status="info" monitorInterval="600" >

    <properties>
        <property name="LOG_HOME">./logs</property>
        <!--info日志的标准输出文件名字-->
        <property name="FILE_NAME_INFO">std</property>
        <!--error日志的标准输出文件名字-->
        <property name="FILE_NAME_ERROR">error</property>
        <!--日志输出的格式-->
        <!--日期时间|日志级别|所属类的全类名|线程名|进程号|方法名|日志信息-->
        <property name="PATTERN_LAYOUT">%d{yyyy-MM-dd HH:mm:ss}|%-5level|%c{5}|%t|%processId|%M|%m%n</property>
    </properties>
    <!--先定义所有的appender -->
    <Appenders>
        <!--这个输出控制台的配置 -->
        <Console name="Console" target="SYSTEM_OUT">
            <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
            <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
            <!--输出日志的格式 引用定义的格式-->
            <PatternLayout pattern="${PATTERN_LAYOUT}"/>
        </Console>

        <!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用 -->
        <!--append为true表示消息追加到指定文件中,false表示消息覆盖指定的文件内容,默认值是true -->
        <RollingRandomAccessFile   name="info" fileName="${LOG_HOME}/${FILE_NAME_INFO}.log" append="true"
                                   filePattern="${LOG_HOME}/${FILE_NAME_INFO}.log.%d{yyyy-MM-dd}">
            <Policies>
                <!--TimeBasedTriggeringPolicy :时间滚动策略,默认0点小时产生新的文件, modulate="true" : 产生文件是否以0点偏移时间-->
                <TimeBasedTriggeringPolicy/>
            </Policies>
            <!--       日志输出格式     -->
            <PatternLayout pattern="${PATTERN_LAYOUT}"/>
        </RollingRandomAccessFile  >

        <!--添加过滤器Filters,可以有选择的输出某个级别以上的类别  onMatch="ACCEPT" onMismatch="DENY"意思是匹配就接受,否则直接拒绝  -->
        <RollingRandomAccessFile   name="error" fileName="${LOG_HOME}/${FILE_NAME_ERROR}.log"
                                   filePattern="${LOG_HOME}/${FILE_NAME_ERROR}.log.%d{yyyy-MM-dd}">
            <Policies>
                <!--TimeBasedTriggeringPolicy :时间滚动策略,默认0点小时产生新的文件, modulate="true" : 产生文件是否以0点偏移时间-->
                <TimeBasedTriggeringPolicy/>
            </Policies>

            <Filters>
                <!--记录error级别信息 -->
                <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <!--输出日志的格式 -->
            <PatternLayout pattern="${PATTERN_LAYOUT}"/>
        </RollingRandomAccessFile  >
    </Appenders>


    <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效 -->
    <loggers>
        <root level="info">
            <appender-ref ref="Console"/>
            <appender-ref ref="error" />
            <appender-ref ref="info"/>
        </root>
        <!--向root上报这个包下的debug级别的日志-->
        <logger name = "com.kevin" level="debug" />
    </loggers>
</configuration>

2.3 测试代码

package com.kevin.log4j;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Test;

/**
 * @Author Kevin
 * @Date 22:04 2023/4/18
 * @Description
 */
public class Log4j2Demo {

    private static  Logger log = LogManager.getLogger();
    @Test
    public void log4j2DemoTest1(){
        System.out.println("===========显示打印Debug日志信息=============");
        log.debug("log level is DEBUG:{}","this is DEBUG log...");
        
        System.out.println("===========显示打印Info日志信息=============");
        log.info("log level is INFO:{}","this is INFO log...");
        
        System.out.println("===========显示打印Warn日志信息=============");
        log.warn("log level is WARN:{}","this is WARN log...");
        
        System.out.println("===========显示打印Error日志信息=============");
        log.error("log level is ERROR:{}","this is ERROR log...");
    }
}

在这里插入图片描述

控制台输出结果:
在这里插入图片描述

日志文件中的结果:
在这里插入图片描述

配置文件的格式: log2j配置文件可以是xml格式的,也可以是json格式的,
配置文件的位置: log4j2默认会在classpath目录下寻找log4j2.xml、log4j.json、log4j.jsn等名称的文件,如果都没有找到,则会按默认配置输出,也就是输出到控制台,也可以对配置文件自定义位置(需要在web.xml中配置),一般放置在src/main/resources根目录下即可

配置文件的名称: 必须为log4j2字样

个人踩坑: 将log4j2.xml配置成了log4j.xml,结果log4j2没有找到对应的xml配置,按照默认配置输出到控制台上:只显示error级别的日志信息:
在这里插入图片描述

2.4 配置文件详解

log4j2.xml文件的配置大致如下:

  • Configuration
    • properties
    • Appenders
      • Console
        • PatternLayout
      • File
      • RollingRandomAccessFile
      • Async
    • Loggers
      • Logger
      • Root
        • AppenderRef

1、Configuration: 为根节点,有status和monitorInterval等多个属性

  • status:用于表示控制log4j2的日志级别,其值的级别从小到大依次有: “trace”, “debug”, “info”, “warn”, “error” and “fatal”,只会显示高于status值级别的日志会显示。
  • monitorInterval:每隔多长时间重新读取配置文件,可以不重启应用的情况下修改配置,时间单位:秒;

2、 Appenders: 输出源,用于定义日志输出的地方
log4j2支持的输出源有很多,有控制台Console、文件File、RollingRandomAccessFile、MongoDB、Flume 等

  • Console: 控制台输出源,是将日志打印到控制台上,开发的时候一般都会配置,以便进行调试

  • File: 文件输出源,将日志写入到指定的文件,需要配置输入到哪个位置(例如:./app/logs)

  • RollingRandomAccessFile: 该输出源也是写入到文件,不同的是比File更加强大,可以指定当文件达到一定大小(如20MB)时,另起一个文件继续写入日志,另起一个文件就涉及到新文件的名字命名规则,因此需要配置文件命名规则;这种方式更加实用,因为你不可能一直往一个文件中写,如果一直写,文件过大,打开就会卡死,也不便于查找日志。

    RollingRandomAccseeFile:中有如下常用属性:

    • fileName 指定当前日志文件的位置和文件名称
    • filePattern 指定当发生Rolling时,文件的转移和重命名规则,大多用.log.时间进rolling:filePattern="${LOG_HOME}/${FILE_NAME_INFO}.log.%d{yyyy-MM-dd}">
    • SizeBasedTriggeringPolicy 指定当文件体积大于size指定的值时,触发Rolling
    • DefaultRolloverStrategy 指定最多保存的文件个数
    • TimeBasedTriggeringPolicy 这个配置需要和filePattern结合使用,注意filePattern中配置的文件重命名规则是${FILE_NAME}-%d{yyyy-MM-dd HH-mm}-%i,最小的时间粒度是mm,即分钟;若指定的size是1,结合起来就是每1分钟生成一个新文件。如果改成%d{yyyy-MM-dd HH},则最小粒度为小时,就会每一个小时生成一个文件

3、PatternLayout: 日志输出的格式

  • 控制台或文件输出源(Console、File、RollingRandomAccessFile)都必须包含一个PatternLayout节点,用于指定输出文件的格式(如 日志输出的时间 文件 方法 行数 等格式)

  • 例如 %d{yyyy-MM-dd HH:mm:ss}|%-5level|%c{5}|%t|%processId|%M|%m%n

  • 日期时间|日志级别|所属类的全类名|线程名|进程号|方法名|日志信息

    # 日志常用的显示格式含义:
    %c 输出所属类的全名,可写为 %c{Num} ,Num类名输出的范围 如:"com.kevin.study.DemoClass",%C{2}将使日志输出输出范围为:study.DemoClass
    %d 输出日志时间其格式为 可指定格式 如 %d{yyyy-MM-dd HH:mm:ss}等
    %l 输出日志事件发生位置,包括类目名、发生线程,在代码中的行数
    %n 换行符
    %m输出代码指定信息,如info(“message”),输出message 一般输出:%m%n放在最后
    %msg 显示日志文本
    %-5level 输出日志级别,-5表示左对齐并且固定输出5个字符,如果不足在右边补0
    %-5p 输出日志的优先级,即 FATAL ,ERROR 等; 与-5level效果一样
    %r 输出从启动到显示该条日志信息所耗费的时间(毫秒数)
    %t 输出产生该日志事件的线程名
    %processId 输出进程号,2.9之后新增
    %M 显示方法名
    

4、Loggers: 日志器

日志器分为:根日志器Root和自定义日志器,当根据日志名字获取不到指定的日志器时,就使用Root作为默认的日志器,自定义时需要指定每个Logger的名称name(对于命名可以以包名作为日志的名字,不同的包配置不同的级别等),日志级别level,相加性additivity(是否继承下面配置的日志器), 对于一般的日志器(如Console、File、RollingRandomAccessFile)一般需要配置一个或多个输出源AppenderRef;

每个logger可以指定一个level(TRACE, DEBUG, INFO, WARN, ERROR, ALL or OFF),不指定时level默认为ERROR

additivity指定是否同时输出log到父类的appender,缺省为true。

5、properties: 属性
使用来定义常量,以便在其他配置的时候引用,该配置是可选的,譬如:

  • 定义日志的存放位置 ,当前目录下的logs文件夹下:<property name="LOG_HOME">./logs</property>
  • 定义日志的输出格式:<property name="PATTERN_LAYOUT">%d{yyyy-MM-dd HH:mm:ss}|%5p|%c{5}|%t|%processId|%M|%m%n</properties>

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Makefile通用模板

工程目录 假如我们有以下目录结构&#xff1a; . ├── inc │ ├── add.h │ └── sub.h ├── main.c └── src├── add.c└── sub.c文件中的内容如下&#xff1a; //main.c #include <stdio.h> #include "add.h" #include "sub.h&q…

Mysql 学习(六)Mysql的数据目录

数据库中数据的存放 Mysql中 InnoDB 和 MyISAM 这样的存储引擎都是把数据存储到磁盘上的&#xff0c;而我们把这种存放到磁盘上的东西叫做文件系统&#xff0c;当我们想读取对应数据的时候&#xff0c;就会把数据从文件系统上加载&#xff0c;并且处理返回给我们&#xff0c;当…

每日学术速递4.19

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.CV 1.Visual Instruction Tuning 标题&#xff1a;可视化指令调优 作者&#xff1a;Haotian Liu, Chunyuan Li, Qingyang Wu, Yong Jae Lee 文章链接&#xff1a;https://arxiv.org/ab…

Midjourney:一步一步教你如何使用 AI 绘画 MJ

一步一步如何使用 Midjourney 教程&#xff1a;教学怎么用 MJ&#xff1f; 一、Midjourney&#xff08;MJ&#xff09;是什么&#xff1f; Midjourney是一款使用文字描述来生成高质量图像的AI绘画工具。这篇文章主要介绍了Midjourney及其用途&#xff0c;并针对Midjourney的使…

python 定时任务执行命令行

1.使用场景&#xff1a; 定时执行jmeter脚本&#xff0c;通过python定时器隔一段时间执行命令行命令。 2.库&#xff1a; os、datetime、threading &#xff08;1&#xff09;利用threading.Timer()定时器实现定时任务 Timer方法说明Timer(interval, function, argsNone, k…

如何利用python实现TURF分析?

1.TRUF分析简介 TURF分析(Total Unduplicated Reach and Frequency)是累计净到达率和频次分析的简称。最初被应用于媒介研究领域。典型应用场景是&#xff0c;在既定条件下&#xff0c;例如预算等资源限制或就当前实施的媒体组合投放计划&#xff0c;哪些渠道组合能让广告投放…

【三十天精通Vue 3】第十二天 Vue 3 过滤器详解

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: 三十天精通 Vue 3 文章目录 引言一、Vue 3 过滤器概述1.1 过滤器的简介1.2 过滤器的作用1.3 过…

WEB通用漏洞水平垂直越权详解业务逻辑访问控制脆弱验证

目录 一、知识点概述 <分类> <原理简述> 二、水平越权示例——检测数据比对弱 <越权演示> <如何防护> 三、垂直越权示例——权限操作无验证 <越权演示> <漏洞成因> 四、访问控制示例——代码未引用验证 <越权演示> 五、脆…

如何才能写出一个符合预期的正则?

如何才能写出一个符合预期的正则&#xff1f; 正则表达式入门示例讲解1、java里正则表达式replaceAll连续的字符正则测试题主问题讲解 2、开发者遇到金额的校验正则描述正则测试 3、java正则表达式匹配字符串正则描述正则测试 4、关于#正则表达式#的问题&#xff0c;如何解决&a…

0基础自学软件测试 用这个方法 99%的人都成功了

对于大多数0基础的小白而言&#xff0c;刚开始学软件测试&#xff0c;肯定会遇到各种各样的难题&#xff0c;有时候问题多了&#xff0c;扛不住了&#xff0c;导致最后无法坚持&#xff0c;或者学的很杂&#xff0c;学而不精。 那么有哪些比较有效的方法和技巧&#xff0c;可以…

系统分析师之数据库系统(七)

目录 一、数据库概念 1.1 数据库管理系统DBMS 1.2 数据库系统DBS 二、数据库设计 2.1 数据库设计过程 2.2 E-R模型 2.3 关系代数 2.4 规范化理论 2.4.1 价值与用途 2.4.2 函数依赖 2.4.3 键 2.4.4 范式 2.4.5 无损分解 三、并发控制 3.1 基本概念 3.2 问题示例…

SCA技术进阶系列(二):代码同源检测技术在供应链安全治理中的应用

一、直击痛点&#xff1a;为什么需要同源检测 随着“数字中国”建设的不断提速&#xff0c;企业在数字化转型的创新实践中不断加大对开源技术的应用&#xff0c;引入开源组件完成应用需求开发已经成为了大多数研发工程师开发软件代码的主要手段。随之而来的一个痛点问题是&…

开启数字化之旅:VR全景视频带你进入真实而神奇的世界

引言&#xff1a;随着科技的不断发展&#xff0c;虚拟现实技术正在成为越来越多人所追捧和体验的技术。而VR全景视频作为虚拟现实技术的一种重要应用&#xff0c;也得到了越来越多人的关注。那么&#xff0c;VR全景视频到底是什么&#xff1f;它的优势和特点是什么&#xff1f;…

OpenGL入门教程之 变化颜色的三角形

一、 知识点 &#xff08;1&#xff09;着色器 着色器(Shader)是运行在GPU上的小程序。这些小程序为图形渲染管线的某个特定部分而运行。从基本意义上来说&#xff0c;着色器只是一种把输入转化为输出的程序。着色器也是一种非常独立的程序&#xff0c;因为它们之间不能相互通…

153. 寻找旋转排序数组中的最小值

已知一个长度为 n 的数组&#xff0c;预先按照升序排列&#xff0c;经由 1 到 n 次 旋转 后&#xff0c;得到输入数组。例如&#xff0c;原数组 nums [0,1,2,4,5,6,7] 在变化后可能得到&#xff1a; 若旋转 4 次&#xff0c;则可以得到 [4,5,6,7,0,1,2] 若旋转 7 次&#xff0…

【刷题】搜索——BFS:字串变换【双向广搜模板】

双向广搜是BFS的一种优化方式&#xff0c;就是起点和终点同时往中间搜索。 假设每搜一步&#xff0c;都会有6种新的状态进入队列&#xff0c;搜索10步才能得到答案&#xff0c;总状态数是 1 6 6 2 6 3 . . . 6 9 166^26^3...6^9 166263...69。 但是假如已知终点的状态&am…

Crash分析gpu非法访问地址问题

Crash分析gpu非法访问地址问题 1. 问题描述 在我司产品monkey老化过程中&#xff0c;极低概率出现gpu驱动访问非法地址导致kernel panic问题&#xff0c;在kernel panic后&#xff0c;主动触发ramdump机制&#xff0c;抓到相关的ramdump文件&#xff0c;利用crash工具进行离线…

ggrcs包2.9版本发布----增加了绘制单独rcs曲线(限制立方样条)的singlercs函数

目前本人写的ggrcs包新的2.8版本已经在CRAN上线&#xff0c;目前支持逻辑回归&#xff08;logistic回归&#xff09;、cox回归和多元线性回归。增加了绘制单独rcs曲线&#xff08;限制立方样条&#xff09;的singlercs函数。 需要的可以使用代码安装 install.packages("…

UE4/5多人游戏详解(五、创建多人游戏插件)

目录 创建插件&#xff1a; 功能制作&#xff1a; 基础构造&#xff1a; 代码&#xff1a; 准备&#xff1a; 代码&#xff1a; 之前4个内容&#xff0c;我简单的讲解了一个项目中如何加入多人会话。 现在我们做一个插件&#xff0c;这样就不需要每一次创建项目的时候就…

CT前瞻(二):Vant4实战之Card卡片与Cell单元格

文章目录 &#x1f4cb;前言&#x1f3af;关于 Card卡片 和 Cell单元格 组件&#x1f9e9;Cell单元格&#x1f9e9;Card卡片 &#x1f3af;实战代码&#x1f4dd;最后 &#x1f4cb;前言 最近在项目开发和学习的过程中&#xff0c;涉及到了Vant UI&#xff08;简称Vant&#x…