Registrazione condizionale con log4j

L’applicazione web su cui lavoro occasionalmente sviluppa problemi di integrità dei dati per alcuni utenti. Mi piacerebbe triggersre la registrazione a livello di traccia, ma dato che abbiamo a che fare con centinaia di richieste al secondo di tracciamento, ogni singola richiesta è fuori questione.

C’è un modo con log4j di essere in grado di registrare condizionatamente? In altre parole, vorrei poter ottenere i log di traccia solo quando gli utenti specifici fanno una richiesta. Dato che non conosco in anticipo quali saranno gli utenti interessati, non posso semplicemente codificare temporaneamente i nomi utente.

Modificare:

Penso di aver bisogno di essere un po ‘più chiaro. Posso facilmente aggiungere condizioni alle mie dichiarazioni di registro. Per esempio

Logger logger = Logger.getLogger("foo"); String usernameFilter = "piglet"; String username = request.getParameter("username"); logger.setLevel(usernameFilter.equals(username) ? Level.TRACE : Level.INFO); if (logger.isTraceEnabled()) { logger.trace("blah blah blah"); } 

La difficoltà sta modificando dynamicmente la condizione che imposta il livello del registro. In altre parole, nell’esempio sopra, come posso impostare il valore di usernameFilter, a parte l’hard-coding.

Si desidera esaminare i contesti diagnostici nidificati oi contesti diagnostici mappati in log4j o slf4j. Un NDC / MDC consente di inserire dati nella sessione che possono essere filtrati da log4j.

Quindi definiresti il ​​nome utente da inserire nel NDC e quindi puoi modificare log4j.properties per modificare il livello di registrazione per utenti specifici.

Un MDC utilizza una mappa, mentre un NDC si basa su un principio di stack. Se stai usando slf4j , puoi persino creare file di registro separati a seconda delle informazioni nel tuo MDC.

Ad esempio, lo abbiamo fatto quando gli utenti hanno effettuato l’accesso a un sito Web. Volevamo tracciare ciò che un particolare utente stava facendo (in modo retrospettivo), quindi abbiamo aggiunto il nome utente e l’ID di sessione all’NDC, e quindi potremmo postare un filtro su questi.

Il codice era simile al seguente:

 public class LoggingFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { MDC.put("username", session.getParameter("username")); // or where ever t is stored chain.doFilter(request, response); } } 

Nel tuo log4j.xml, questo filtro si basa sull’utente:

                

% X {chiave} restituisce il valore di MDC.get (chiave) in un MDC. Se si desidera un filtro più complesso, è ansible estenderlo manualmente e osservare personalmente i valori nell’MDC.

La risposta di Matthew Farwell (usare MDC) è quella che ha funzionato per me e menziona la scrittura del proprio filtro. Il mio bisogno era di hide i messaggi di registrazione in alcuni casi. In particolare, abbiamo una chiamata di controllo sanitario che viene colpita molto più frequentemente rispetto al tipico utilizzo da parte dell’utente e stava riempiendo inutilmente i registri. La soluzione di Matthew non si adatta alla mia situazione perché richiede di aggiungere MDC all’output di registro effettivo. Voglio solo utilizzare MDC per il filtraggio, quindi ho esteso org.apache.log4j.spi.Filter con la seguente class:

 /** * Log4J filter that stops certain log messages from being logged, based on a * value in the MDC (See Log4J docs). */ public class Log4JMDCFilter extends Filter { private String keyToMatch; private String valueToMatch; private boolean denyOnMatch = true; /** * {@inheritDoc} */ public int decide(LoggingEvent event) { if (keyToMatch != null && valueToMatch != null && valueToMatch.equals(event.getMDC(keyToMatch))) { return denyOnMatch ? DENY : ACCEPT; } return denyOnMatch ? ACCEPT : DENY; } /** * The key on which to filter. * * @return key on which to filter */ public String getKeyToMatch() { return keyToMatch; } /** * Sets the key on which to filter. * * @param keyToMatch key on which to filter */ public void setKeyToMatch(String keyToMatch) { this.keyToMatch = keyToMatch; } /** * Gets the value to match. * * @return the value to match. */ public String getValueToMatch() { return valueToMatch; } /** * Sets the value to match. * * @param valueToMatch the value to match. */ public void setValueToMatch(String valueToMatch) { this.valueToMatch = valueToMatch; } /** * Returns true if the log message should not be logged if a match is found. * * @return true if the log message should not be logged if a match is found. */ public boolean isDenyOnMatch() { return denyOnMatch; } /** * Set this to "true" if you do not want log messages that match the given * key/value to be logged. False if you only want messages that match to be * logged. * * @param denyOnMatch "true" if you do not want log messages that match the * given key/value to be logged. False if you only want messages that * match to be logged. */ public void setDenyOnMatch(String denyOnMatch) { this.denyOnMatch = Boolean.valueOf(denyOnMatch).booleanValue(); } } 

Utilizza il seguente snippet log4j.xml per triggersre il filtro (“HEALTHCHECK” è la chiave e “true” è il valore su cui sto filtrando):

       

Quindi, ovunque tu voglia contrassegnare per il filtro, inserisci un codice come questo:

 MDC.put("HEALTHCHECK", "true"); try { // do healthcheck stuff that generates unnecessary logs } finally { MDC.remove("HEALTHCHECK"); // not sure this is strictly necessary } 

Ho trovato questo articolo del blog molto utile. Questo può aiutarti a creare le condizioni per accedere ai tuoi utenti.

Faccio una soluzione alternativa come segue

Configare la destinazione del registro in log4j.xml come la seguente:

               

crea un metodo di registrazione del cliente che aggiunge il tag di destinazione [ trackfile ]

 private void logfile(String msg) { logger.info("trackfile: " + msg); } 

registra le tue informazioni usando il metodo sopra riportato:

 logfile("your log message") 

inserisci la descrizione dell'immagine qui