用Log4j 2记录日志

这篇具有很好参考价值的文章主要介绍了用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
用Log4j 2记录日志,log4j,Java

通常给每个类创建自己的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("名字为:" + name);
}

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

在log4j 2中的做法为:

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

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

备注:使用替换参数,后面的参数值如果是函数(没有使用Lambda表达式的方式)就达不到提升性能的效果了,因为此时无论该级别的日志是否真正打开,函数都会被执行。

通过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());		
	}

}

运行结果:

用Log4j 2记录日志,log4j,Java
从上面输出结果可以发现,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());		
	}

}

运行输出:
用Log4j 2记录日志,log4j,Java
从上面输出可以看出,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时明确指定了名字为Thb
	private 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 2记录日志,log4j,Java

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

package com.thb;

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

public class Demo {

    /**
     * 日志类.
     */
    private static final Logger LOGGER = LogManager.getLogger();

    /**
     * 主函数.
     * @param args
     */
    public static void main(String[] args) {
        final String name = "Mike";
        final Demo demo = new Demo();
        LOGGER.info("name is {}", name);
    }
}

运行输出:

08:30:09.638 [main] INFO  com.thb.Demo - name is Mike

不正确地使用替换参数:参数值是函数(不是Lambda表达式)

下面代码中本意是要使用替换参数的方式提升性能(字符串晚构造),但因为参数值是函数(不是Lambda表达式的形式),结果就是即便该级别的日志没有实际打开,函数也会被执行。

package com.thb;

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

public class Demo {

    /**
     * 日志类.
     */
    private static final Logger LOGGER = LogManager.getLogger();

    /**
     * 主函数.
     * @param args
     */
    public static void main(String[] args) {
        final Demo demo = new Demo();

        // 即便这个级别日志级别没有打开,函数method2也会被执行,因为逗号后面是函数
        LOGGER.trace("name is {}", demo.method2());
    }
    
    /**
     * 函数2.
     * @return 字符串
     */
    public String method2() {
        System.out.println("in method2");
        return "in method2";
    }
}

运行输出:

in method2

从上面输出可以看到,尽管trace级别的日志没有被打印,但代替参数值的函数还是被执行了(我们不期望它执行),这样就没有达到提升性能的目的。

通过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

多个参数都使用Lambda表达式

package com.thb;

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

public class Demo {

    /**
     * 日志类.
     */
    private static final Logger LOGGER = LogManager.getLogger();
    private static final int AGE = 10;

    /**
     * 主函数.
     * @param args
     */
    public static void main(String[] args) {
        final Demo demo = new Demo();
        LOGGER.info("name is {} and age is {}", () -> demo.method1(), () -> demo.method2());       
    }

    /**
     * 函数1.
     * @return 名字
     */
    public String method1() {
        return "ok";
    }

    /**
     * 函数2.
     * @return 年龄
     */
    public int method2() {
        return AGE;
    }
}

运行输出:

13:34:17.281 [main] INFO  com.thb.Demo - name is ok and age is 10

参数使用Lambda表达式,因为日志级别没有打开,所以Lambda表达式不会执行

package com.thb;

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

public class Demo {

    /**
     * 日志类.
     */
    private static final Logger LOGGER = LogManager.getLogger();

    /**
     * 主函数.
     * @param args
     */
    public static void main(String[] args) {
        final Demo demo = new Demo();

        // 如果这个级别的日志没有打开,method3不会被执行,因为使用了Lambda表达式
        LOGGER.trace("name is {}", () -> demo.method3());
    }

    /**
     * 函数3.
     * @return 字符串
     */
    public String method3() {
        System.out.println("in method3");
        return "in method3";
    }
}

运行以后没有任何输出,这个是因为trace级别的日志没有被打开,Lambda表达式没有被执行,因此函数method3没有被执行。

两个类都定义了静态的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

用catching(Throwable throwable)打印ERROR级别的异常

catching(Throwable throwable)用 ERROR级别打印异常。

示例:

package com.thb;

import java.io.IOException;

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

public class Demo {
    private static final Logger LOGGER = LogManager.getLogger();
    
    public static void main(String[] args) {
        final Demo demo = new Demo();
        demo.method();
    }

    public void method() {
        try {
            throw new IOException("illegal input type");
        } catch(IOException e) {
            LOGGER.catching(e);
            // do something
        } finally {
            // do something
        }
    }
}

运行输出:
用Log4j 2记录日志,log4j,Java

用catching(Level level, Throwable throwable)打印指定级别的异常

catching(Level level, Throwable throwable)可以用指定级别打印异常。

示例:

package com.thb;

