2009-07-30 14 views
7

Ho un componente che legge costantemente un valore da un dispositivo. Attualmente si aggiorna ogni {n} secondi e registra un messaggio di debug con il valore su un'istanza di ILog.log4net - nessun filtro per registrare solo l'ennesimo messaggio?

Ogni secondo è troppo frequente per me, semplicemente non mi interessa e si mangia troppo spazio nel registro. Tuttavia, sarei certamente interessato a catturare ogni 10 o 30 messaggio da quel componente in modo da ottenere l'essenza generale di ciò che sta facendo.

Qualcuno conosce un modo per farlo che non mi coinvolge nella mia implementazione ILog?

risposta

11

Probabilmente è troppo tardi per aiutarti, ma potresti implementare un filtro. http://www.mail-archive.com/log4net-user%40logging.apache.org/msg02517.html mostra come implementare un filtro per limitare la frequenza con cui viene registrata un'eccezione (se il tipo di eccezione è uguale all'ultimo tipo di eccezione e se è trascorso meno di un determinato periodo di tempo).

Ecco il codice vero e proprio sorgente di filtro da questo link:

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; } 
    } 
} 

Sarebbe essere configurato in questo modo:

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

Sembra che sarebbe piuttosto semplice per modificarlo a "farfalla "messaggi che si ripetono. Forse qualcosa di simile (non testata):

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; 
    } 
} 

Potrebbe essere bello per annotare un messaggio registrato con quante volte è stato ripetuto, ma come fare che non è ovvio per me:

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

potrebbe generare qualcosa di simile:

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

Probabilmente un qualche tipo di ForwardingAppender o BufferingForwardingAppender. Sarebbe sempre un messaggio dietro. Un messaggio arriva. Il "RepeatedMessageAppender" manterrà quel messaggio. Il messaggio successivo arriva. Se è diverso dall'ultimo messaggio, inoltra l'ultimo messaggio al "reale" Appender (se "count ripetuto" è> 0, aggiungi il numero all'ultimo messaggio prima di inoltrare - questa è la parte che sono Non sono sicuro perché penso che non è facile modificare il LoggingEvent che viene passato all'Appender). Se è lo stesso dell'ultimo messaggio, incrementa il contatore e non inoltra. Poiché "RepeatedMessageAppender" è uno dietro, probabilmente deve essere un BufferingForwardingAppender e deve implementare Flush.

Forse tu (o qualcun altro) troverai utile questa informazione.

+0

Molto utile davvero. Per il tag "quante volte", suggerirei di utilizzare una proprietà per memorizzare il numero di volte, quindi visualizzarlo tramite un PatternLayout, come value = "% message (% property {numberOfSimilar} volte)". La proprietà può essere impostata in Decide (LoggingEvent) da GlobalContext.Properties ["numberOfSimilar"] ++; – PPC

+0

non è mai troppo tardi ... – KornMuffin

1

Dipende da ciò che si sta registrando. Se c'è qualcosa da registrare ogni secondo, forse dovresti rivisitare quello che stai registrando.

È possibile eseguire l'hash dei messaggi simili e stamparli dopo un po 'di tempo.

+0

Beh, non lo sto loggando, disabilito la registrazione del livello di debug per quel componente ma lo tengo ovviamente come opzione se voglio registrare il valore che l'applicazione pensa sia attualmente sul dispositivo. Hashing suona come una buona soluzione: c'è un modo semplice per configurarlo? –

+0

Non sono d'accordo con "hash simile e aspetto la stampa": questa è la responsabilità del meccanismo di registrazione, non quello del codice aziendale per chiedersi che cosa dovrebbe essere stampato.La tua macchina dice "I'm up" ogni secondo, ed è la tua logica di log che la tradurrà "fino alle 13:44", non la macchina stessa, specialmente se hai bisogno di due registri diversi, solo uno viene tagliato da questo meccanismo. – PPC

Problemi correlati