2010-03-22 20 views
41

Je souhaite configurer le logback pour effectuer les opérations suivantes.Comment faire pour lancer le fichier journal au démarrage dans le journal

  • Connexion à un fichier
  • Roulez le fichier quand il atteint 50 Mo
  • TENIR 7 jours de journaux
  • Au démarrage génèrent toujours un nouveau fichier (faire un rouleau)

Je l'ai tout fonctionne sauf pour le dernier élément, le rouleau de démarrage. Est-ce que quelqu'un sait comment y parvenir? Voici la config ...

<appender name="File" class="ch.qos.logback.core.rolling.RollingFileAppender"> 

    <layout class="ch.qos.logback.classic.PatternLayout"> 
     <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg \(%file:%line\)%n</Pattern> 
    </layout> 

    <File>server.log</File> 

    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 
     <FileNamePattern>server.%d{yyyy-MM-dd}.log</FileNamePattern> 
     <!-- keep 7 days' worth of history --> 
     <MaxHistory>7</MaxHistory> 

     <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> 
     <MaxFileSize>50MB</MaxFileSize> 
     </TimeBasedFileNamingAndTriggeringPolicy> 

    </rollingPolicy> 
    </appender> 

Répondre

1

Créer votre propre sous-classe de ch.qos.logback.core.rolling.TimeBasedRollingPolicy et passer outre son start

public class MyPolicy 
    extends ch.qos.logback.core.rolling.TimeBasedRollingPolicy 
{ 

    public void start () 
    { 
     super.start(); 
     rollover(); 
    } 
} 
+0

Malheureusement cela ne fonctionne pas parce que la politique de déclenchement retourne null de getElapsedPeriodsFileName() qui explose alors le rollover(). –

3

Redéfinition de la méthode isTriggeringEvent() dans ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP devrait fonctionner bien. Renvoie juste 'true' la première fois que la méthode isTriggeringEvent() est appelée.

+0

existe-t-il un moyen de roll-over au démarrage - sans avoir besoin d'un événement déclencheur? J'ai un fileappender pour les messages d'erreur seulement.Je veux que l'error-logfile soit vide après chaque démarrage - où généralement aucune erreur ne se produit. –

+0

Puis-je demander, quel est le but de bidouiller avec maxFileSize? – Mykro

+0

Hey Ceki, est-ce que cela doit être thread safe? IsTriggeringEvent est-il appelé à partir de plusieurs threads? –

2

La solution de Ceki ne semble pas fonctionner pour moi, mais semble être en partie au moins là.

Il explose parce qu'il ne peut pas voir la politique de roulement au démarrage du TimeBasedFileNamingAndTriggeringPolicyBase. Avec un peu de hackery je l'ai eu pour faire de la journalisation, et avec plus je l'ai eu pour observer le déclencheur, mais alors il a cassé encore parce qu'il ne pourrait pas résoudre une des propriétés de nom de fichier ... Le paquet est un logback donc je pourrait arriver à certains des internes, pour reproduire une partie de la logique dans SizeAndTimeBasedFNATP#isTriggeringEvent et appelez computeCurrentPeriodsHighestCounterValue. Je pense que quelque chose dans ce sens pourrait marcher, mais je n'ai pas encore trouvé la combinaison magique. J'espère vraiment que je ferai quelque chose de bête, parce que sinon, je pense que cela signifiera soit ouvrir certains détails pour la sous-classification, soit mettre cela directement dans le logback comme une autre politique de roulement/déclenchement.

logback.xml: essayé diverses commandes de triggeringPolicy, TimeBasedFileNamingAndTriggeringPolicy à l'intérieur et à l'extérieur du rollingPolicy.

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> 
    <file>${LOG_DIR}/${LOG_FILE_BASE}.log</file> 
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 
     <fileNamePattern>${LOG_DIR}/${LOG_FILE_BASE}.%d{yyyy-MM-dd}.%i.log</fileNamePattern> 
     <MaxHistory>7</MaxHistory> 

     <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.RollOnStartupPolicy" /> 
    </rollingPolicy> 

    <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> 
     <level>INFO</level> 
    </filter> 

    <encoder> 
     <pattern>%msg%n</pattern> 
    </encoder> 
</appender> 

La politique de déclenchement:

