Самая полная быстрая практика Logback

Java
Самая полная быстрая практика Logback

Введение

logbackЭто самый популярный на данный момент инструмент для записи логов, обладающий высокой производительностью, полным функционалом и полной документацией.log4jРазработчик серии,

Эта статья изlogbackВводятся часто используемые компоненты и функциональные точки, а также приводится простой справочный пример.logbackОфициальный сайт


javaкак пользоватьсяlogback

существуетpom.xmlВнедрить два ключевых пакета в

 <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-core -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.2.3</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
            <scope>test</scope>
        </dependency>

Затем создайте logback.xml в каталоге ресурсов, см.Полный набор доступных профилейэта глава


уровень журнала

Рекомендуются следующие, ранжированные от высокого к низкому

Level описывать
ERROR События ошибок могут по-прежнему позволять приложению продолжать работу.
WARN Обозначьте потенциально опасные ситуации
INFO Указывает сообщение, которое может выделять информацию о работе приложения на грубом уровне.
DEBUG Указание детальных информационных событий наиболее полезно для отладки приложений.
***
## Уровень добавления

What is an Appender?

Appender class dependency

appender

ConsoleAppender(вывод журнала в консоль)

вывести информацию журнала на консоль

настроить тип описывать
encoder Encoder формат вывода журнала
target String Место назначения вывода журнала, которое может быть System.out или System.err, по умолчанию — System.out.
withJansi boolean Значение по умолчанию - false, которое нельзя использовать.Похоже, что вывод ANSI будет иметь цвет после его включения.Подробности см. во введении на официальном сайте.

sample:

<configuration>
  <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>

  <root level="DEBUG">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

FileAppender(вывод журнала в файл)

FileAppender OutputStreamAppenderПодкласс , который выводит журнал в указанный файл. Если файл уже существует, добавьте или заново создайте файл в конце в соответствии со свойством конфигурации.

настроить тип описывать
append boolean По умолчанию true, журнал будет добавлен в конец существующего файла.
encoder Encoder формат вывода журнала
file String Имя файла, может иметь путь, если файл или каталог не существует, он будет создан, например:logs/info.log, это свойство не имеет значения по умолчанию
immediateFlush boolean Как только журнал сгенерирован, он будет немедленно сброшен в файл, и для повышения производительности для него следует установить значение false, поскольку буфер будет сбрасываться часто;

sample:

<configuration>
  <!-- 使用时间戳作为文件名 -->
  <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>testFile-${bySecond}.log</file>
    <append>true</append>
    <!-- set immediateFlush to false for much higher logging throughput -->
    <immediateFlush>true</immediateFlush>
    <!-- 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>

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

RollingFileAppender(прокатный выход)

RollingFileAppenderУнаследованный от FileAppender, он генерирует скользящие файлы в соответствии с некоторыми специфическими политиками. Например, когда он работает в паре с политикой TimeBasedRollingPolicy, когда файл достигает указанного времени, новый файл будет создан заново. Политика будет подробно описана в следующие главы.

настроить тип описывать
append boolean См. конфигурацию FileAppender
encoder Encoder См. конфигурацию FileAppender
file String См. конфигурацию FileAppender
rollingPolicy RollingPolicy Политика обновления журнала: при настройке этого параметра файл журнала будет обновляться в соответствии с указанной политикой.
triggeringPolicy TriggeringPolicy Политика прокрутки триггера: обычно используется с RollingPolicy для установки условий запуска прокрутки.

sample:

<appender name="errorAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>logs/error.log</file>
    <!-- 设置滚动策略 TimeBasedRollingPolicy 按日期滚动 -->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!--设置日志命名模式-->
        <fileNamePattern>errorFile.%d{yyyy-MM-dd}.log</fileNamePattern>
        <!--最多保留30天log-->
        <maxHistory>30</maxHistory>
    </rollingPolicy>
    <!-- 超过150MB时,立即触发滚动策略,生成新的文件 -->
    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
        <maxFileSize>150</maxFileSize>
    </triggeringPolicy>
    <encoder>
        <pattern>%d [%p] %-5level %logger - %msg%newline</pattern>
    </encoder>