import java.io.IOException;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Demo {
    private static final Logger LOGGER = LogManager.getLogger();
    
    public static void main(String[] args) {
        final Demo demo = new Demo();
        demo.method();
    }

    public void method() {
        try {
            throw new IOException("illegal input type");
        } catch(IOException e) {
            LOGGER.catching(Level.FATAL, e);
            // do something
        } finally {
            // do something
        }
    }
}

运行输出:
用Log4j 2记录日志,log4j,Java文章来源地址https://www.toymoban.com/news/detail-625067.html

到了这里,关于用Log4j 2记录日志的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • logging.level的含义及设置 【java 日志 (logback、log4j)】

    日志级别 tracedebuginfowarnerrorfatal 常用的有:debug,info,warn,error 通常我们想设置日志级别,会用到 logging.level.root=info logging.level设置日志级别,后面跟生效的区域。root表示整个项目。 也可以写某个包,或者某个类。 例如:logging.level.com.ali.service=error。在com.ali.service包下所有

    2024年02月10日
    浏览(27)
  • log4j日志框架的使用

    log4j的配置文件可以理解成有2部分 1根日志记录器  2 各appender(输出源)配置 入口 loggerManager的静态代码块 在loggerManager的静态代码块中,完成对配置文件的读取和解析 然后组装成框架的Logger对象、appender对象完成初始化操作 当调用logger.info打印日志时,和logback的流程基本一样

    2024年02月04日
    浏览(41)
  • Log4j疯狂写日志问题排查

    最近有个 Java 系统上线后不久就收到了磁盘使用率告警,磁盘使用率已经超过了 90% 以上,并且磁盘使用率还在不停增长。 由于服务器磁盘被打满,导致了系统正常的业务日志无法继续打印,严重影响了系统的可靠性。 刚开始收到磁盘告警的时候,怀疑是日志级别问题,业务

    2024年02月13日
    浏览(39)
  • 使用Log4j与log4j2配置mybatisplus打印sql日志

    环境:项目非完全spring项目,没有spring的配置文件。执行sql时老是不打印sql语句。因此进行修改,过程比较坎坷,记录一下。 我尝试使用log4j和log4j2进行配置 最终把这两种全部配置记录上 Log4j配置 如果项目用的是log4j需要进行配置打印sql的步骤 首先引入log4j的包 配置一下l

    2024年02月04日
    浏览(43)
  • SpringCloud使用log4j日志框架教程

    上一篇文章我们介绍了《SpringCloud使用logback日志框架教程》,本文我们再来介绍下log4j2。 Log4j2是一款流行的Java日志框架,它提供了高度可配置的日志记录功能,支持多种不同的输出格式和目标,比如文件、控制台、数据库等等。Log4j2的设计目标是提供高性能、低延迟的日志

    2024年02月16日
    浏览(37)
  • Mybatis日志Log4j与Logback

    目录 一、Log4j与Logback的区别? 发展历史和维护 二、Slf4j 依赖 三、Logback使用 logback.xml配置文件 四、Log4j使用 五、查看日志内容 发展历史和维护 Log4j是最早的Java日志框架之一,具有较长的历史;然而Log4j 1.x版本在性能和并发性方面存在一些限制,并且已经停止维护。 Logbac

    2024年02月12日
    浏览(59)
  • JAVA中使用log4j及slf4j进行日志输出的方法

    JAVA中输出日志比较常用的是log4j,这里讲下log4j的配置和使用方法,以及slf4j的使用方法。 一、下载log4j的架包,并导入项目中,如下: 二、创建log4j.properties配置文件 1、log4j配置文件的位置: (1)如果是java project项目,则在项目的根目录下创建log4j.properties而不是在src目录下

    2024年02月07日
    浏览(29)
  • 1.12 springboot 整合log4j打印日志

    1.除去springboot自带的日志 2.添加log4j依赖 3. 添加log4j依赖对应的配置文件log4j.properties[api模块下的resources文件夹下创建] 4.log4j日志应用

    2024年02月16日
    浏览(34)
  • was下log4j设置日志不输出问题

    WAS 也是用的 commons-logging 日志框架 commons-logging 确定 LogFactory 实现的顺序是 从应用的 META-INF/services/org.apache.commons.logging.LogFactory 中获得 LogFactory 实现 从系统环境中获得 org.apache.commons.logging.LogFactory 获得 LogFactory 实现 从 classpath 下的 commons-logging.properties 文件中获得 LogFactory 实

    2024年02月08日
    浏览(38)
  • log4j--动态打印日志文件到指定文件夹

    1、添加Maven依赖 2、配置文件 log4j.properties 3、编写日志打印工具类 LogUtil 4、工具类调用 测试结果:

    2024年02月16日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包