2009-07-30 6 views
7

J'ai un composant qui lit constamment les valeurs d'un périphérique. Actuellement, il met à jour toutes les {n} secondes et enregistre un message de débogage avec la valeur dans une instance d'ILog.log4net - un filtre pour ne consigner que le Nième message?

Chaque seconde est trop fréquente pour moi, je m'en fous et ça mange trop d'espace de journal. Cependant, je serais certainement intéressé à capturer tous les 10e ou 30e messages de cette composante afin que je puisse avoir une idée générale de ce qu'elle fait.

Est-ce que quelqu'un connaît un moyen de le faire qui ne m'implique pas d'implémenter ma propre implémentation ILog?

Répondre

11

Il est probablement trop tard pour vous aider, mais vous pouvez implémenter un filtre. http://www.mail-archive.com/log4net-user%40logging.apache.org/msg02517.html montre comment implémenter un filtre pour limiter la fréquence de journalisation d'une exception (si le type d'exception est le même que le dernier type d'exception et si moins d'une durée spécifiée est dépassée).

Voici le code source de filtre réelle de ce lien:

public class ExceptionThrottleFilter : FilterSkeleton 
{ 
    private DateTime lastException = DateTime.MinValue; 
    private Type exceptionType = typeof(Exception); 
    private int threshold = 5; // seconds 

    public override void ActivateOptions() 
    { 
    base.ActivateOptions(); 
    } 

    public override FilterDecision Decide(LoggingEvent loggingEvent) 
    { 
    if (loggingEvent.ExceptionObject != null && loggingEvent.ExceptionObject.GetType) == exceptionType) 
    { 
     if (loggingEvent.TimeStamp.Subtract(lastException).TotalSeconds > threshold) 
     { 
     lastException = loggingEvent.TimeStamp; 
     return FilterDecision.Accept; 
     } 
     else 
     { 
     return FilterDecision.Deny; 
     } 
    } 
    else 
    { 
     return FilterDecision.Neutral; 
    } 
    } 

    public Type ExceptionType 
    { 
    get { return exceptionType; } 
    set { exceptionType = value; } 
    } 

    public int Threshold 
    { 
    get { return threshold; } 
    set { threshold = value; } 
    } 
} 

Il serait configuré comme ceci:

<filter type="Company.Project.Logging.ExceptionThrottleFilter"> 
    <threshold value="2" /> 
    <exceptionType value="System.ApplicationException" /> 
</filter> 

Il semble que ce serait assez simple de le modifier à « gaz "messages qui répètent. Peut-être quelque chose comme ça (non testé):

public class DuplicateMessageThrottleFilter : FilterSkeleton 
{ 
    private string lastMessage; 

    public override void ActivateOptions() 
    { 
    base.ActivateOptions(); 
    } 

    public override FilterDecision Decide(LoggingEvent loggingEvent) 
    { 
    string newMessage; 
    if (loggingEvent.MessageObject != null) 
    { 
     newMessage = loggingEvent.MessageObject.ToString(); 
    } 

    if (newMessage.Equals(lastMessage)) 
    { 
     return FilterDecision.Deny; 
    } 

    lastMessage = newMessage; 
    return FilterDecision.Accept; 
    } 
} 

Il pourrait être agréable d'annoter un message connecté avec combien de fois il a été répété, mais comment le faire est pas évident pour moi:

Some message. 
Some message. 
Some message. 
Look, a new message. 
Some message. 
Some message. 
Look, a new message. 

Pourrait générer quelque chose comme ceci:

Some message. (3 times) 
Look, a new message. 
Some message. (2 times) 
Look, a new message. 

Probablement une sorte de ForwardingAppender ou BufferingForwardingAppender. Ce serait toujours un message derrière. Un message arrive. Le message "RepeatedMessageAppender" contient ce message. Le message suivant entre. Si le message est différent du dernier message, transmettre le dernier message au "réel" Appender (si le "compte répété" est> 0, ajouter le numéro au dernier message avant le transfert - c'est la partie que je suis Je ne suis pas sûr parce que je pense qu'il n'est pas facile de modifier le LoggingEvent qui est passé à l'Appender). Si c'est le même que le dernier message, incrémentez le compteur et ne retransmettez pas. Puisque le "RepeatedMessageAppender" est un derrière, il doit probablement être un BufferingForwardingAppender et il doit implémenter Flush.

Peut-être que vous (ou quelqu'un d'autre) trouverez cette information utile.

+0

Très utile en effet. Pour le marquage "combien de fois", je suggère d'utiliser une propriété pour stocker le nombre de fois, puis de l'afficher via un PatternLayout, comme value = "% message (% property {numberOfSimilar} times)". La propriété peut être définie dans Decide (LoggingEvent) par GlobalContext.Properties ["numberOfSimilar"] ++; – PPC

+0

il n'est jamais trop tard ... – KornMuffin

1

Dépend de ce que vous enregistrez. S'il y a quelque chose à consigner chaque seconde, alors peut-être que vous devriez revoir ce que vous enregistrez.

Vous pouvez hacher les messages similaires et les imprimer après un certain temps.

+0

Eh bien, je ne le connecte pas, je désactive la journalisation du niveau de débogage pour ce composant mais je le garde en option bien sûr si je veux enregistrer la valeur que l'application pense être actuellement sur le périphérique. Hashing sonne comme une bonne solution est-il un moyen facile de le configurer? –

+0

Je suis en désaccord avec le "hachage similaire et attendre l'impression": C'est la responsabilité du mécanisme de journalisation, pas celle de votre code d'entreprise de se demander ce qui doit être imprimé.Votre machine dit "Je suis en haut" toutes les secondes, et c'est votre logique de journalisation qui va le traduire "jusqu'à 13:44", pas la machine elle-même, surtout si vous avez besoin de deux bûches différentes, une seule étant coupée mécanisme. – PPC

Questions connexes