2009-07-30 12 views
7

Tengo un componente que lee constantemente valores de un dispositivo. Actualmente, actualiza cada {n} segundos y registra un mensaje de depuración con el valor de una instancia de ILog.log4net: ¿algún filtro para registrar solo el enésimo mensaje?

Cada segundo es demasiado frecuente para mí, simplemente no me importa y se come demasiado espacio de registro. Sin embargo, ciertamente estaría interesado en capturar cada décimo o trigésimo mensaje de ese componente para poder obtener la esencia general de lo que está haciendo.

¿Alguien sabe alguna forma de hacer esto que no me involucre en mi propia implementación ILog?

Respuesta

11

Probablemente sea demasiado tarde para ayudarlo, pero podría implementar un filtro. http://www.mail-archive.com/log4net-user%40logging.apache.org/msg02517.html muestra cómo implementar un filtro para limitar la frecuencia con la que se registra una excepción (si el tipo de excepción es el mismo que el último tipo de excepción y si ha transcurrido menos de una cantidad específica de tiempo).

Aquí está el código fuente real del filtro a partir de ese enlace:

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

Sería ser configurado de esta manera:

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

Parece que sería bastante sencillo modificarlo para "acelerador "mensajes que se repiten. Tal vez algo como esto (no probado):

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

podría ser bueno para anotar un mensaje registrado con el número de veces que se repite, pero la forma de hacerlo no es evidente para mí:

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

podría generar algo como esto:

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

Probablemente algún tipo de ForwardingAppender o BufferingForwardingAppender. Siempre sería un mensaje detrás. Aparece un mensaje. El "RepeatedMessageAppender" contendría ese mensaje. El siguiente mensaje entra. Si es diferente al último mensaje, reenvíe el último mensaje al Appender "real" (si "conteo repetido" es> 0, añada el número al último mensaje antes de reenviar - esta es la parte que soy no estoy seguro porque creo que no es fácil modificar el LoggingEvent que se pasa al Appender). Si es el mismo que el último mensaje, incremente el contador y no reenvíe. Como el "RepeatedMessageAppender" está a una detras, probablemente tiene que ser un BufferingForwardingAppender y debe implementar Flush.

Quizás usted (u otra persona) encuentre esta información útil.

+0

Muy útil de hecho. Para el etiquetado "cuántas veces", sugiero usar una propiedad para almacenar el número de veces, y luego mostrarlo a través de PatternLayout, como value = "% message (% property {numberOfSimilar} times)". La propiedad podría establecerse en Decide (LoggingEvent) por GlobalContext.Properties ["numberOfSimilar"] ++; – PPC

+0

nunca es demasiado tarde ... – KornMuffin

1

Depende de lo que está registrando. Si hay algo que registrar cada segundo, tal vez deba volver a visitar lo que está registrando.

Puede ver los mensajes similares e imprimirlos después de un tiempo.

+0

Bueno, no lo estoy registrando, deshabilito el registro de nivel de depuración para ese componente, pero lo guardo como una opción, por supuesto, si quiero registrar el valor que la aplicación cree que está actualmente en el dispositivo. Hashing suena como una buena solución ¿hay alguna manera fácil de configurarlo? –

+0

No estoy de acuerdo con el "hash similar y espere la impresión": es responsabilidad del mecanismo de registro, no de su código comercial, preguntarse qué se debe imprimir.Su máquina dice "Estoy listo" cada segundo, y es su lógica de registro lo que lo traducirá a "desde 13:44", no la máquina en sí, especialmente si necesita dos registros diferentes, solo uno está cortado por este mecanismo. – PPC

Cuestiones relacionadas