package ch.qos.logback.core.rolling; 
public class RollOnStartupPolicy<E> extends SizeAndTimeBasedFNATP<E> { 
private final AtomicBoolean firstTime = new AtomicBoolean(true); 

    @Override 
    public boolean isTriggeringEvent(File activeFile, E event) { 
     if (!firstTime.get()) { // fast path 
      return false; 
     } 

     if (firstTime.getAndSet(false)) { 
      return true; 
     } 
     return false; 
    } 
} 

L'exception:

java.lang.NullPointerException 
at at ch.qos.logback.core.rolling.TimeBasedFileNamingAndTriggeringPolicyBase.start(TimeBasedFileNamingAndTriggeringPolicyBase.java:46) 
at at ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP.start(SizeAndTimeBasedFNATP.java:36) 
at at ch.qos.logback.core.joran... [snip joran config] 
7

Il fonctionne pour moi, en utilisant la classe suivante comme timeBasedFileNamingAndTriggeringPolicy:

import java.io.File; 
import java.util.concurrent.atomic.AtomicBoolean; 

import ch.qos.logback.core.joran.spi.NoAutoStart; 
import ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP; 

@NoAutoStart 
public class Trigger<E> extends SizeAndTimeBasedFNATP<E> 
{ 
    private final AtomicBoolean trigger = new AtomicBoolean(); 

    public boolean isTriggeringEvent(final File activeFile, final E event) { 
     if (trigger.compareAndSet(false, true) && activeFile.length() > 0) { 
      String maxFileSize = getMaxFileSize(); 
      setMaxFileSize("1"); 
      super.isTriggeringEvent(activeFile, event); 
      setMaxFileSize(maxFileSize); 
      return true; 
     } 
     return super.isTriggeringEvent(activeFile, event); 
    } 
} 
1

Je suis la suivant à travailler (en combinant les idées des réponses précédentes). Note Je travaillais avec des fichiers basés sur la taille, pas sur le temps, mais je suppose que la même solution fonctionne.

public class StartupSizeBasedTriggeringPolicy<E> extends ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy<E> { 

private final AtomicReference<Boolean> isFirstTime = new AtomicReference<Boolean>(true); 

@Override 
public boolean isTriggeringEvent(final File activeFile, final E event) { 

    //this method appears to have side-effects so always call 
    boolean result = super.isTriggeringEvent(activeFile, event); 

    return isFirstTime.compareAndSet(true, false) || result; 
} 

}

23

Aucun des autres suggestions convenait à ma situation. Je ne voulais pas utiliser une solution basée sur la taille et le temps, car cela nécessite de configurer un MaxFileSize, et nous utilisons une politique strictement basée sur le temps.Voici comment j'accompli rouler le fichier au démarrage avec un TimeBasedRollingPolicy:

@NoAutoStart 
public class StartupTimeBasedTriggeringPolicy<E> 
     extends DefaultTimeBasedFileNamingAndTriggeringPolicy<E> { 

    @Override 
    public void start() { 
     super.start(); 
     nextCheck = 0L; 
     isTriggeringEvent(null, null); 
     try { 
      tbrp.rollover(); 
     } catch (RolloverFailure e) { 
      //Do nothing 
     } 
    } 

} 

L'astuce consiste à régler l'heure nextCheck à 0L, de sorte que isTriggeringEvent() pensera qu'il est temps de lancer le fichier journal sur. Il exécutera donc le code nécessaire pour calculer le nom de fichier, ainsi que la réinitialisation de la valeur de temps nextCheck. L'appel suivant à rollover() entraîne le roll-file du fichier journal. Comme cela ne se produit qu'au démarrage, c'est une solution plus optimale que celles qui effectuent une comparaison dans isTriggerEvent(). Aussi petite que soit cette comparaison, elle dégrade encore légèrement les performances lorsqu'elle est exécutée sur chaque message de journal. Cela force également le rollover à se produire immédiatement au démarrage, au lieu d'attendre le premier événement de journal. L'annotation @NoAutoStart est importante pour empêcher Joran d'exécuter la méthode start() avant que toutes les autres initialisations soient terminées. Sinon, vous obtenez une exception NullPointerException.

Voici la config:

