1、定义appender
1.1 logback.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径 -->
<!-- <property name="LOG_HOME" value="d:" /> -->
<!-- ch.qos.logback.core.ConsoleAppender 控制台输出 -->
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<!-- 自定义文件输出-错误日志 -->
<appender name="ErrorFile" class="com.ybw.logback.demo.filter.LogFileAppender">
<File>${LOG_HOME:-c:/}logs/error/error.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME:-c:/}logs/error/error-%d{yyyy-MM-dd}.%i.log
</FileNamePattern>
<MaxHistory>30</MaxHistory>
<TimeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>100MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印错误日志 -->
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder charset="UTF-8">
<pattern>[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="stdout"/>
<appender-ref ref="ErrorFile"/>
</root>
</configuration>
1.2 自定义appender代码
package com.ybw.logback.demo.filter;
import ch.qos.logback.core.encoder.Encoder;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.spi.DeferredProcessingAware;
import ch.qos.logback.core.status.ErrorStatus;
import com.ybw.logback.demo.constant.fs.FSConstant;
import com.ybw.logback.demo.utils.FsUtils;
import java.io.IOException;
/**
* 自定义的appender
* 1.可以对接受到的event中的日志信息做任何操作处理
* 2.可以在同步写日志文件的时候,存入MySQL或者es
*
* @author ybw
* @version V1.0
* @className LogFileAppender
* @date 2022/9/16
**/
public class LogFileAppender<E> extends RollingFileAppender<E> {
public void setEncoder(Encoder encoder) {
//自定义的appender的父类OutputStreamAppender在启动的时候会判断是否有encoder ,无的话自定义appender启动会失败
super.setEncoder(encoder);
}
/**
* 覆盖父类OutputStreamAppender的日志记录功能,再这里面做日志切操作功能
*
* @param event
*/
protected void subAppend(E event) {
if (this.isStarted()) {
try {
if (event instanceof DeferredProcessingAware) {
((DeferredProcessingAware) event).prepareForDeferredProcessing();
}
//根据标签规则拿到日志字符串,这里可以再次修改日志信息
byte[] byteArray = super.encoder.encode(event);
//做一些日志的特殊处理
sendFs(byteArray);
// writeMongo(...);
// writeRedis(...);
// writeMq(...);
//写入日志文件
writeBytes(byteArray);
} catch (IOException var3) {
this.started = false;
this.addStatus(new ErrorStatus("IO failure in appender", this, var3));
}
}
}
/**
* 飞书报警
*
* @param byteArray
* @methodName: sendFs
* @return: void
* @author: ybw
* @date: 2022/9/15
**/
private void sendFs(byte[] byteArray) {
if (byteArray != null && byteArray.length != 0) {
this.lock.lock();
try {
FsUtils.sendTextMessage(FSConstant.TextContentEnum.ERROR_LOG, new String(byteArray));
} finally {
this.lock.unlock();
}
}
}
private void writeBytes(byte[] byteArray) throws IOException {
if (byteArray != null && byteArray.length != 0) {
this.lock.lock();
try {
this.getOutputStream().write(byteArray);
if (this.isImmediateFlush()) {
this.getOutputStream().flush();
}
} finally {
this.lock.unlock();
}
}
}
}
1.3 测试
package com.ybw.logback.demo.custom;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
/**
* @className CustomLog
* @author ybw
* @date 2022/9/15
* @version V1.0
**/
@Slf4j
public class CustomLog {
/**
*
* @methodName: print
* @return: void
* @author: ybw
* @date: 2022/9/15
**/
@Test
public void print(){
log.info("aa");
log.error("bb");
}
}
错误日志、报警内容如下:
[ERROR] 2022-09-17 18:07:51.577 [main] c.ybw.logback.demo.custom.CustomLog - bb
2、logback.xml变量使用-spring配置
logback的变量作用于有三种:local,context,system
- local 作用域在配置文件内有效;
- context 作用域的有效范围延伸至 logger context;
- system 作用域的范围最广,整个 JVM 内都有效;
logback 在替换变量时,首先搜索 local 变量,然后搜索 context,然后搜索 system,在spring项目中,应将变量的作用域设置为context,并交给spring控制。
2.1 spring的配置作为变量
application.yml
server:
port: 8080
spring:
application:
name: logback-online-alarm
profiles:
active: dev
application-dev.yml
#飞书
fs:
bot:
webhook:
suf: /aa #测试
logback.xml配置如下,PROFILES-ACTIVE、FS-BOT-WEBHOOK-SUF为spring配置文件中的属性
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--获取spring配置文件的变量-->
<springProperty scope="context" name="PROFILES-ACTIVE" source="spring.profiles.active" defaultValue=""/>
<springProperty scope="context" name="FS-BOT-WEBHOOK-SUF" source="fs.bot.webhook.suf" defaultValue=""/>
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径 -->
<!-- <property name="LOG_HOME" value="d:" /> -->
<!-- ch.qos.logback.core.ConsoleAppender 控制台输出 -->
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<!-- 所有日志输出 -->
<appender name="AllFile"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${LOG_HOME:-c:/}logs/all/all.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME:-c:/}logs/all/all-%d{yyyy-MM-dd}.%i.log
</FileNamePattern>
<MaxHistory>30</MaxHistory>
<TimeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>100MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %logger{36} - %msg%n
</pattern>
</layout>
</appender>
<!-- 自定义文件输出-错误日志 -->
<appender name="ErrorFile" class="com.ybw.logback.demo.config.LogFileAppender">
<File>${LOG_HOME:-c:/}logs/error/error.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME:-c:/}logs/error/error-%d{yyyy-MM-dd}.%i.log
</FileNamePattern>
<MaxHistory>30</MaxHistory>
<TimeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>100MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印错误日志 -->
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder charset="UTF-8">
<pattern>[${PROFILES-ACTIVE}] [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %logger{36} - %msg%n</pattern>
</encoder>
<fsSuf>${FS-BOT-WEBHOOK-SUF}</fsSuf>
</appender>
<root level="info">
<appender-ref ref="stdout"/>
<appender-ref ref="ErrorFile"/>
<appender-ref ref="AllFile"/>
</root>
</configuration>
2.2 自定义appender代码
package com.ybw.logback.demo.config;
import ch.qos.logback.core.encoder.Encoder;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.spi.DeferredProcessingAware;
import ch.qos.logback.core.status.ErrorStatus;
import com.ybw.logback.demo.constant.fs.FSConstant;
import com.ybw.logback.demo.utils.FsUtils;
import lombok.Data;
import java.io.IOException;
/**
* 自定义的appender
* 1.可以对接受到的event中的日志信息做任何操作处理
* 2.可以在同步写日志文件的时候,存入mysql或者es
*
* @author ybw
* @version V1.0
* @className LogFileAppender
* @date 2022/9/16
**/
@Data
public class LogFileAppender<E> extends RollingFileAppender<E> {
private String fsSuf;
@Override
public void setEncoder(Encoder encoder) {
//自定义的appender的父类OutputStreamAppender在启动的时候会判断是否有encoder ,无的话自定义appender启动会失败
super.setEncoder(encoder);
}
/**
* 覆盖父类OutputStreamAppender的日志记录功能,再这里面做日志切操作功能
*
* @param event
*/
@Override
protected void subAppend(E event) {
if (this.isStarted()) {
System.out.println("fsSuf:"+fsSuf);
try {
if (event instanceof DeferredProcessingAware) {
((DeferredProcessingAware) event).prepareForDeferredProcessing();
}
//根据标签规则拿到日志字符串,这里可以再次修改日志信息
byte[] byteArray = super.encoder.encode(event);
//做一些日志的特殊处理
sendFs(byteArray);
// writeMongo(...);
// writeRedis(...);
// writeMq(...);
//写入日志文件
writeBytes(byteArray);
} catch (IOException var3) {
this.started = false;
this.addStatus(new ErrorStatus("IO failure in appender", this, var3));
}
}
}
/**
* 飞书报警
*
* @param byteArray
* @methodName: sendFs
* @return: void
* @author: ybw
* @date: 2022/9/15
**/
private void sendFs(byte[] byteArray) {
if (byteArray != null && byteArray.length != 0) {
this.lock.lock();
try {
FsUtils.sendTextMessage(FSConstant.TextContentEnum.ERROR_LOG, new String(byteArray));
} finally {
this.lock.unlock();
}
}
}
private void writeBytes(byte[] byteArray) throws IOException {
if (byteArray != null && byteArray.length != 0) {
this.lock.lock();
try {
this.getOutputStream().write(byteArray);
if (this.isImmediateFlush()) {
this.getOutputStream().flush();
}
} finally {
this.lock.unlock();
}
}
}
}
fsSuf为logback.xml配置的属性。
2.3 测试
package com.ybw.logback.demo.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author ybw
* @version V1.0
* @className LogController
* @date 2022/9/16
**/
@RestController
@Slf4j
public class LogController {
/**
*
* @methodName: getLog
* @return: java.lang.String
* @author: ybw
* @date: 2022/9/16
**/
@GetMapping("/getLog")
public String getLog() {
log.info("aa");
log.error("bb");
return "OK";
}
}
访问接口:http://localhost:8080/getLog
错误日志、报警内容如下:
[dev] [ERROR] 2022-09-17 18:30:31.513 [http-nio-8080-exec-5] c.y.l.demo.controller.LogController - bb
[dev]为spring.profiles.active。
3、logback.xml变量使用-配置中心
以nacos为例
3.1 配置文件
bootstrap.yml配置
server:
port: 8080
spring:
application:
name: logback-nacos
profiles:
active: dev
logging:
config: classpath:logback.xml #日志配置要放在nacos配置之后
bootstrap-dev.yml配置
spring:
cloud:
nacos:
config:
server-addr: localhost:8848
username: nacos
password: nacos
namespace: nacos-config #命名空间
# group: DEFAULT_GROUP #默认DEFAULT_GROUP
file-extension: yml #配置中心的格式,默认为properties
配置中心
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--获取spring配置文件的变量-->
<springProperty scope="context" name="PROFILES-ACTIVE" source="spring.profiles.active" defaultValue=""/>
<springProperty scope="context" name="FS-BOT-WEBHOOK-SUF" source="fs.bot.webhook.suf" defaultValue=""/>
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径 -->
<!-- <property name="LOG_HOME" value="d:" /> -->
<!-- ch.qos.logback.core.ConsoleAppender 控制台输出 -->
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<!-- 所有日志输出 -->
<appender name="AllFile"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${LOG_HOME:-c:/}logs/all/all.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME:-c:/}logs/all/all-%d{yyyy-MM-dd}.%i.log
</FileNamePattern>
<MaxHistory>30</MaxHistory>
<TimeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>100MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %logger{36} - %msg%n
</pattern>
</layout>
</appender>
<!-- 自定义文件输出-错误日志 -->
<appender name="ErrorFile" class="com.ybw.logback.demo.config.LogFileAppender">
<File>${LOG_HOME:-c:/}logs/error/error.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME:-c:/}logs/error/error-%d{yyyy-MM-dd}.%i.log
</FileNamePattern>
<MaxHistory>30</MaxHistory>
<TimeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>100MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印错误日志 -->
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder charset="UTF-8">
<pattern>[${PROFILES-ACTIVE}] [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %logger{36} - %msg%n</pattern>
</encoder>
<fsSuf>${FS-BOT-WEBHOOK-SUF}</fsSuf>
</appender>
<root level="info">
<appender-ref ref="stdout"/>
<appender-ref ref="ErrorFile"/>
<appender-ref ref="AllFile"/>
</root>
</configuration>
3.2 自定义appender代码
与2.2一致。
3.3 测试
与2.3一致。
fsSuf即配置中心的属性,会打印在控制台。
fsSuf:/aa
版权声明:本文为xixingzhe2原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。