- <?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>
- 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();
- }
- }
- }
- }
- 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
logback的变量作用于有三种:local,context,system
logback 在替换变量时,首先搜索 local 变量,然后搜索 context,然后搜索 system,在spring项目中,应将变量的作用域设置为context,并交给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>
- 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配置的属性。
- 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。
以nacos为例
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>
与2.2一致。
与2.3一致。
fsSuf即配置中心的属性,会打印在控制台。
fsSuf:/aa