<!-- Daily rollover appender that also appends timestamp and rolls over on startup --> 
    <appender name="startupDailyRolloverAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"> 
    <file>${LOG_FILE}</file> 
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 
     <fileNamePattern>${LOG_FILE}.%d{yyyyMMdd}_%d{HHmmss,aux}</fileNamePattern> 
     <TimeBasedFileNamingAndTriggeringPolicy class="my.package.StartupTimeBasedTriggeringPolicy" /> 
    </rollingPolicy> 
    <encoder> 
     <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> 
    </encoder> 
    </appender> 

Hope this helps!

+1

Je luttais et c'est exactement ce que je veux, merci! IMO cela devrait être une fonctionnalité standard et de config est un peu peu intuitif – vincentlcy

+1

Merci pour la solution - Je suis d'accord avec @vincentlcy et pense aussi que cela devrait être une fonctionnalité standard. – dcompiled

+0

Je veux juste ajouter mes remerciements pour une excellente solution. Je veux ajouter ceci ne fonctionne (Logback 1.0.13) si vous avez défini un nom de fichier brut: event.txt Si vous excluez ce de votre config afin que vous obtenez seulement .0, .1, .2, fichiers indexés etc (ceci est recommandé par la documentation de Logback pour les plates-formes Windows pour éviter les problèmes de verrouillage/renommage de fichiers) alors cette solution n'effectuera malheureusement pas de rollover car dans TimeBasedRollingPolicy.rollover() l'appel à getParentsRawFileProperty () renvoie null. – Mykro

1

Je l'ai enfin compris. Je peux rouler par taille, temps et démarrer. Voici la solution:

1er vous créer votre propre classe

@NoAutoStart 
public class StartupSizeTimeBasedTriggeringPolicy<E> extends SizeAndTimeBasedFNATP<E> { 

    private boolean started = false; 

    @Override 
    public boolean isTriggeringEvent(File activeFile, E event) { 
     if (!started) { 
      nextCheck = 0L; 
      return started = true; 
     } 

     return super.isTriggeringEvent(activeFile, event); 
    }; 
} 

2ème configure logback

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> 
    <file>${LOGS_DIR}/${FILE_NAME}.log</file> 
    <encoder> 
     <pattern>%d [%thread] %-5level %logger{50} - %msg%n</pattern> 
    </encoder> 
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 
     <fileNamePattern>${LOGS_DIR}/${FILE_NAME}.%d{yyyy-MM-dd}_%d{HHmmss,aux}.%i.log.zip</fileNamePattern> 
     <maxHistory>30</maxHistory> 
     <TimeBasedFileNamingAndTriggeringPolicy class="my.StartupSizeTimeBasedTriggeringPolicy"> 
      <MaxFileSize>250MB</MaxFileSize> 
     </TimeBasedFileNamingAndTriggeringPolicy> 
    </rollingPolicy> 
</appender> 
1

Cette solution fonctionne vraiment, merci beaucoup. Cependant, il y a un problème gênant: lorsque vous lancez le programme pour la première fois, le journal est lancé juste après sa création, lorsqu'il est vide ou presque vide. Donc, je suggère un correctif: vérifiez si le fichier journal existe et n'est pas vide au moment de l'appel de la méthode. En outre, une autre correction cosmétique: renommez la variable "started", car elle cache le membre hérité avec le même nom.

@NoAutoStart 
public class StartupSizeTimeBasedTriggeringPolicy<E> extends  SizeAndTimeBasedFNATP<E> { 

    private boolean policyStarted; 

    @Override 
    public boolean isTriggeringEvent(File activeFile, E event) { 
     if (!policyStarted) { 
      policyStarted = true; 
      if (activeFile.exists() && activeFile.length() > 0) { 
       nextCheck = 0L; 
       return true; 
      } 
     } 
     return super.isTriggeringEvent(activeFile, event); 
    } 
} 

Aussi, je crois que cela fonctionne correctement avec la version logback-SNAPSHOT 1.1.4 (je suis la source et moi-même compilé), mais il ne fonctionne pas pleinement avec 1.1.3 version. Avec 1.1.3, il nomme les fichiers correctement avec le fuseau horaire spécifié, mais le survol se produit toujours au fuseau horaire par défaut minuit.

+0

Je vois que la version 1.1.7 est sortie maintenant, mais cette fonctionnalité n'est toujours pas là. Y a-t-il des plans pour l'ajouter à l'emballage standard? Ça a l'air d'être assez simple. Évidemment, j'utilise toujours ma propre StartupSizeTimeBasedTriggeringPolicy, mais c'est ennuyeux de garder une petite addition. –