</appender>

Политика файла журнала *Политика (обычно используется)

TimeBasedRollingPolicy(скользящая стратегия по дате)

TimeBasedRollingPolicyЭто может быть самая популярная стратегия логбэка. Прокрутка на основе времени может составлять один день или один месяц. Это чаще используется. Обычно мы можем установить день для создания нового файла, который легко суммировать и подсчитывать.

настроить тип описывать
fileNamePattern String Правила именования файлов журнала обычно используют %d для вывода по дням или месяцам, например, errorFile.%d{гггг-ММ-дд}.log, сгенерированный файл похож на errorFile.2018-10-09.log, с дата, файлы, создаваемые каждый день, не будут иметь повторяющихся имен. Это также поддерживает выбор часового пояса, например %d{yyyy-MM-dd,UTC}
maxHistory int Количество дней для хранения журнала. Исторические файлы журнала, которые превышают это количество дней, будут удалены асинхронно путем возврата журнала.
totalSizeCap int Общий размер заархивированных файлов и политика maxHistory применяются в первую очередь.
cleanHistoryOnStart boolean Значение по умолчанию — false, что запускает действие по немедленному удалению файла архива.

Прокрутка вывода поддерживает автоматическое сжатиеИмя файла начинается с.gzили.zipконец, например:/wombat/foo.%d.gz

sample:

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>logFile.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <!-- daily rollover -->
      <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>

      <!-- keep 30 days' worth of history capped at 3GB total size -->
      <maxHistory>30</maxHistory>
      <totalSizeCap>3GB</totalSizeCap>

    </rollingPolicy>

    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

SizeAndTimeBasedRollingPolicy(Скользящая стратегия по размеру и времени)

Это должно быть наиболее часто используемым, прокручивая журнал в соответствии с политикой указания времени и размера файла. Без дальнейших церемоний, посмотрите на следующий пример

<configuration>
  <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>mylog.txt</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
      <!-- rollover daily -->
      <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
       <!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
       <maxFileSize>100MB</maxFileSize>    
       <maxHistory>60</maxHistory>
       <totalSizeCap>20GB</totalSizeCap>
    </rollingPolicy>
    <encoder>
      <pattern>%msg%n</pattern>
    </encoder>
  </appender>


  <root level="DEBUG">
    <appender-ref ref="ROLLING" />
  </root>

</configuration>

Обратите внимание, что кроме“%d”за пределами“%i”Тег конверсии.%iи%dТокены обязательны. Всякий раз, когда текущий файл журнала достигает maxFileSize до конца текущего периода, он будет архивироваться с возрастающим индексом, начиная с 0.


FixedWindowRollingPolicy(Создание скользящих файлов с фиксированной стратегией алгоритма обычно не используется)

Эта стратегия обычно не используется, поэтому давайте не будем использовать больше bbs. Атрибуты такие же, как и у других стратегий прокрутки. Обычно соглашение об именах файлов выглядит следующим образом:tests.%i.log, файл будет сгенерирован, когда будет достигнуто условие для запуска прокруткиtest1.log,test2.log,test3.log ...


SizeBasedTriggeringPolicy(стратегия, запускающая прокрутку в зависимости от размера)

Конфигурация в этом теге используется для запуска времени прокрутки, например, когда размер файла достигает указанного значения, запускается прокрутка.

sample:

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>test.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
      <fileNamePattern>test.%i.log.zip</fileNamePattern>
      <minIndex>1</minIndex>
      <maxIndex>3</maxIndex>
    </rollingPolicy>

    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
      <maxFileSize>5MB</maxFileSize>
    </triggeringPolicy>
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

fileNamePattenнекоторые правила для (например, прокатка по годам, месяцам, дням, дням, часам, минутам, секундам)

