用Log4j 2记录日志

说明

maven工程中增加对Log4j 2的依赖

下面代码示例的maven工程中的pom.xml文件中需要增加对Log4j 2的依赖:

  	<dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.20.0</version></dependency>

log4j 2的配置

配置说明参考文档

https://logging.apache.org/log4j/2.x/manual/configuration.html

配置文件中pattern的详细说明

例如,下面配置文件片段中用到了pattern:

  <Appenders><Console name="Console" target="SYSTEM_OUT"><PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/></Console><File name="File1" fileName="${filename}"><PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/></File></Appenders>

pattern的详细说明请参考:
https://logging.apache.org/log4j/2.x/manual/layouts.html#PatternLayout
在这里插入图片描述

通常给每个类创建自己的Logger

为了便于对日志的过滤、搜索、排序等,通常每个类都获取它自己的带名字的Logger,而不是所有类共用一个Logger。
例如通常的做法:
private static final Logger logger = LogManager.getLogger();
创建一个Logger ,名字就是调用类的全限定名。

建议将Logger 声明为static的

Logger 可以声明为static的、或者非static的,但建议声明为static的。这样做的目的是为了节约实例化的成本。

Logger的名字

大多数log实现用层级结构匹配Logger的名字和日志的配置,层级结构用点号“.”表示,跟包名类似。例如,com.thb.register和com.thb.common的父都是com.thb。例如,下面几种写法得到的Logger的名字相同:

package com.thb;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Test {private static final Logger logger = LogManager.getLogger();
}
package com.thb;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Test {	private static final Logger logger = LogManager.getLogger(Test.class);
}
package com.thb;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Test {	private static final Logger logger = LogManager.getLogger(Test.class.getName());
}

替换参数

在记录日志时,经常需要将一些动态信息放进去,log4j 2和log4j 1.x的做法不同。

在log4j 1.x中的做法为如下:

// log4j 1.x中的做法,代码中要显式判断对应级别的日志是否打开
if (logger.isInfoEnabled()) {logger.info("面积为:" + Math.PI * Math.pow(r, 2));
}

上面代码,对日志级别的判断实际进行了两次,第一次是调用isInfoEnabled()方法的时候,第二次是调用info方法记录日志的时候。如果记录日志的地方多,代码就显得庞杂

在log4j 2中的做法为:

// log4j 2中的做法,用替换参数,代码中不需要显式判断对应级别的日志是否打开
logger.info("面积为:{}", Math.PI * Math.pow(r, 2));

上面代码,对日志级别的判断只进行了一次,而且日志字符串只有在对应级别的日志允许输出的情况下才进行构造。代码更加简洁

通过Java-8的Lambda表达式支持日志消息懒构造

log4j 2通过Java-8的Lambda表达式支持日志消息懒构造,即日志消息在对应的日志级别打开的情况下才构造:

logger.info("the information is {}", () -> expensiveOperation())

log4j 2的日志级别

下面日志级别按照由高到低列出:
OFF:不记录日志(其实这个本质上不是日志级别,是个关闭所有日志开关)
FATAL
ERROR
WARN
INFO
DEBUG
TRACE
ALL:所有日志都记录(其实这个本质上不是日志级别,是个打开所有日志开关)

在过滤器或者Logger中配置了某个级别的日志,那么实际会记录该级别及该级别以上的日志。例如,如果配置了日志级别为INFO,那么实际会记录FATAL、ERROR、WARN、和INFO几个级别的日志。

代码示例

代码示例公共说明

如果没有特别说明,下面代码示例中maven工程中src/main/resources/log4j2.xml的配置内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN"><Appenders><Console name="Console" target="SYSTEM_OUT"><PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/></Console><File name="File1" fileName="${filename}"><PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/></File></Appenders><Loggers><Root level="info"><AppenderRef ref="Console"/></Root></Loggers>
</Configuration>

用LogManager.ROOT_LOGGER_NAME获取root Logger的名字

LogManager.ROOT_LOGGER_NAME是root Logger的名字,这个名字是空字符串""。