5

J'ai trouvé une autre solution pour rouler le fichier journal une fois, lorsque l'application démarre.

J'utilise le RollingFileAppender de logback avec le FixedWindowRollingPolicy de logback et ma propre implémentation d'un TriggeringPolicy<E>. Le FixedWindowRollingPolicy obtient le nomFichierPattern pour le nouveau fichier journal, %1 étant le nouveau numéro du fichier. Le maxIndex représente le nombre maximum de mon "histoire". Plus d'informations: FixedWindowRollingPolicy

Mes implémentations TriggeringPolicy renvoie vrai pour la première temps, quand isTriggeringEvent (...) est appelée. WindowRollingPolicy survole donc les fichiers journaux, lorsque la stratégie est appelée la première fois et qu'elle ne se répète plus.

Le xml-configuration pour le RollingFileAppender:

<configuration> 
    ... 
    <appender name="FILE_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender"> 
     <file>logFile.log</file> 

     <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> 
      <fileNamePattern>logFile.%i.log</fileNamePattern> 
      <minIndex>1</minIndex> 
      <maxIndex>4</maxIndex> 
     </rollingPolicy> 

     <triggeringPolicy class="my.classpath.RollOncePerSessionTriggeringPolicy"/> 
    </appender> 
... 
</configuration> 

Le TriggeringPolicy:

package my.classpath; 

import ch.qos.logback.core.rolling.TriggeringPolicyBase; 

import java.io.File; 

public class RollOncePerSessionTriggeringPolicy<E> extends TriggeringPolicyBase<E> { 
    private static boolean doRolling = true; 

    @Override 
    public boolean isTriggeringEvent(File activeFile, E event) { 
     // roll the first time when the event gets called 
     if (doRolling) { 
      doRolling = false; 
      return true; 
     } 
     return false; 
    } 
} 
3

Pour une solution en utilisant des composants déjà existants le logback suggère les fichiers portant un nom unique: http://logback.qos.ch/manual/appenders.html#uniquelyNamed

Pendant la phase de développement d'application ou dans le cas d'applications de courte durée , par ex. applications par lots, il est souhaitable de créer un nouveau fichier journal à chaque lancement d'une nouvelle application. C'est assez facile à faire avec l'élément <timestamp>.

<?xml version="1.0" encoding="UTF-8"?> 
<configuration> 
    <timestamp key="startTimestamp" datePattern="yyyyMMddHHmmssSSS"/> 
    <appender name="File" 
    class="ch.qos.logback.core.rolling.RollingFileAppender"> 
     <layout class="ch.qos.logback.classic.PatternLayout"> 
      <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg \(%file:%line\)%n</Pattern> 
     </layout> 

     <file>server-${startTimestamp}.log</file> 

     <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 
      <FileNamePattern>server-${startTimestamp}-%d{yyyy-MM-dd}-%i.log</FileNamePattern> 
      <!-- keep 7 days' worth of history --> 
      <MaxHistory>7</MaxHistory> 

      <TimeBasedFileNamingAndTriggeringPolicy 
      class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> 
       <MaxFileSize>1KB</MaxFileSize> 
      </TimeBasedFileNamingAndTriggeringPolicy> 
     </rollingPolicy> 
    </appender> 
    <root level="DEBUG"> 
     <appender-ref ref="File" /> 
    </root> 
</configuration> 

MISES A JOUR POUR logback-1.2.1

<?xml version="1.0" encoding="UTF-8"?> 
<configuration> 
    <timestamp key="startTimestamp" datePattern="yyyyMMddHHmmssSSS"/> 
    <appender name="File" 
    class="ch.qos.logback.core.rolling.RollingFileAppender"> 
     <layout class="ch.qos.logback.classic.PatternLayout"> 
      <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg \(%file:%line\)%n</Pattern> 
     </layout> 

     <file>server-${startTimestamp}.log</file> 

     <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> 
      <fileNamePattern>server-${startTimestamp}-%d{yyyy-MM-dd}-%i.log</fileNamePattern> 
      <maxFileSize>10MB</maxFileSize> 
      <!-- keep 7 days' worth of history --> 
      <maxHistory>7</maxHistory> 
      <totalSizeCap>20GB</totalSizeCap> 
     </rollingPolicy> 
    </appender> 
    <root level="DEBUG"> 
     <appender-ref ref="File" /> 
    </root> 
