# logback
###### tags: `logback` `java`
Logback is intended as a successor to the popular log4j project.
## 模組
* `logback-core`
另外兩個模組的基礎。
* `logback-classic`
延伸了`logback-core`並大幅改進`log4j`。
* `logback-access`
整合 Servlet containers 提供 HTTP access logs 功能。
## 構成
Logback 由三個元件構成:Logger、Appenders、Layouts。
### Logger context
`TRACE` < `DEBUG` < `INFO` < `WARN` < `ERROR`
### Appenders
### Layouts
(待續)
## 依存性
* `logback-classic`
* `slf4j-api`
* `logback-core`
## 配置
透過 Java 或 XML 兩種方式設定;這個[鏈結](https://logback.qos.ch/translator/)能將`log4j.properties`轉為`logback.xml`。
### 順序
1. `logback-test.xml`
2. `logback.groovy`
3. `logback.xml`
4. 觀察`/META-INF/services/ch.qos.logback.classic.spi.Configurator`、實作`ch.qos.logback.classic.spi.Configurator`的 class。
5. 以上都沒有的話就套用`ch.qos.logback.classic.BasicConfigurator`。
> It takes about 100 miliseconds for Joran to parse a given logback configuration file. To shave off those miliseconds at aplication start up, you can use the service-provider loading facility (item 4 above) to load your own custom Configurator class with BasicConfigrator serving as a good starting point.
解析設定檔大概要100毫秒,直接採用第4種方式能有效地節省應用程式啟動時間。
### XML
```
<?xml encoding="UTF-8" version="1.0"?>
<configuration debug="true" scan="true" scanPeriod="30 seconds" packagingData="true">
<contextName>myAppName</contextName>
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="" level="TRACE|DEBUG|INFO|WARN|ERROR|ALL|OFF|INHERITED|NULL" additivity="true|false"/>
<root level="TRACE|DEBUG|INFO|WARN|ERROR|ALL|OFF">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
```
#### 變數
> Earlier versions of this document used the term "property substitution" instead of the term "variable". Please consider both terms interchangeable although the latter term conveys a clearer meaning.
早期稱**屬性替代**。
### Java
#### `ConsoleAppender`[](http://logback.qos.ch/apidocs/?ch/qos/logback/core/ConsoleAppender.html "ch.qos.logback.core.ConsoleAppender")
|子元素|類型|預設|描述|
|-|-|-|-|
|`encoder`|`ch.qos.logback.core.encoder.Encoder`|`OutputStreamAppender`|See `OutputStreamAppender` properties.|
|`target`|`String`|`System.out`|`System.out`或`System.err`|
|`withJansi`|`boolean`|`false`|Setting withJansi to true activates the Jansi library which provides support for ANSI color codes on Windows machines. On a Windows host, if this property is set to true, then you should put "org.fusesource.jansi:jansi:1.17" on the class path. Note that Unix-based operating systems such as Linux and Mac OS X support ANSI color codes by default.|
```
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
</encoder>
</appender>
```
#### `FileAppender`[](http://logback.qos.ch/apidocs/?ch/qos/logback/core/FileAppender.html "ch.qos.logback.core.FileAppender")
##### `RollingFileAppender`[](http://logback.qos.ch/apidocs/?ch/qos/logback/core/rolling/RollingFileAppender.html "ch.qos.logback.core.rolling.RollingFileAppender")
#### `DBAppender`[](http://logback.qos.ch/apidocs/?ch/qos/logback/classic/db/DBAppender.html "ch.qos.logback.core.DBAppender")
##### 先決條件
在`logback-classic`的`src/main/java/ch/qos/logback/classic/db/script`可以找到對應常見 RDBMS 的 DDL。
###### `logging_event`資料表
* MySQL/MariaDB
```
CREATE TABLE `logging_event` (
`event_id` BIGINT AUTO_INCREMENT PRIMARY KEY, -- 官方的設計是將此欄位放在最後
`occurred` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 這是我自己新增的欄位
`timestmp` BIGINT NOT NULL,
`formatted_message` TEXT NOT NULL,
`logger_name` VARCHAR(256) NOT NULL,
`level_string` VARCHAR(256) NOT NULL,
`thread_name` VARCHAR(256),
`reference_flag` SMALLINT,
`arg0` VARCHAR(256),
`arg1` VARCHAR(256),
`arg2` VARCHAR(256),
`arg3` VARCHAR(256),
`caller_filename` VARCHAR(256) NOT NULL,
`caller_class` VARCHAR(256) NOT NULL,
`caller_method` VARCHAR(256) NOT NULL,
`caller_line` CHAR(4) NOT NULL
)COLLATE=utf8mb4_general_ci;
```
* PostgreSQL
```
CREATE TABLE "logging_event" (
"event_id" serial8 PRIMARY KEY, -- 官方的設計是將此欄位放在最後
"occurred" timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 這是我自己新增的欄位
"timestmp" int8 NOT NULL,
"formatted_message" text NOT NULL,
"logger_name" varchar NOT NULL,
"level_string" varchar NOT NULL,
"thread_name" varchar,
"reference_flag" int2,
"arg0" varchar,
"arg1" varchar,
"arg2" varchar,
"arg3" varchar,
"caller_filename" varchar NOT NULL,
"caller_class" varchar NOT NULL,
"caller_method" varchar NOT NULL,
"caller_line" varchar NOT NULL
);
```
###### `logging_event_property`資料表
* MySQL/MariaDB
```
CREATE TABLE `logging_event_exception` (
`event_id` BIGINT NOT NULL,
`i` SMALLINT NOT NULL,
`trace_line` VARCHAR(256) NOT NULL,
PRIMARY KEY(`event_id`, `i`),
FOREIGN KEY (`event_id`) REFERENCES `logging_event`(`event_id`)
)COLLATE=utf8mb4_general_ci;
```
* PostgreSQL
```
CREATE TABLE "logging_event_exception" (
"event_id" int8 NOT NULL,
"i" int2 NOT NULL,
"trace_line" varchar NOT NULL,
PRIMARY KEY("event_id", "i"),
FOREIGN KEY ("event_id") REFERENCES "logging_event"("event_id")
);
```
###### `logging_event_exception`資料表
* MySQL/MariaDB
```
CREATE TABLE `logging_event_property` (
`event_id` BIGINT NOT NULL,
`mapped_key` VARCHAR(256) NOT NULL,
`mapped_value` TEXT,
PRIMARY KEY(`event_id`, `mapped_key`),
FOREIGN KEY (`event_id`) REFERENCES `logging_event`(`event_id`)
)COLLATE=utf8mb4_general_ci;
```
* PostgreSQL
```
CREATE TABLE "logging_event_property" (
"event_id" int8 NOT NULL,
"mapped_key" varchar NOT NULL,
"mapped_value" text,
PRIMARY KEY("event_id", "mapped_key"),
FOREIGN KEY ("event_id") REFERENCES "logging_event"("event_id")
);
```
##### `<connectionSource/>`
以下實作`ConnectionSource`[](http://logback.qos.ch/apidocs/?ch/qos/logback/core/db/ConnectionSource.html "ch.qos.logback.core.db.ConnectionSource")的類別可取得`Connection`[](https://docs.oracle.com/javase/8/docs/api/?java/sql/Connection.html "java.sql.Connection"):
* `DriverManagerConnectionSource`
* `DataSourceConnectionSource`
* `JNDIConnectionSource`
[How to create JNDI context in Spring Boot with Embedded Tomcat Container](https://stackoverflow.com/questions/24941829/how-to-create-jndi-context-in-spring-boot-with-embedded-tomcat-container)
* `https://stackoverflow.com/questions/52552866/spring-boot-2-embedded-tomcat-jndi-datasource-configuration`