pattern name logger java logging logback

java - name - logback: Dos appenders, mĂșltiples madereros, diferentes niveles



logback logger name (5)

Agregar una solución adicional que es más simple que lo que ya está aquí

Ninguna de estas soluciones funcionó para mí, ya que no estoy usando un framework como Spark o Spring. Así que hice algo un poco más simple que parece funcionar muy bien. Si bien esta solución puede no funcionar para el PO, quizás puede ser útil para alguien que quiere algo que no sea tan voluminoso.

<property name="pattern" value="%d{yyyy.MMM.dd HH:mm:ss.SSS} [ProgramName] %level - %msg%n" /> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>/path/to/your/program.log</file> <append>true</append> <encoder> <pattern>${pattern}</pattern> </encoder> </appender> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <target>System.out</target> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>INFO</level> </filter> <encoder> <pattern>${pattern}</pattern> </encoder> </appender> <root level="debug"> <appender-ref ref="FILE" /> <appender-ref ref="STDOUT" /> </root>

Con esta configuración, puedo mantener la consola bastante limpia, al tiempo que envío declaraciones DEBUG al archivo de registro.

Quiero tener dos archivos de registro en mi aplicación (Spring Integration), debug.log y main.log. Quiero ejecutar main.log en un nivel INFO y debug.log en un nivel de DEPURACIÓN. Esto es factible con filtros en los appenders. Quiero registrar diferentes niveles para los apéndices en función de la fuente. En otras palabras

<logger name="org.springframework" level="ERROR"> <appender-ref ref="main" /> </logger> <logger name="org.springframework" level="DEBUG"> <appender-ref ref="debug" /> </logger> <logger name="com.myapp" level="INFO"> <appender-ref ref="main" /> </logger> <logger name="com.myapp" level="DEBUG"> <appender-ref ref="debug" /> </logger>

Entonces para resumir:

  1. Registrador de primavera
    • main -> ERROR
    • depurar -> DEPURAR
  2. com.myapp logger
    • main -> INFO
    • depurar -> DEPURAR

Debido a esto, tengo que tener los registradores ejecutándose en DEBUG y un filtro de umbral en un appender no es lo suficientemente fino.

Actualizar Claridad agregada a la pregunta


Acabo de encontrar una solución práctica que usa elementos de logback solo que funciona bastante bien, esencialmente necesitas tener dos appenders, uno con la configuración predeterminada y el otro con un filtro (en mi ejemplo, estoy usando la consola):

<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="WARN_FILTER_STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>WARN</level> </filter> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <logger name="org.apache.spark" level="INFO" additivity="false"> <appender-ref ref="SPARK" /><!-- this line is not necessary, just here to ilustrate the need for the filter --> <appender-ref ref="WARN_FILTER_STDOUT" /> </logger> <root level="info"> <appender-ref ref="STDOUT" /> </root>


Crea una clase ThresholdLoggerFilter que se puede poner en un appender como:

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>INFO</level> </filter> <filter class="com.myapp.ThresholdLoggerFilter"> <logger>org.springframework</logger> <level>ERROR</level> </filter> </appender>

El siguiente código funciona

package com.myapp; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.filter.Filter; import ch.qos.logback.core.spi.FilterReply; public class ThresholdLoggerFilter extends Filter<ILoggingEvent> { private Level level; private String logger; @Override public FilterReply decide(ILoggingEvent event) { if (!isStarted()) { return FilterReply.NEUTRAL; } if (!event.getLoggerName().startsWith(logger)) return FilterReply.NEUTRAL; if (event.getLevel().isGreaterOrEqual(level)) { return FilterReply.NEUTRAL; } else { return FilterReply.DENY; } } public void setLevel(Level level) { this.level = level; } public void setLogger(String logger) { this.logger = logger; } public void start() { if (this.level != null && this.logger != null) { super.start(); } } }


También puede hacer esto de una manera más simple si está dispuesto a heredar del registrador de raíz, por ejemplo, aquí agregamos un registrador extra para los errores, que se registra en stderr. Solo está habilitado para madereros en particular.

<configuration> <appender name="CONSOLE-stdout" class="ch.qos.logback.core.ConsoleAppender"> <target>System.out</target> <encoder> <pattern>%d %-5level [%thread] %logger{0}: %msg%n</pattern> </encoder> </appender> <appender name="CONSOLE-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 [%thread] %logger{0}: %msg%n</pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="CONSOLE-stdout" /> </root> <!-- We want error logging from this logger to go to an extra appender It still inherits CONSOLE-stdout from the root logger --> <logger name="org.springframework" level="INFO"> <appender-ref ref="CONSOLE-stderr" /> </logger> </configuration>


Usar múltiples registradores para diferentes mensajes será así:

import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.encoder.PatternLayoutEncoder; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.FileAppender; public class ConfigureLogBack { public static void programmaticConfiguration() { Logger camel = getLogger("MyRoute", C://Users//amrut.malaji//Desktop//Oracle//logback//camel-Log.txt"); Logger services = getLogger("webservices", "C://Users//amrut.malaji//Desktop//Oracle//logback//services-log.txt"); } private static Logger getLogger(String string, String file) { LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); PatternLayoutEncoder ple = new PatternLayoutEncoder(); ple.setPattern("%date %level [%thread] %logger{10} [%file:%line] %msg%n"); ple.setContext(lc); ple.start(); FileAppender<ILoggingEvent> fileAppender = new FileAppender<ILoggingEvent>(); fileAppender.setFile(file); fileAppender.setEncoder(ple); fileAppender.setContext(lc); fileAppender.start(); Logger logger = (Logger) LoggerFactory.getLogger(string); logger.addAppender(fileAppender); logger.setLevel(Level.INFO); logger.setAdditive(false); /* set to true if root should log too */ return logger; }