пример описывать
/wombat/foo.%d Ролл по дням, формат год-месяц-день, все создается в одной папке
/wombat/%d{yyyy/MM}/foo.txt Прокручивайте по месяцам, создавайте одинаковый файл каждый месяц в другой папке месяца, например, сначала: /wombat/2018/09/foo.txt, затем: /wombat/2018/10/foo.txt
/wombat/foo.%d{yyyy-ww}.log Генерировать раз в неделю, регенерируя с первого дня недели
/wombat/foo%d{yyyy-MM-dd_HH}.log Генерируется каждый час
/wombat/foo%d{yyyy-MM-dd_HH-mm}.log Генерируется каждую минуту
/wombat/foo%d{yyyy-MM-dd_HH-mm, UTC}.log Генерируется каждую минуту в указанном часовом поясе
/foo/%d{yyyy-MM,aux}/%d.log Генерируется один раз в день с разбивкой по годам и месяцам, например, в /foo/2018-09/ есть журнал за месяц, а имя журнала — это дата каждого дня

patternКонфигурация (форматирование вывода журнала)

пример

Некоторые общие правила конфигурации описаны ниже.

<encoder>
    <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
  • %-4relative: время выходной записи журнала выравнивается по левому краю, а ширина равна 4.
  • %thread: номер потока, в котором будет выводиться журнал.
  • %-5level: Вывод 5 уровней журнала, выровненных по левому краю.
  • %logger{35}: записи журнала выводаloggerИмя обычно является именем класса и имеет длину 35.
  • %msg%n: Печать информации, предоставленной приложением, с переносом строки.

Уведомление: при использовании должны быть включены все ключевые слова.%, как указано выше,-Как его логотип

patternлист

ключевые слова описывать
c{length}
lo{length}
Категория, к которой принадлежит выходной логгер, обычно полное имя класса, к которому он принадлежит.Параметром является зарезервированная длина имени логгера, а полное имя по умолчанию не заполняется.
%logger com.util.StringUtils com.util.StringUtils
%logger{0} com.util.StringUtils StringUtils
%logger{10} com.util.StringUtils c.u.StringUtils
C{length}
class{length}
Аналогично приведенному выше использованию, выводится полное имя вызывающего абонента, что имеет низкую производительность и не рекомендуется настраивать.
contextName
cn|
имя выходного контекста
d{pattern}
date{pattern}
Время печати выходного журнала, похожее на формат даты в java.
%d 2019-02-12 18:00:00,000
%date 2019-02-12 18:00:00,000
%date{ISO8601} 2019-02-12 18:00:00,000
%date{HH:mm:ss,SSSS} 18:00:00,000
%date{yyyy-MM-dd HH:mm:ss,SSSS} 2019-02-12 18:00:00,000
caller{depth} Вывод информации о глубине стека вызовов вызывающего абонента, чем больше значение, тем больше информации о стеке выводится.
%caller{2} [main]-[INFO]: log test
Caller+0 at com.util.StringUtil.subString(StringUtil.java :22)
Caller+1 at com.util.Main.exec(Main.java :17)
L
line
Выведите, где произошло событие журнала, включая название категории, поток, в котором оно произошло, и количество строк в коде. Если вопросы производительности не рассматриваются, вы можете использовать
m
msg
message
Информация, предоставленная приложением
M
method
Производительность имени метода для вывода журнала выполнения низкая. Если проблемы с производительностью не учитываются, вы можете использовать
n Вывод возврата каретки и перевода строки, "/r/n" для платформ Windows и "/n" для платформ Unix.
p
le
level
Уровень выходного журнала, т. е. DEBUG, INFO, WARN, ERROR, FATAL
t
thread
Имя потока для вывода журнала печати
replace(msg){r,t} msg — это содержимое журнала, а r — регулярное выражение.Замените содержимое r в msg на t.
Например: %replace(%msg){'\s',""}
r
relative
Количество миллисекунд, которое потребовалось для вывода информации журнала с момента запуска приложения.

Конфигурация:

<configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 日期 [线程] [class类]-[日志级别] log内容 回车符号 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n</pattern>
        </encoder>

    </appender>

    <!-- 输出INFO及以上的日志 -->
    <root level="INFO">
        <!-- 让自定义的appender生效 -->
        <appender-ref ref="STDOUT"/>
    </root>

