2017-08-29 1 views
0

Je vais mettre mon application java dans docker. Mais sur la base de l'installation d'exploitation forestière de notre entreprise, je dois utiliser fluentd pour collecter le journal des conteneurs. Cela m'oblige à mettre des stacktraces java dans un journal de ligne.Problèmes d'impression java exceptions dans une ligne par le logback pour docker

J'ai fait ce qui suit, cela fonctionne dans certaines circonstances mais échoue l'un dans l'autre.

package com.alex; 

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

import java.util.zip.DataFormatException; 

public class Main { 
    private static final Logger logger = LoggerFactory.getLogger(Main.class); 

    public static void alexExc() throws Exception { 
     throw new Exception("hello"); 
    } 

    public static void main(String[] args) throws Exception { 
     try { 
      alexExc(); 
     } catch (Throwable t) { 
      logger.error("oops", t); 
     } 

     throw new DataFormatException("invalid data format"); 
    } 
} 

Ce qui suit est mon convertisseur pour remplacer le séparateur avec mon spécifié un "# 012"

package com.alex; 

import ch.qos.logback.classic.pattern.ThrowableProxyConverter; 
import ch.qos.logback.classic.spi.IThrowableProxy; 
import ch.qos.logback.core.CoreConstants; 

public class OneLineStackTraceConverter extends ThrowableProxyConverter { 
    protected String throwableProxyToString(IThrowableProxy tp) { 
     String originalStackTrace = super.throwableProxyToString(tp); 

     return originalStackTrace.replace(CoreConstants.LINE_SEPARATOR, " #012"); 
    } 
} 

Et est alors ma configuration logback:

<?xml version="1.0" encoding="UTF-8" ?> 
<configuration scan="true" scanPeriod="30 seconds"> 
    <conversionRule conversionWord="ex" 
      converterClass="com.alex.OneLineStackTraceConverter" /> 

    <appender name="INFO_FILE" 
       class="ch.qos.logback.core.rolling.RollingFileAppender"> 
     <file>/logs/loggingmdc/info.log</file> 
     <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> 
      <fileNamePattern>/logs/loggingmdc/info.log.%i</fileNamePattern> 
      <minIndex>1</minIndex> 
      <maxIndex>5</maxIndex> 
     </rollingPolicy> 
     <triggeringPolicy 
       class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> 
      <maxFileSize>1GB</maxFileSize> 
     </triggeringPolicy> 
     <encoder> 
      <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %le %logger{0}: ## %msg\n</pattern> 
     </encoder> 
     <filter class="ch.qos.logback.classic.filter.LevelFilter"> 
      <level>INFO</level> 
      <onMatch>ACCEPT</onMatch> 
      <onMismatch>DENY</onMismatch> 
     </filter> 
    </appender> 
    <appender name="DEBUG_FILE" 
       class="ch.qos.logback.core.rolling.RollingFileAppender"> 
     <file>/logs/loggingmdc/debug.log</file> 
     <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> 
      <fileNamePattern>/logs/loggingmdc/debug.log.%i</fileNamePattern> 
      <minIndex>1</minIndex> 
      <maxIndex>5</maxIndex> 
     </rollingPolicy> 
     <triggeringPolicy 
       class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> 
      <maxFileSize>1GB</maxFileSize> 
     </triggeringPolicy> 
     <encoder> 
      <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %le %logger{0}: ## %msg %ex\n</pattern> 
     </encoder> 
     <filter class="ch.qos.logback.classic.filter.LevelFilter"> 
      <level>DEBUG</level> 
      <onMatch>ACCEPT</onMatch> 
      <onMismatch>DENY</onMismatch> 
     </filter> 
    </appender> 
    <appender name="ERROR_FILE" 
       class="ch.qos.logback.core.rolling.RollingFileAppender"> 
     <file>/logs/loggingmdc/error.log</file> 
     <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> 
      <fileNamePattern>/logs/loggingmdc/error.log.%i</fileNamePattern> 
      <minIndex>1</minIndex> 
      <maxIndex>5</maxIndex> 
     </rollingPolicy> 
     <triggeringPolicy 
       class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> 
      <maxFileSize>1GB</maxFileSize> 
     </triggeringPolicy> 
     <encoder> 
      <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %le %logger{0}: ## %msg %ex\n</pattern> 
     </encoder> 
     <filter class="ch.qos.logback.classic.filter.LevelFilter"> 
      <level>ERROR</level> 
      <onMatch>ACCEPT</onMatch> 
      <onMismatch>DENY</onMismatch> 
     </filter> 
    </appender> 
    <appender name="THIRD_PARTY_FILE" 
       class="ch.qos.logback.core.rolling.RollingFileAppender"> 
     <file>/logs/loggingmdc/thirdparty.log</file> 
     <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> 
      <fileNamePattern>/logs/loggingmdc/thirdparty.log.%i</fileNamePattern> 
      <minIndex>1</minIndex> 
      <maxIndex>5</maxIndex> 
     </rollingPolicy> 
     <triggeringPolicy 
       class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> 
      <maxFileSize>1GB</maxFileSize> 
     </triggeringPolicy> 
     <encoder> 
      <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %le %logger{0}: ## %msg %ex\n</pattern> 
     </encoder> 
    </appender> 

    <root level="INFO"> 
     <appender-ref ref="THIRD_PARTY_FILE"/> 
    </root> 
    <logger name="com.alex" level="DEBUG" additivity="false"> 
     <appender-ref ref="INFO_FILE"/> 
     <appender-ref ref="DEBUG_FILE"/> 
     <appender-ref ref="ERROR_FILE"/> 
    </logger> 
