Как я могу настроить Logback для регистрации различных уровней для регистратора в разных местах назначения?
как я могу настроить Logback для регистрации различных уровней для регистратора в разные пункты назначения?
например, учитывая следующую конфигурацию Logback, будет Logback record INFO сообщения STDOUT и ERROR сообщения STDERR?
(обратите внимание, что этот пример является вариантом примера logback-examples/src/main/java/chapters/configuration/sample4.xml показано в Глава 3: Конфигурация Logback).
<configuration>
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>
%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<appender name="STDERR"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>
%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
<target>System.err</target>
</appender>
<!-- What is the effective level of "chapters.configuration"? -->
<logger name="chapters.configuration" level="INFO" additivity="false">
<appender-ref ref="STDOUT" />
</logger>
<logger name="chapters.configuration" level="ERROR" additivity="false">
<appender-ref ref="STDERR" />
</logger>
<!-- turn OFF all logging (children can override) -->
<root level="OFF">
<appender-ref ref="STDOUT" />
</root>
</configuration>
12 ответов:
обновление: для всех конфигураций на основе подхода с использованием Groovy см. ответ Дина Хиллера.
--
вы можете сделать некоторые интересные вещи с Logback filters. Приведенная ниже конфигурация будет печатать только предупреждения и сообщения об ошибках в stderr, а все остальное стандартный вывод.
logback.xml
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender"> <target>System.out</target> <filter class="com.foo.StdOutFilter" /> ... </appender> <appender name="stderr" class="ch.qos.logback.core.ConsoleAppender"> <target>System.err</target> <filter class="com.foo.ErrOutFilter" /> ... </appender> <logger name="mylogger" level="debug"> <appender-ref ref="stdout" /> <appender-ref ref="stderr" /> </logger>com.foo.StdOutFilter
public class StdOutFilter extends ch.qos.logback.core.filter.AbstractMatcherFilter { @Override public FilterReply decide(Object event) { if (!isStarted()) { return FilterReply.NEUTRAL; } LoggingEvent loggingEvent = (LoggingEvent) event; List<Level> eventsToKeep = Arrays.asList(Level.TRACE, Level.DEBUG, Level.INFO); if (eventsToKeep.contains(loggingEvent.getLevel())) { return FilterReply.NEUTRAL; } else { return FilterReply.DENY; } } }com.foo.ErrOutFilter
public class ErrOutFilter extends ch.qos.logback.core.filter.AbstractMatcherFilter { @Override public FilterReply decide(Object event) { if (!isStarted()) { return FilterReply.NEUTRAL; } LoggingEvent loggingEvent = (LoggingEvent) event; List<Level> eventsToKeep = Arrays.asList(Level.WARN, Level.ERROR); if (eventsToKeep.contains(loggingEvent.getLevel())) { return FilterReply.NEUTRAL; } else { return FilterReply.DENY; } } }
Я считаю, что это было бы самое простое решение:
<configuration> <contextName>selenium-plugin</contextName> <!-- Logging configuration --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <Target>System.out</Target> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>INFO</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> <encoder> <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%level] %msg%n</pattern> </encoder> </appender> <appender name="STDERR" class="ch.qos.logback.core.ConsoleAppender"> <Target>System.err</Target> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> <encoder> <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%level] [%thread] %logger{10} [%file:%line] %msg%n</pattern> </encoder> </appender> <root level="INFO"> <appender-ref ref="STDOUT"/> <appender-ref ref="STDERR" /> </root> </configuration>
хорошо, вот мой любимый xml-способ сделать это. Я делаю это для версии Eclipse, так что я могу
- нажмите на вещи, чтобы взять меня в журнал заявлений и
- смотрите информацию и ниже черным цветом и предупреждайте / суровый красным
и по какой-то причине так не показывает это все правильно, но большинство, кажется, там...
<configuration scan="true" scanPeriod="30 seconds"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <filter class="ch.qos.logback.core.filter.EvaluatorFilter"> <evaluator class="ch.qos.logback.classic.boolex.GEventEvaluator"> <expression> e.level.toInt() <= INFO.toInt() </expression> </evaluator> <OnMismatch>DENY</OnMismatch> <OnMatch>NEUTRAL</OnMatch> </filter> <encoder> <pattern>%date{ISO8601} %X{sessionid}-%X{user} %caller{1} %-4level: %message%n</pattern> </encoder> </appender> <appender name="STDERR" class="ch.qos.logback.core.ConsoleAppender"> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>warn</level> </filter> <encoder> <pattern>%date{ISO8601} %X{sessionid}-%X{user} %caller{1} %-4level: %message%n</pattern> </encoder> <target>System.err</target> </appender> <root> <level value="INFO" /> <appender-ref ref="STDOUT"/> <appender-ref ref="STDERR"/> </root> </configuration>
решение, основанное только на конфигурации, с Thresholdfilter и LevelFilters, чтобы держать вещи действительно простыми для понимания:
<configuration> <appender name="STDERR" class="ch.qos.logback.core.ConsoleAppender"> <target>System.err</target> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>WARN</level> </filter> <encoder> <pattern>%date %level [%thread] %logger %msg%n</pattern> </encoder> </appender> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <target>System.out</target> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>DEBUG</level> <onMatch>ACCEPT</onMatch> </filter> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>INFO</level> <onMatch>ACCEPT</onMatch> </filter> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>TRACE</level> <onMatch>ACCEPT</onMatch> </filter> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>WARN</level> <onMatch>DENY</onMatch> </filter> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <onMatch>DENY</onMatch> </filter> <encoder> <pattern>%date %level [%thread] %logger %msg%n</pattern> </encoder> </appender> <root level="INFO"> <appender-ref ref="STDOUT" /> <appender-ref ref="STDERR" /> </root> </configuration>
самое простое решение-использовать
ThresholdFilterна аппендеры:<appender name="..." class="..."> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>INFO</level> </filter>полный пример:
<configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>INFO</level> </filter> <encoder> <pattern>%d %-5level: %msg%n</pattern> </encoder> </appender> <appender name="STDERR" class="ch.qos.logback.core.ConsoleAppender"> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>ERROR</level> </filter> <target>System.err</target> <encoder> <pattern>%d %-5level: %msg%n</pattern> </encoder> </appender> <root> <appender-ref ref="STDOUT" /> <appender-ref ref="STDERR" /> </root> </configuration>Update: как указал Майк в комментарии, сообщения с уровнем ошибок печатаются здесь как в STDOUT, так и в STDERR. Не уверен, однако, что было целью операции. Вы можете попробовать ответ Майка, если это не то, что вы хотели.
это конфигурация, которую я использую, которая отлично работает, она основана на XML + JaninoEventEvaluator (требуется Чжэньину библиотека для добавления в Classpath)
<configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%date | [%-5level] in [%file:%line] - %msg %n</pattern> </encoder> <filter class="ch.qos.logback.core.filter.EvaluatorFilter"> <evaluator class="ch.qos.logback.classic.boolex.JaninoEventEvaluator"> <expression> level <= INFO </expression> </evaluator> <OnMismatch>DENY</OnMismatch> <OnMatch>NEUTRAL</OnMatch> </filter> </appender> <appender name="STDERR" class="ch.qos.logback.core.ConsoleAppender"> <target>System.err</target> <encoder> <pattern>%date | [%-5level] in [%file:%line] - %msg %n</pattern> </encoder> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>WARN</level> </filter> </appender> <root level="DEBUG"> <appender-ref ref="STDOUT" /> <appender-ref ref="STDERR" /> </root> </configuration>
Я использую logback.groovy для настройки моего logback, но вы также можете сделать это с помощью XML config:
import static ch.qos.logback.classic.Level.* import static ch.qos.logback.core.spi.FilterReply.DENY import static ch.qos.logback.core.spi.FilterReply.NEUTRAL import ch.qos.logback.classic.boolex.GEventEvaluator import ch.qos.logback.classic.encoder.PatternLayoutEncoder import ch.qos.logback.core.ConsoleAppender import ch.qos.logback.core.filter.EvaluatorFilter def patternExpression = "%date{ISO8601} [%5level] %msg%n" appender("STDERR", ConsoleAppender) { filter(EvaluatorFilter) { evaluator(GEventEvaluator) { expression = 'e.level.toInt() >= WARN.toInt()' } onMatch = NEUTRAL onMismatch = DENY } encoder(PatternLayoutEncoder) { pattern = patternExpression } target = "System.err" } appender("STDOUT", ConsoleAppender) { filter(EvaluatorFilter) { evaluator(GEventEvaluator) { expression = 'e.level.toInt() < WARN.toInt()' } onMismatch = DENY onMatch = NEUTRAL } encoder(PatternLayoutEncoder) { pattern = patternExpression } target = "System.out" } logger("org.hibernate.type", WARN) logger("org.hibernate", WARN) logger("org.springframework", WARN) root(INFO,["STDERR","STDOUT"])Я думаю, что использовать GEventEvaluator проще, потому что нет необходимости создавать классы фильтров.
Прошу прощения за мой английский!
попробуйте это. Вы можете просто использовать встроенный
ThresholdFilterиLevelFilter. Нет необходимости создавать свои собственные фильтры программно. В этом примере предупреждения и уровни ошибок регистрируются в системе.ошибитесь и отдохните до системы.выход:
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender"> <!-- deny ERROR level --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <onMatch>DENY</onMatch> </filter> <!-- deny WARN level --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>WARN</level> <onMatch>DENY</onMatch> </filter> <target>System.out</target> <immediateFlush>true</immediateFlush> <encoder> <charset>utf-8</charset> <pattern>${msg_pattern}</pattern> </encoder> </appender> <appender name="stderr" class="ch.qos.logback.core.ConsoleAppender"> <!-- deny all events with a level below WARN, that is INFO, DEBUG and TRACE --> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>WARN</level> </filter> <target>System.err</target> <immediateFlush>true</immediateFlush> <encoder> <charset>utf-8</charset> <pattern>${msg_pattern}</pattern> </encoder> </appender> <root level="WARN"> <appender-ref ref="stderr"/> </root> <root level="TRACE"> <appender-ref ref="stdout"/> </root>
Я не беру на себя ответственность за этот ответ, поскольку это всего лишь комбинация двух лучших ответов выше: X. Wo Satuk и Себастьена Хелберта:
ThresholdFilterпрекрасно, но вы не можете настроить его, чтобы иметь верхний уровень, а также нижний уровень*, но сочетая его с двумяLevelFiltersустановите значение "запретить"WARNиERRORработает удовольствие.очень важно не забудьте
<target>System.err</target>тег в приложении STDERR: мое упущение этого меня расстроило на несколько протокол.<configuration> <timestamp key="byDay" datePattern="yyyyMMdd'T'HHmmss" /> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>INFO</level> </filter> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>WARN</level> <onMatch>DENY</onMatch> </filter> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <onMatch>DENY</onMatch> </filter> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M\(%line\) - %msg%n </pattern> </encoder> </appender> <appender name="STDERR" class="ch.qos.logback.core.ConsoleAppender"> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>WARN</level> </filter> <target>System.err</target> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M\(%line\) - %msg%n </pattern> </encoder> </appender> <root level="debug"> <appender-ref ref="STDOUT" /> <appender-ref ref="STDERR" /> </root> </configuration>* однако у него есть метод
decideна API но я понятия не имею, как вы будете использовать его в этом контексте.
Программирование не требуется. конфигурация делает вашу жизнь легкой.
Ниже приведена конфигурация, которая регистрирует разные уровни журналов в разных файлах
<property name="DEV_HOME" value="./logs" /> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>INFO</level> </filter> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern> %d{yyyy-MM-dd HH:mm:ss} %-5level - %msg%n </Pattern> </layout> </appender> <appender name="FILE-ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${DEV_HOME}/app-error.log</file> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <Pattern> %d{yyyy-MM-dd HH:mm:ss} %-5level - %msg%n </Pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- rollover daily --> <fileNamePattern>${DEV_HOME}/archived/app-error.%d{yyyy-MM-dd}.%i.log </fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>10MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <!--output messages of exact level only --> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <appender name="FILE-INFO" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${DEV_HOME}/app-info.log</file> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <Pattern> %d{yyyy-MM-dd HH:mm:ss} %-5level - %msg%n </Pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- rollover daily --> <fileNamePattern>${DEV_HOME}/archived/app-info.%d{yyyy-MM-dd}.%i.log </fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>10MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>INFO</level> <!--output messages of exact level only --> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <appender name="FILE-DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${DEV_HOME}/app-debug.log</file> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <Pattern> %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n </Pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- rollover daily --> <fileNamePattern>${DEV_HOME}/archived/app-debug.%d{yyyy-MM-dd}.%i.log </fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>10MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>DEBUG</level> <!--output messages of exact level only --> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <appender name="FILE-ALL" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${DEV_HOME}/app.log</file> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <Pattern> %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n </Pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- rollover daily --> <fileNamePattern>${DEV_HOME}/archived/app.%d{yyyy-MM-dd}.%i.log </fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>10MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> </appender> <logger name="com.abc.xyz" level="DEBUG" additivity="true"> <appender-ref ref="FILE-DEBUG" /> <appender-ref ref="FILE-INFO" /> <appender-ref ref="FILE-ERROR" /> <appender-ref ref="FILE-ALL" /> </logger> <root level="INFO"> <appender-ref ref="STDOUT" /> </root>
<configuration scan="true" scanPeriod="60 seconds"> <appender name="A1" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${storm.log.dir}/${logfile.name}</file> <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> <fileNamePattern>${storm.log.dir}/${logfile.name}.%i</fileNamePattern> <minIndex>1</minIndex> <maxIndex>9</maxIndex> </rollingPolicy> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <maxFileSize>100MB</maxFileSize> </triggeringPolicy> <encoder> <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSZZ} %c{1} [%p] %m%n</pattern> </encoder> </appender> <appender name="ACCESS" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${storm.log.dir}/access.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> <fileNamePattern>${storm.log.dir}/access.log.%i</fileNamePattern> <minIndex>1</minIndex> <maxIndex>9</maxIndex> </rollingPolicy> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <maxFileSize>100MB</maxFileSize> </triggeringPolicy> <encoder> <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSZZ} %c{1} [%p] %m%n</pattern> </encoder> </appender> <appender name="METRICS" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${storm.log.dir}/metrics.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> <fileNamePattern>${storm.log.dir}/logs/metrics.log.%i</fileNamePattern> <minIndex>1</minIndex> <maxIndex>9</maxIndex> </rollingPolicy> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <maxFileSize>2MB</maxFileSize> </triggeringPolicy> <encoder> <pattern>%d %-8r %m%n</pattern> </encoder> </appender> <root level="INFO"> <appender-ref ref="A1"/> </root> <logger name="backtype.storm.security.auth.authorizer" additivity="false"> <level value="INFO" /> <appender-ref ref="ACCESS" /> </logger> <logger name="backtype.storm.metric.LoggingMetricsConsumer" additivity="false" > <level value="INFO"/> <appender-ref ref="METRICS"/> </logger> </configuration> So here is the logback file in which I am not printing backtype.storm.metric.LoggingMetricsConsumer info level if i say additivity = "true" then for for all classes in backtype.* this rule will be applied
пример вывода цветных сообщений уровня "INFO" или выше до консоль и сообщения уровня "WARN" или выше до file.
код logback.xml file:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/defaults.xml"/> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>INFO</level> <!--output messages of exact level only--> <!--<onMatch>ACCEPT</onMatch>--> <!--<onMismatch>DENY</onMismatch>--> </filter> <encoder> <pattern>%d{yyyy-MMM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{15}) - %msg %n </pattern> </encoder> </appender> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>myfile.log</file> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>WARN</level> </filter> <append>true</append> <encoder> <pattern>%d{yyyy-MMM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{15} - %msg%n</pattern> </encoder> </appender> <root level="INFO"> <appender-ref ref="STDOUT" /> <appender-ref ref="FILE"/> </root> </configuration>
Comments