按照内容分割日志

前言

前一段时间接到一个需求,在特定场景下进行告警。需要将告警内容写入到日志文件中,运维人员会收集这类日志进行告警。这就需要将告警信息写入到单独的日志文件中,即通过内容将日志分割。

这里不介绍logback与log4j2的比较与选择,直奔主题——logback和log4j2是如何通过关键字将日志分割的。

logback

maven依赖

<!-- logback依赖 -->
···
<logback.version>1.2.3</logback.version>
<janino.version>3.1.0</janino.version>
···
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>${logback.version}</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>${logback.version}</version>
</dependency>
<!--  janino 需要通过此包进行关键字匹配-->
<dependency>
    <groupId>org.codehaus.janino</groupId>
    <artifactId>commons-compiler</artifactId>
    <version>${janino.version}</version>
</dependency>
<dependency>
    <groupId>org.codehaus.janino</groupId>
    <artifactId>janino</artifactId>
    <version>${janino.version}</version>
</dependency>

配置文件

logback.xml
如注释所示,配置一个告警日志alertAppender,包含指定关键字的日志内容会写入到所指定的日志文件中。

  1. alertAppender
  • RollingFileAppender
  • 按照日期分割日志
  • SizeAndTimeBasedRollingPolicy
  • 通过maxFileSize,maxHistory,totalSizeCap等参数制定分割规则
    +** EvaluatorFilter**
  • 通过配置expression进行包含关键字内容的过滤
<?xml version="1.0" encoding="utf-8" ?>
<configuration debug="true">

	<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %X{traceId} %-5level %logger{36} %L - %msg%n</pattern>
        </encoder>
    </appender>

	<!-- 主要配置!!! -->
    <!-- 配置报警日志 -->
    <appender name="alertAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 接收WARN级别日志,不是WARN级别的会拒绝,WARN级别的进行下一个filter判断 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>NEUTRAL</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <!-- 通过EvaluatorFilter结合janino包下的JaninoEventEvaluator 实现指定关键词过滤 -->
        <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
            <!-- 日志中必须包含ALERT,包含的接受,不包含的拒绝 -->
            <evaluator> <!-- defaults to type ch.qos.logback.classic.boolex.JaninoEventEvaluator -->
                <expression>return message.contains("ALERT");</expression>
            </evaluator>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>

		<!-- 日志输出到指定日志中,500MB时分割日志,最多30个,最大50GB -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- rollover daily -->
            <fileNamePattern>logs/logback/alert-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxFileSize>500MB</maxFileSize>    
            <maxHistory>30</maxHistory>
            <totalSizeCap>50GB</totalSizeCap>
        </rollingPolicy>

        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS}--%msg%n</pattern>
        </encoder>
    </appender>

    <appender name="warnAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
	      <!-- rollover daily -->
	      <fileNamePattern>logs/logback/warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
	       
	       <maxFileSize>500MB</maxFileSize>    
	       <maxHistory>30</maxHistory>
	       <totalSizeCap>50GB</totalSizeCap>
	    </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %thread %X{traceId} %X{invokeNo} %logger{40} %msg%n</pattern>
        </encoder>
    </appender>
    
    <appender name="infoAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
	      <!-- rollover daily -->
	      <fileNamePattern>logs/logback/info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
	       <maxFileSize>500MB</maxFileSize>    
	       <maxHistory>30</maxHistory>
	       <totalSizeCap>50GB</totalSizeCap>
	    </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %thread %X{traceId} %X{invokeNo} %logger{40} %msg%n</pattern>
        </encoder>
    </appender>
    
    <logger name="alertAppender" level="WARN" addtivity="false">
        <appender-ref ref="alertAppender"/>
    </logger>
    <logger name="warnAppender" level="WARN" addtivity="false">
        <appender-ref ref="warnAppender"/>
    </logger>
    <logger name="infoAppender" level="INFO" addtivity="false">
        <appender-ref ref="infoAppender"/>
    </logger>
    
    <root level="info">
        <appender-ref ref="alertAppender"/>
        <appender-ref ref="warnAppender"/>
        <appender-ref ref="infoAppender"/>
        <appender-ref ref="consoleAppender"/>
    </root>
</configuration>

Demo

demo与测试结果如下:

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@Slf4j
@SpringBootTest(classes = LogExampleApplication.class)
public class LogTest {

    @Test
    public void logTest() {
        System.out.println("=========================");
        log.info(RandomStringUtils.randomAlphabetic(6));
        log.info("alert info");
        log.warn("alert warn");
        log.warn("ALERT warn");
    }
}

java错误日志过滤关键字 查看日志过滤关键字_分割


java错误日志过滤关键字 查看日志过滤关键字_log4j2_02


根据输出结果可以看到,只有包含关键字“ALERT”的内容输出到了alert.log中,其他内容被过滤了。

log4j2

maven依赖

由于使用的是springboot,需要默认使用logback,需要将spring-boot-starter-logging依赖排除

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

配置文件

log4j2.xml
告警日志配置

  1. 按照每日分割日志:
  • 配置RollingFile ,如果同时配置File和RollingFile ,二者的fileName不能相同,否则RollingFile 配置可能会失效。
  • 配置TimeBasedTriggeringPolicy ,每日触发分割
  1. 按照大小分割日志
  • 配置SizeBasedTriggeringPolicy ,当日志达到指定大小时,进行分割,分割出来的日志名参照filePattern配置
  1. 按照关键字过滤日志
  • 配置RegexFilter,通过正则匹配符合的内容。
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug" monitorInterval="60">
    <Properties>
        <Property name="default_log_pattern">
            [%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5p] [%t] (%c{1}:%L) [TxId:%X{PtxId} SpanId:%X{PspanId}] %m%n
        </Property>
    </Properties>

    <Appenders>
        <Console name="STDOUT" target="SYSTEM_OUT">
            <PatternLayout pattern="${default_log_pattern}"/>
        </Console>

        <RollingFile name="alertRollingFile"
                     filePattern="logs/log4j/alert-%d{yyyy-MM-dd}.%i.log"
                     fileName="logs/log4j/alert.log">
            <!-- 正则匹配,符合条件的写入日志 -->
            <RegexFilter regex=".*ALERT.*" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout>
                <Pattern>%d{yyyy-MM-dd HH:mm:ss}--%msg%n</Pattern>
            </PatternLayout>
            <Policies>
                <!-- 每次启动执行 -->
<!--                <OnStartupTriggeringPolicy />-->
                <!-- 达到250MB进行分割 -->
                <SizeBasedTriggeringPolicy size="250 MB"/>
                <TimeBasedTriggeringPolicy />
            </Policies>
            <!-- 最多20个 -->
            <DefaultRolloverStrategy max="20"/>
        </RollingFile>

    </Appenders>

    <Loggers>
        <Root level="info">
            <AppenderRef ref="STDOUT" level="info"/>
            <AppenderRef ref="alertRollingFile" level="warn"/>
        </Root>
    </Loggers>
</Configuration>

Demo

同上

由于只有alertRollingFile配置了写入日志文件,且根据规则过滤,所以只有带关键字“ALERT”的日志内容写到日志文件中。

java错误日志过滤关键字 查看日志过滤关键字_关键字_03