</configuration> 

Comme vous pouvez le voir dans Dans ma configuration de logback, j'ajoute un conversionRule pour spécifier que l'exception dans l'événement de journalisation est d'utiliser mon OneLineStackTraceConverter.

  1. il fonctionne si j'inclus %ex dans chaque modèle pour mon encodeur
  2. il ne fonctionne pas si je DONOT inclure %ex dans le motif. Pourquoi? Si l'utilisateur oublie d'inclure %ex dans son modèle, ai-je un autre mot de conversion à utiliser pour cette exception?
  3. Le dernier DataFormatException ne va pas dans le fichier journal, il sort dans la console, ce que je m'attends aussi à ce qu'il passe au fichier journal. Comment puis-je le faire pour le faire?

Merci.

Répondre

1

cela ne fonctionne pas si JE N'INDIQUE pas% ex dans le motif. Pourquoi? Parce que vous avez déclaré le mot de conversion = ex

Si vous ne l'utilisez pas, Logback ne sait pas ce que vous pensez, donc il ne fait rien. Comparez cela avec déclarer une variable dans le code et ne pas l'utiliser, et vous devriez être capable de comprendre.

Le dernier DataFormatException ne va pas dans le fichier journal

Parce qu'il est pas connecté aussi loin que votre code va. Si vous lancez une exception dans votre code, Logback (ou SLF4J dans votre cas) ne va pas automatiquement l'attraper et l'enregistrer.

+0

Merci pour votre réponse. Pour le premier, je comprends exactement ce que vous avez expliqué. Mais quand j'utilise '% ex' dans le pattern, la stacktrace est formatée en une ligne. Si je supprime '% ex' dans le pattern, la stacktrace est également dans le fichier journal, mais ils sont toujours la stackstrace multiligne d'origine, n'utilisant pas mon convertisseur spécifié. Pour le second, y a-t-il un moyen pour moi de diriger l'exception vers le fichier journal également? – Alex

+0

@Alex 1) Le journal de connexion correspond aux instructions du journal avec le modèle. Si vous ne fournissez pas d'analyseur personnalisé pour vos instructions de journal, il les transfèrera simplement vers l'appender dans le cadre du message. Ceci est analogue à une correspondance regex - seules les parties que vous spécifiez sont appariées. 2) Vous pouvez déclarer un appender de console, et utiliser fluentd pour pomper les journaux Docker aussi. –