</configuration>

Вывод консоли:

2018-10-09 14:27:55 [main] [org.springframework.web.servlet.handler.SimpleUrlHandlerMapping]-[INFO] Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-10-09 14:27:55 [main] [org.springframework.jmx.export.annotation.AnnotationMBeanExporter]-[INFO] Registering beans for JMX exposure on startup
2018-10-09 14:27:55 [main] [org.apache.coyote.http11.Http11NioProtocol]-[INFO] Starting ProtocolHandler ["http-nio-6677"]
2018-10-09 14:27:55 [main] [org.apache.tomcat.util.net.NioSelectorPool]-[INFO] Using a shared selector for servlet write/read
2018-10-09 14:27:55 [main] [org.springframework.boot.web.embedded.tomcat.TomcatWebServer]-[INFO] Tomcat started on port(s): 6677 (http) with context path ''
2018-10-09 14:27:55 [main] [com.xj.plugins.Springboot2AnalyzeApplication]-[INFO] Started Springboot2AnalyzeApplication in 2.014 seconds (JVM running for 3.949)


Цвет конфигурации журнала вывода консоли

Формат описывать
%black чернить
%red красный
%green зеленый
%yellow желтый
%blue синий
%magenta пурпурный
%cyan синий
%white белый
%gray серый
%highlight Цвет выделения
%bold Более яркие цвета, усиливающие все вышеперечисленные цвета, такие как %boldRed, %boldBlack

пример:

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 日期 [线程] [class类]-[日志级别] log内容 回车符号 -->
            <pattern>%blue(%d{yyyy-MM-dd HH:mm:ss,SSS}) [%cyan(%t)] [%yellow(%c)]-[%highlight(%p)] %m%n</pattern>         
        </encoder>
    </appender>

    <!-- 输出INFO及以上的日志 -->
    <root level="INFO">
        <!-- 让自定义的appender生效 -->
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>

Вывод в консоль после настройки

增加色彩输出


лог-направленный вывод

В logback.xml, как вывести определенный журнал в файл, можно использовать фильтр, аналогичный следующему примеру.

фильтр конфигурации xml, например вывод журнала ошибок в error.log

    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
           <encoder>
               <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] [%c]-[%p] %m%n</pattern>
           </encoder>

           <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
               <!-- rollover daily -->
               <fileNamePattern>${LOG_HOME}/error-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
               <!-- 文件最大30MB,保留60天,总大小20GB -->
               <maxFileSize>30MB</maxFileSize>
               <maxHistory>60</maxHistory>
               <totalSizeCap>20GB</totalSizeCap>
           </rollingPolicy>

           <!-- 过滤器,只写入error级别log -->
           <filter class="ch.qos.logback.classic.filter.LevelFilter">
               <level>ERROR</level>
               <onMatch>ACCEPT</onMatch>
               <onMismatch>DENY</onMismatch>
           </filter>

       </appender>

Метод Filter можно переписать, если есть необходимость в специальных логах, требующих направленного вывода

public class MyLogFilter extends Filter<ILoggingEvent> {
       @Override

       public FilterReply decide(ILoggingEvent event) {
           
           if(event.getMessage() != null
                   && (event.getMessage().startsWith("test")
                   || event.getMessage().startsWith("demo"))) {
               return FilterReply.ACCEPT;
           } else {
               return FilterReply.DENY;
           }
       }
   }

Затем добавьте фильтр в приложение

<!-- 过滤器,写入test和demo开头的日志 -->
<filter class="xx.xxx.xxxx.MyLogFilter" />

Отключить вывод журнала на уровне класса

Добавьте следующую конфигурацию в logback.xml.

OFF означает, что все закрыто, вы можете настроить указанный уровень, например INFO, DEBUG...

<logger name="xx.xx.class" level="OFF" />

logback.xmlчитать переменные окружения