package com.thb;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Test {public static Logger logger = LogManager.getLogger();public static void main(String[] args) {System.out.println("root logger name: " + LogManager.ROOT_LOGGER_NAME);//System.out.println("logger name: " + logger.getName());		}}

运行结果:

在这里插入图片描述
从上面输出结果可以发现,root Logger的名字是空字符串""。

用LogManager的getLogger()获取一个带名字的Logger

LogManager.getLogger()返回一个带名字的Logger,这个Logger的名字就是调用的类的全限定名称。这个方法经常使用。
下面代码中获取Logger的方法是典型的获取方法。

package com.thb;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Test {private static final Logger logger = LogManager.getLogger();public static void main(String[] args) {		System.out.println("logger name: " + logger.getName());		}}

运行输出:
在这里插入图片描述
从上面输出可以看出,Logger的名字是调用类的全限定名称,此处是com.thb.Test。

几种方法获取相同名字的Logger

方法一:

package com.thb;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Test {private static final Logger logger = LogManager.getLogger();public static void main(String[] args) {System.out.println(logger.getName());}}

运行输出:

com.thb.Test

方法二:

package com.thb;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Test {	private static final Logger logger = LogManager.getLogger(Test.class);public static void main(String[] args) {System.out.println(logger.getName());}}

运行输出:

com.thb.Test

方法三:

package com.thb;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Test {	private static final Logger logger = LogManager.getLogger(Test.class.getName());public static void main(String[] args) {System.out.println(logger.getName());}}

运行输出:

com.thb.Test

用LogManager的getLogger(String name)创建Logger时指定名字

package com.thb;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Test {// 创建Logger时明确指定了名字为Thbprivate static final Logger logger = LogManager.getLogger("Thb");public static void main(String[] args) {double r = 2;// log4j 2中的做法,代码中不需要显式判断对应级别的日志是否打开logger.info("面积为:{}", Math.PI * Math.pow(r, 2));}}

运行输出:

08:55:31.715 [main] INFO  Thb - 面积为:12.566370614359172

在控制台打印一条INFO级别的日志

打印日志的代码:

package com.thb;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Test {private static final Logger logger = LogManager.getLogger();public static void main(String[] args) {		System.out.println("logger name: " + logger.getName());	logger.info("hello");}}

输出:
在这里插入图片描述

在控制台打印日志,使用替换参数构造日志字符串

为了进行对比,首先给出log4j 1.x中的做法:

package com.thb;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Test {private static final Logger logger = LogManager.getLogger();public static void main(String[] args) {double r = 2;// log4j 1.x中的做法,代码中要显式判断对应级别的日志是否打开if (logger.isInfoEnabled()) {logger.info("面积为:" + Math.PI * Math.pow(r, 2));}}}

运行输出:

08:41:01.549 [main] INFO  com.thb.Test - 面积为:12.566370614359172

再给出log4j 2中的做法:

package com.thb;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Test {private static final Logger logger = LogManager.getLogger();public static void main(String[] args) {double r = 2;// log4j 2中的做法,使用替换参数,代码中不需要显式判断对应级别的日志是否打开logger.info("面积为:{}", Math.PI * Math.pow(r, 2));}}

运行输出:

08:43:14.741 [main] INFO  com.thb.Test - 面积为:12.566370614359172

通过Java-8的Lambda表达式支持日志消息懒构造

package com.thb;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Test {private static final Logger logger = LogManager.getLogger();public static void main(String[] args) {double r = 2;// 通过Java-8的Lambda表达式支持日志消息懒构造logger.info("面积为:{}", () -> Math.PI * Math.pow(r, 2));		}}

运行输出:

09:29:48.911 [main] INFO  com.thb.Test - 面积为:12.566370614359172

两个类都定义了静态的Logger,并且在一个类中调用另外一个类的方法

定义一个类,类中定义了自己的静态Logger:

package com.thb;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class AnotherClass {private static final Logger logger = LogManager.getLogger();public void method() {logger.info("hello from AnotherClass");}
}

定义一个主类,在主类中也定义了一个静态Logger:

package com.thb;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Test {private static final Logger logger = LogManager.getLogger();public static void main(String[] args) {		logger.info("hello from Test");AnotherClass another = new AnotherClass();another.method();}}

运行结果:

15:10:28.161 [main] INFO  com.thb.Test - hello from Test
15:10:28.199 [main] INFO  com.thb.AnotherClass - hello from AnotherClass

用traceEntry(String format, Object… params)在函数的入口记录trace日志

maven工程中src/main/resources/log4j2.xml的配置内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN"><Appenders><Console name="Console" target="SYSTEM_OUT"><PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/></Console><File name="File1" fileName="${filename}"><PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/></File></Appenders><Loggers><Root level="trace"><AppenderRef ref="Console"/></Root></Loggers>
</Configuration>

记录日志的代码示例:

package com.thb;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Test {private static final Logger logger = LogManager.getLogger();public static void main(String[] args) {Test test = new Test();test.method("hello", 10);		}public void method(String name, int age) {logger.traceEntry("name: {} and age: {}", name, age);		}}

运行输出:

10:26:48.335 [main] TRACE com.thb.Test - Enter name: hello and age: 10

用traceExit(R result)在函数的结尾记录trace日志

maven工程中src/main/resources/log4j2.xml的配置内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN"><Appenders><Console name="Console" target="SYSTEM_OUT"><PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/></Console><File name="File1" fileName="${filename}"><PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/></File></Appenders><Loggers><Root level="trace"><AppenderRef ref="Console"/></Root></Loggers>
</Configuration>

记录日志的代码示例:

package com.thb;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Test {private static final Logger logger = LogManager.getLogger();public static void main(String[] args) {Test test = new Test();test.method("hello", 10);		}public boolean method(String name, int age) {boolean result = true;logger.traceExit(result);return result;}}

运行输出:

10:36:38.201 [main] TRACE com.thb.Test - Exit with(true)

用traceEntry()和traceExit()记录函数的进入和离开trace日志

如果函数没有参数、或者我们对参数不感兴趣,可以直接用traceEntry()记录函数的进入日志。
如果函数不返回任何结果、或者我们对返回结果不感兴趣,可以直接用traceExit()记录函数的离开日志。
maven工程中src/main/resources/log4j2.xml的配置内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN"><Appenders><Console name="Console" target="SYSTEM_OUT"><PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/></Console><File name="File1" fileName="${filename}"><PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/></File></Appenders><Loggers><Root level="trace"><AppenderRef ref="Console"/></Root></Loggers>
</Configuration>

输出日志代码:

package com.thb;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Test {private static final Logger logger = LogManager.getLogger();public static void main(String[] args) {Test test = new Test();test.method();}public void method() {logger.traceEntry();logger.traceExit();		}
}

运行结果:

11:09:29.794 [main] TRACE com.thb.Test - Enter
11:09:29.799 [main] TRACE com.thb.Test - Exit

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

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

相关文章

微信小程序真机防盗链referer问题处理

公司使用百度云存储一些资源&#xff0c;然后现在要做防盗链&#xff0c;在CDN加入Referer白名单后发现PC是正常的&#xff0c;微信小程序无法正常访问资源了。然后是各种查啊&#xff0c;然后发现是微信小程序不支持Referer的修改&#xff0c;且在小程序开发工具是Referer是固…

Vue3基础_响应式数据

setup是组合式API 选项式API&#xff0c;是data,methods,computed&#xff0c;watch等等全都是分开的&#xff0c;但是组合式API是把这些东西全都写在一起了。 1 vue2的缺点 (1)使用vue2 Vue2版本对数据的拦截用的是Object.defineProperty, 可以监测到对象的变化。因为o…

时序预测 | Matlab实现基于SVR支持向量机回归的电力负荷预测模型

文章目录 预测结果基本介绍程序设计参考资料预测结果 基本介绍 时序预测 | Matlab实现基于SVR支持向量机回归的电力负荷预测模型 支持向量机(英语:support vector machine,常简称为SVM,又名支持向量网络)是在分类与回归分析中分析数据的监督式学习模型与相关的学习算法。给…

BGP实验

实验要求: 优化及要求&#xff1a; 1&#xff0c;AS1存在两个环回&#xff0c;&#xff0c;一个地址为192.168.1.0/24该地址不能在任何协议中宣告, AS3中存在两个环回&#xff0c;一个地址为192.168.2./24该地址不能在任何协议中宣告&#xff0c;最终要求这两个环回可以互相通…

windows开机运行jar

windows开机自启动jar包&#xff1a; 一、保存bat批处理文件 echo off %1 mshta vbscript:CreateObject("WScript.Shell").Run("%~s0 ::",0,FALSE)(window.close)&&exit java -jar E:\projects\ruoyi-admin.jar > E:\server.log 2>&1 &…

性能测试基础知识(三)性能指标

性能测试基础知识&#xff08;三&#xff09;性能指标 前言一、时间特性1、响应时间2、并发数3、吞吐量&#xff08;TPS&#xff09; 二、资源特性1、CPU利用率2、内存利用率3、I/O利用率4、网络带宽使用率5、网络传输速率&#xff08;MB/s&#xff09; 三、实例场景 前言 性能…

机器学习基础知识(1)

什么是机器学习 机器学习是一种通过输入大量数据来构建一种模型&#xff08;网络&#xff09;&#xff0c;这个训练好的模型将会被用来预测或执行某些操作&#xff0c;这个训练的过程和方法就是机器学习。 我们也可以理解为构建一个“函数”&#xff0c;使得这个函数面对我们…

flask服务生成证书文件,采用https访问,开启用户密码验证

openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 3072开启用户密码验证 auth.verify_password def verify_password(username, password):if username abcdefg and password 1234546:return usernameapp.route(/post_request, methods[POST…

mysql 、sql server 常见的区别

&#xff2e;&#xff35;&#xff2c;&#xff2c;   处理 MySQL IFNULL(col , val) SQL Server ISNULL(col,val) 表名、列名等 一般不推荐用保留字 &#xff0c;如果非要保留字 MySQL 用用着重号&#xff0c;即 反引号 包括 select col from GROUP SQL Server 用用着重号…

如何快速完成 App 安全评估报告【最快当天完事】

文章目录 1. App下架展示2. 检查App是否存在问题3. 注册《安全评估》 信息4. 人工快速干预&#xff0c;加快审核步骤5. 面审阶段6. 后续 1. App下架展示 在华为应用市场上架的App突然间被下架&#xff0c;把我搞得猝不及防&#xff0c;原因如下&#xff1a; 是因为我们缺少 《…

两个镜头、视野、分辨率不同的相机(rgb、红外)的视野校正

文章目录 背景实际效果查找资料资料1资料2 解决方案最终结果 背景 目前在做的项目用到两个摄像头&#xff0c;一个是热成像摄像头、另一个是普通的rgb摄像头。 一开始的目标是让他们像素级重合&#xff0c;使得点击rgb图像时&#xff0c;即可知道其像素对应的温度。但是在尝试…

物理机是什么?有什么优势?可以上堡垒机吗?

你知道物理机是什么&#xff1f;有什么优势&#xff1f;可以上堡垒机吗&#xff1f;今天我们就来简单聊聊。 物理机是什么&#xff1f; 物理机是相对于虚拟机而言的对实体计算机的称呼。物理机提供给虚拟机以硬件环境&#xff0c;有时也称为“寄主”或“宿主”。 物理机有什么…

docker compose一键部署lnmt环境

创建docker compose 目录 [rootlocalhost ~]# mkdir -p /compose_lnmt 编写nginx的dockerfile文件 创建目录 [rootlocalhost compose_lnmt]# mkdir -p nginx 编写nginx配置文件 [rootlocalhost nginx]# vim nginx.conf user root; #运行身份#nginx自动设置进程…

web基础与tomcat环境部署

一. 简述静态网页和动态网页的区别。 请求响应信息&#xff0c;发给客户端进行处理&#xff0c;由浏览器进行解析&#xff0c;显示的页面称为静态页面。处理文件类型如.html、jpg、.gif、.mp4、.swf、.avi、.wmv、.flv等 请求响应信息&#xff0c;发给事务端进行处理&#xff0…

红帽8.2版本CSA题库:第一题配置网络设置

红帽认证工程师是业界公认的最权威的Linux认证之一。RHCE 是世界上第一个面向Linux 的认证考试&#xff0c;它不是一个普通的认证测试&#xff0c;和其他操作系统认证考试相比&#xff0c;它没有笔试&#xff0c;全部是现场实际操作&#xff0c;所以RHCE成了业界公认的最难的认…

【Java基础教程】(四十四)IO篇 · 上:File类、字节流与字符流,分析字节输出流、字节输入流、字符输出流和字符输入流的区别~

Java基础教程之IO操作 上 &#x1f539;本节学习目标1️⃣ 文件操作类&#xff1a;File2️⃣ 字节流与字符流2.1 字节输出流&#xff1a;OutputStream2.2 字节输入流&#xff1a;InputStream2.3 字符输出流&#xff1a;Writer2.4 字符输入流&#xff1a;Reader2.5 字节流与字符…

router-view路由出口

这边文章主要讲router-view搭建后台管理系统的一个基本模板 一.创建自己的路由规则 1.新建文件夹src/router/index.js npm i vue-router3.6.5 2.配置好文件 import Vue from "vue"; import VueRouter from "vue-router"; Vue.use(VueRouter);// 1.创建…

俄罗斯方块

俄罗斯方块简单实现 使用 pygame 模块实现俄罗斯方块的简单实现&#xff0c;这里没有使用pygame 自带的碰撞检测&#xff0c;而是自定义的方法实现边界碰撞和方块间碰撞检测。 代码实现 import random import pygame import time # 初始化游戏 pygame.init()# 设置游戏窗口大…

使用AIGC工具提升安全工作效率

新钛云服已累计为您分享760篇技术干货 在日常工作中&#xff0c;安全人员可能会涉及各种各样的安全任务&#xff0c;包括但不限于&#xff1a; 开发某些安全工具的插件&#xff0c;满足自己特定的安全需求&#xff1b;自定义github搜索工具&#xff0c;快速查找所需的安全资料、…

Python(六十七)什么是元组

❤️ 专栏简介&#xff1a;本专栏记录了我个人从零开始学习Python编程的过程。在这个专栏中&#xff0c;我将分享我在学习Python的过程中的学习笔记、学习路线以及各个知识点。 ☀️ 专栏适用人群 &#xff1a;本专栏适用于希望学习Python编程的初学者和有一定编程基础的人。无…