</configuration> 
0

L'API a changé (par exemple setMaxFileSize n'existe plus) et beaucoup de choses ci-dessus ne semblent fonctionner, mais j'ai quelque chose qui fonctionne pour moi contre le logback 1.1.8 (le dernier en ce moment).

Je voulais lancer au démarrage et rouler sur la taille, mais pas le temps. Il le fait:

public class RollOnStartupAndSizeTriggeringPolicy<E> extends SizeBasedTriggeringPolicy<E> { 
    private final AtomicBoolean firstTime = new AtomicBoolean(); 

    public boolean isTriggeringEvent(final File activeFile, final E event) { 
     if (firstTime.compareAndSet(false, true) && activeFile != null && activeFile.length() > 0) { 
      return true; 
     } 
     return super.isTriggeringEvent(activeFile, event); 
    } 
} 

Avec cela, vous avez également besoin d'une politique de roulement. FixedWindowRollingPolicy ferait probablement, mais je ne l'aime pas parce que je veux garder un grand nombre de fichiers et c'est très inefficace pour ça. Quelque chose qui incrémente les nombres (au lieu de glisser comme FixedWindow) fonctionnerait, mais cela n'existe pas. Tant que j'écris le mien, j'ai décidé d'utiliser le temps au lieu de compter. Je voulais étendre le code de logback actuel, mais pour les choses basées sur le temps, les politiques de roulement et de déclenchement sont souvent combinées en une seule classe, et il y a des logs et des champs sans getters, donc j'ai trouvé cela plutôt impossible. Donc j'ai dû faire beaucoup de rien. Je reste simple et n'ai pas implémenté des fonctionnalités comme la compression - j'adorerais les avoir, mais j'essaie simplement de garder les choses simples.

public class TimestampRollingPolicy<E> extends RollingPolicyBase { 
    private final RenameUtil renameUtil = new RenameUtil(); 
    private String activeFileName; 
    private String fileNamePatternStr; 
    private FileNamePattern fileNamePattern; 

    @Override 
    public void start() { 
     super.start(); 
     renameUtil.setContext(this.context); 
     activeFileName = getParentsRawFileProperty(); 
     if (activeFileName == null || activeFileName.isEmpty()) { 
      addError("No file set on appender"); 
     } 
     if (fileNamePatternStr == null || fileNamePatternStr.isEmpty()) { 
      addError("fileNamePattern not set"); 
      fileNamePattern = null; 
     } else { 
      fileNamePattern = new FileNamePattern(fileNamePatternStr, this.context); 
     } 
     addInfo("Will use the pattern " + fileNamePattern + " to archive files"); 
    } 

    @Override 
    public void rollover() throws RolloverFailure { 
     File f = new File(activeFileName); 
     if (!f.exists()) { 
      return; 
     } 
     if (f.length() <= 0) { 
      return; 
     } 
     try { 
      String archiveFileName = fileNamePattern.convert(new Date(f.lastModified())); 
      renameUtil.rename(activeFileName, archiveFileName); 
     } catch (RolloverFailure e) { 
      throw e; 
     } catch (Exception e) { 
      throw new RolloverFailure(e.toString(), e); 
     } 
    } 

    @Override 
    public String getActiveFileName() { 
     return activeFileName; 
    } 

    public void setFileNamePattern(String fnp) { 
     fileNamePatternStr = fnp; 
    } 
} 

Et puis config ressemble

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> 
    <encoder> 
    <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> 
    </encoder> 
    <file>/tmp/monitor.log</file> 
    <rollingPolicy class="my.log.TimestampRollingPolicy"> 
    <fileNamePattern>/tmp/monitor.%d{yyyyMMdd-HHmmss}.log</fileNamePattern> 
    </rollingPolicy> 
    <triggeringPolicy class="my.log.RollOnStartupAndSizeTriggeringPolicy"> 
    <maxFileSize>1gb</maxFileSize> 
    </triggeringPolicy> 
</appender> 

si vous êtes frustré ce n'est pas résolu en mode natif, votez pour elle à

http://jira.qos.ch/browse/LOGBACK-204

http://jira.qos.ch/browse/LOGBACK-215

(il est été des années, et pour moi, c'est un plaisir absolument critique ctionality, bien que je sache que beaucoup d'autres frameworks échouent aussi)