logback.xmlПоддержка двух методов чтения: чтение из системной среды, чтение из файла конфигурации spring.

Чтение переменных системной среды и получение их с помощью ${envName}

<!-- 从系统环境变量读取日志输出目录 -->
<property name="LOG_HOME" value="${log.dir}"/>

Как читать файлы конфигурации Spring

<!-- 从context中读取所以不需要使用${}获取 -->
<springProperty scope="context" name="LOG_HOME" source="logback.dir"/>

Настройки значения по умолчанию

Если вы не получите его в переменной окруженияLOG_HOMEзначение, сделаетlogsпо умолчанию иShellСинтаксис установки значений по умолчанию аналогичен

<file>${LOG_HOME:-logs}/test/test-info.log</file>

-

Полный набор доступных профилей

Следующая конфигурация будет генерировать три файла журнала. Конкретная стратегия такова: новый файл будет создаваться каждый день. Когда файл журнала достигает указанного размера в день, он будет автоматически сжат, и будет создан новый файл для записи.

  • main.log(только записьinfoвыход журнала уровня и выше)
  • warn.log(только записьwarnуровень вывода журнала)
  • error.log(только записьerrorуровень вывода журнала)
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    <!-- 从spring中获取配置,如获取不到会使用默认值 -->
    <springProperty scope="context" name="LOG_HOME" source="logging.path"/>
    <springProperty scope="context" name="LOG_LEVEL" source="logging.output.level"/>
    <springProperty scope="context" name="LOG_MAX_SIZE" source="logging.file.max-size"/>
    <springProperty scope="context" name="LOG_TOTAL_SIZE_CAP" source="logging.file.total-size-cap"/>
    <springProperty scope="context" name="LOG_MAX_HISTORY" source="logging.file.max-history"/>
    <!-- 输出样式 -->
    <property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] [%logger{10}]-[%p] %m%n"/>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%blue(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%cyan(%t)] [%yellow(%logger{10})]-[%highlight(%p)] %m%n</pattern>
        </encoder>
    </appender>

    <appender name="Main-Log" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME:-logs}/logback/main.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <FileNamePattern>${LOG_HOME:-logs}/logback/main-%d{yyyy-MM-dd}_%i.log.zip</FileNamePattern>
            <MaxHistory>${LOG_MAX_HISTORY:-30}</MaxHistory>
            <MaxFileSize>${LOG_MAX_SIZE:-10MB}</MaxFileSize>
            <totalSizeCap>${LOG_TOTAL_SIZE_CAP:-10GB}</totalSizeCap>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>


    <appender name="Error-Log" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME:-logs}/logback/error.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <FileNamePattern>${LOG_HOME:-logs}/logback/error-%d{yyyy-MM-dd}_%i.log.zip</FileNamePattern>
            <MaxHistory>${LOG_MAX_HISTORY:-30}</MaxHistory>
            <MaxFileSize>${LOG_MAX_SIZE:-10MB}</MaxFileSize>
            <totalSizeCap>${LOG_TOTAL_SIZE_CAP:-10GB}</totalSizeCap>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>

        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="Warn-Log" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME:-logs}/logback/warn.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <FileNamePattern>${LOG_HOME:-logs}/logback/warn-%d{yyyy-MM-dd}_%i.log.zip</FileNamePattern>
            <MaxHistory>${LOG_MAX_HISTORY:-30}</MaxHistory>
            <MaxFileSize>${LOG_MAX_SIZE:-10MB}</MaxFileSize>
            <totalSizeCap>${LOG_TOTAL_SIZE_CAP:-10GB}</totalSizeCap>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
        <!-- log filter -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    
    <!-- 关闭类中某个级别的输出 OFF全部关闭 , INFO,DEBUG ...
    <logger name="x.x.Constants">
        <level value="OFF"/>
    </logger> 
    -->

    <!-- log output level -->
    <root level="${LOG_LEVEL:-INFO}">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="Main-Log"/>
        <appender-ref ref="Warn-Log"/>
        <appender-ref ref="Error-Log"/>
    </root>

</configuration>