log4j2

いつも忘れるので、ここでメモ。

## jar ファイル
最低限、以下のファイルが必要。
log4j-core-2.13.3.jar
log4j-api-2.13.3.jar
(2.13.3 はこれを書いている時点の最新バージョン)
maven:
[https://mvnrepository.com/artifact/org.apache.logging.log4j](https://mvnrepository.com/artifact/org.apache.logging.log4j)

★ commons-logging と接続したい場合は、log4j-jcl-2.13.3.jar も必要です。
詳細はこちら：[https://stackoverflow.com/questions/41462181/commons-logging-with-log4j2](https://stackoverflow.com/questions/41462181/commons-logging-with-log4j2)

★ slf4j 使用、以下のエラーが出た場合、log4j-slf4j-impl を追加する必要ある

```shell
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
```

## pom.xml
```xml:pom.xml
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
	<groupId>org.apache.logging.log4j</groupId>
	<artifactId>log4j-core</artifactId>
	<version>2.13.3</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
<dependency>
	<groupId>org.apache.logging.log4j</groupId>
	<artifactId>log4j-api</artifactId>
	<version>2.13.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-jcl -->
<!-- https://stackoverflow.com/questions/41462181/commons-logging-with-log4j2 -->
<dependency>
	<groupId>org.apache.logging.log4j</groupId>
	<artifactId>log4j-jcl</artifactId>
	<version>2.13.3</version>
</dependency>
<!-- slf4j -->
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.13.3</version>
    <!-- <scope>test</scope> -->
</dependency>
```

## log4j2.xml
```xml:log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE project>
<Configuration status="off">
	<Properties>
		<Property name="format1">%d{yyyy/MM/dd HH:mm:ss.SSS} [%t] %-6p %c{10}#%M:%L | %m%n</Property>
	</Properties>
	<Appenders>
		<Console name="Console" target="SYSTEM_OUT">
			<PatternLayout>
				<pattern>${format1}</pattern>
			</PatternLayout>
		</Console>
	</Appenders>

	<Loggers>
		<logger name="com.zaxxer.hikari" level="info" additivity="false">
			<AppenderRef ref="Console" />
		</logger>
		<Root level="trace">
			<AppenderRef ref="Console" />
		</Root>
	</Loggers>
</Configuration>
```
%M: 出力箇所のメソッド名（遅くなる）
%L: 出力箇所の行数（遅くなる）
[https://logging.apache.org/log4j/2.x/manual/layouts.html#PatternLine](https://logging.apache.org/log4j/2.x/manual/layouts.html#PatternLine)

## Java
```java:Log4j2Test.java
package cn;

import java.lang.invoke.MethodHandles;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Log4j2Test {

    private static final Logger logger = LogManager.getLogger(MethodHandles.lookup().lookupClass());

    public static void main(String[] args) {
        int times = 3;
        long start = System.currentTimeMillis();
        String str = "test1";
        logger.debug("at {} {} tests {} times.", start, str, times); // {} と 変数の数が一致

        logger.debug("at {} @@@@@@@@", start, str, times); // {} が少ない

        logger.debug("at {} {} tests {} times.1{},2{},3{},4", start, str, times); // 変数が少ない

        logger.debug("lessionId={}", () -> lessionId); // java8 lambda
        logger.info("lessionId={}", () -> lessionId);
        logger.warn("lessionId={}", () -> lessionId);
        logger.fatal("lessionId={}", () -> lessionId);
        logger.error("lessionId={}", () -> lessionId);
    }
}
```

```shell:out
2020/08/06 00:07:27.888 [main] DEBUG  cn.Log4j2Test#main:16 | at 1596640047883 test1 tests 3 times.
2020/08/06 00:07:27.894 [main] DEBUG  cn.Log4j2Test#main:18 | at 1596640047883 @@@@@@@@
2020/08/06 00:07:27.894 [main] DEBUG  cn.Log4j2Test#main:20 | at 1596640047883 test1 tests 3 times.1{},2{},3{},4
```

メッセージをフォーマットする処理：
org.apache.logging.log4j.message.ParameterFormatter.countArgumentPlaceholders2(String, int[])
org.apache.logging.log4j.message.ParameterFormatter.formatMessage2(StringBuilder, String, Object[], int, int[])

## SpringBoot で logback をやめて、log4j2 にしたい場合
```xml:pom.xml
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<!-- exclude logback -->
			<exclusions>
				<exclusion>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-starter-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<!-- add log4j2 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-log4j2</artifactId>
		</dependency>
```

## Log4j2 のバージョン確認。（Runtime）
```java
Package p = org.apache.logging.log4j.core.Layout.class.getPackage();
System.out.println(p);
System.out.println("Implementation title:   " + p.getImplementationTitle());
System.out.println("Implementation vendor:  " + p.getImplementationVendor());
System.out.println("Implementation version: " + p.getImplementationVersion());
```

参考リンク：
[https://qiita.com/mato-599/items/979e10135c1cb54ceda9](https://qiita.com/mato-599/items/979e10135c1cb54ceda9)
[https://qiita.com/pica/items/f801c74848f748f76b58](https://qiita.com/pica/items/f801c74848f748f76b58)
https://stackoverflow.com/questions/37438652/how-can-i-find-out-what-version-of-log4j-i-am-using/37438968#37438968
以上