Vantaggi della registrazione strutturata rispetto alla registrazione di base


110

Stiamo creando una nuova app e vorrei includere la registrazione strutturata. La mia configurazione ideale sarebbe qualcosa di simile Serilogal nostro codice C # e Bunyanal nostro JS. Questi si alimenterebbero fluentde poi potrebbero uscire a qualsiasi numero di cose, stavo pensando inizialmente elasticsearch + kibana. Abbiamo già un database MySQL, quindi a breve termine sono più interessato a ottenere l'installazione di Serilog + Bunyan e gli sviluppatori per usarlo e possiamo accedere a MySQL mentre impieghiamo un po 'più di tempo a portare fluentd e il resto.

Tuttavia, uno dei nostri programmatori più esperti preferirebbe semplicemente fare qualcosa di simile: log.debug("Disk quota {0} exceeded by user {1}", quota, user);usando log4nete quindi eseguendo istruzioni selezionate su MySQL come:SELECT text FROM logs WHERE text LIKE "Disk quota";

Detto questo, quale approccio è migliore e / o quali cose dobbiamo considerare quando si sceglie il tipo di sistema di registrazione?


Sono d'accordo con le modifiche apportate. Non sto tanto cercando di dimostrare qualcosa a qualcuno, ma sto cercando di capire i vantaggi e le differenze nella registrazione strutturata rispetto a quella di base. Nella mia mente, strutturato ci offre molta più flessibilità soprattutto nelle fonti dei registri e in che modo siamo in grado di visualizzare i loro dati. Al momento della mia comprensione, non sono in grado di spiegare perché la registrazione di base e la ricerca di MySQL sono migliori / peggiori della registrazione strutturata.
DTI-Matt

2
La registrazione strutturata di @DTI-Matt serilog è solo una registrazione di base, ma formatta solo gli oggetti che vi vengono stampati, cosa che potete fare voi stessi superando facilmente ToString. Un aspetto più importante è la configurazione e la gestione dei file di registro, non un modo di formattare una stringa su un altro, un altro è la prestazione. Se lo sviluppatore vuole usare log4net (che è una buona libreria di log), allora la tua scelta di serilog (che sembra interessante) è una di quelle "soluzioni alla ricerca di un problema".
gbjbaanb

@ DTI-Matt Guardando serilog sembra molto simile a log4net. log4net gestisce la creazione di registri strutturati su config. Non è necessario cercare i messaggi di registro poiché è possibile configurare e scrivere informazioni aggiuntive in una tabella. Configura anche log4net per fluentd tipstuff.org/2014/05/…
RubberChickenLeader

Fai attenzione, ci sono alcuni sciocchi che non comprendono l'idea delle domande concettuali qui. chiedendo la direzione delle applicazioni di database nel tentativo di ottenere un controllo sulle loro capacità ETL v. code ti darà alcuni downvotes gravi. Presumo che anche la tua domanda sarà sul tagliere.
user3916597

2
@gbjbaanb Serilog funziona allo stesso modo di log4net durante il rendering di eventi come testo, ma se si utilizza un formato strutturato per archiviare i registri, assocerà le proprietà denominate agli argomenti che vengono passati (ovvero per supportare la ricerca / filtro senza regex ecc. ) HTH!
Nicholas Blumhardt,

Risposte:


140

Ci sono due progressi fondamentali con l' approccio strutturato che non possono essere emulati usando i log di testo senza (a volte livelli estremi di) ulteriore sforzo.

Tipi di eventi

Quando scrivi due eventi con log4net come:

log.Debug("Disk quota {0} exceeded by user {1}", 100, "DTI-Matt");
log.Debug("Disk quota {0} exceeded by user {1}", 150, "nblumhardt");

Questi produrranno un testo simile:

Disk quota 100 exceeded by user DTI-Matt
Disk quota 150 exceeded by user nblumhardt

Ma per quanto riguarda l'elaborazione automatica, sono solo due righe di testo diverso.

Potresti voler trovare tutti gli eventi "quota disco superata", ma il caso semplicistico di cercare eventi like 'Disk quota%'cadrà non appena si verifica un altro evento simile a:

Disk quota 100 set for user DTI-Matt

La registrazione del testo elimina le informazioni che abbiamo inizialmente sulla fonte dell'evento e questo deve essere ricostruito quando si leggono i registri di solito con espressioni di corrispondenza sempre più elaborate.

Al contrario, quando scrivi i seguenti due eventi Serilog :

log.Debug("Disk quota {Quota} exceeded by user {Username}", 100, "DTI-Matt");
log.Debug("Disk quota {Quota} exceeded by user {Username}", 150, "nblumhardt");

Questi producono un output di testo simile alla versione log4net, ma dietro le quinte, il "Disk quota {Quota} exceeded by user {Username}" modello di messaggio viene portato da entrambi gli eventi.

Con un sink appropriato, è possibile in seguito scrivere query where MessageTemplate = 'Disk quota {Quota} exceeded by user {Username}'e ottenere esattamente gli eventi in cui è stata superata la quota del disco.

Non è sempre conveniente archiviare l'intero modello di messaggio con ogni evento di registro, quindi alcuni sink eseguono l'hash del modello di messaggio in un EventTypevalore numerico (ad esempio 0x1234abcd), oppure è possibile aggiungere un enricher alla pipeline di registrazione per farlo da soli .

È più sottile della successiva differenza di seguito, ma è enormemente potente quando si tratta di grandi volumi di log.

Dati strutturati

Ancora una volta, considerando i due eventi sull'utilizzo dello spazio su disco, potrebbe essere abbastanza semplice utilizzare i log di testo per eseguire query per un determinato utente like 'Disk quota' and like 'DTI-Matt'.

Ma la diagnostica di produzione non è sempre così semplice. Immagina che sia necessario trovare eventi in cui la quota del disco superata fosse inferiore a 125 MB?

Con Serilog, questo è possibile nella maggior parte dei lavandini usando una variante di:

Quota < 125

Costruire questo tipo di query da un'espressione regolare è possibile, ma diventa stancante e di solito finisce per essere l'ultima misura.

Ora aggiungi a questo un tipo di evento:

Quota < 125 and EventType = 0x1234abcd

Inizierai a vedere qui come queste funzionalità si combinano in modo semplice per far sembrare il debug della produzione con i log un'attività di sviluppo di prima classe.

Un ulteriore vantaggio, forse non così facile da prevenire in anticipo, ma una volta che il debug della produzione è stato rimosso dalla terra degli hacker regex, gli sviluppatori iniziano a valutare molto di più i log e ad esercitare più attenzione e considerazione quando li scrivono. Registri migliori -> applicazioni di migliore qualità -> maggiore felicità.


4
amo questa risposta. scritto molto bene e per qualche motivo non riesco a spiegarmi, mi tiene al limite del mio posto.
jokab

16

Quando si raccolgono registri per l'elaborazione, che si tratti dell'analisi in alcuni database e / o della ricerca in un secondo momento nei registri elaborati, l'utilizzo della registrazione strutturata rende parte dell'elaborazione più semplice / efficiente. Il parser può sfruttare la struttura nota ( ad es. JSON, XML, ASN.1, qualunque cosa) e utilizzare macchine a stati per l'analisi, al contrario delle espressioni regolari (che possono essere computazionalmente costose (relativamente) da compilare ed eseguire). L'analisi del testo in formato libero, come quello suggerito dal collega, tende a fare affidamento su espressioni regolari e a fare in modo che il testo non cambi . Ciò può rendere piuttosto fragile l' analisi del testo in formato libero ( ovvero l' analisi è strettamente accoppiata al testo esatto nel codice).

Considera anche il caso di ricerca / ricerca, ad esempio :

SELECT text FROM logs WHERE text LIKE "Disk quota";

LIKEle condizioni richiedono confronti con ogni textvalore di riga; ancora una volta, questo è relativamente costoso dal punto di vista computazionale, in particolare quando vengono utilizzati i caratteri jolly:

SELECT text FROM logs WHERE text LIKE "Disk %";

Con la registrazione strutturata, il messaggio di registro relativo agli errori del disco potrebbe apparire così in JSON:

{ "level": "DEBUG", "user": "username", "error_type": "disk", "text": "Disk quota ... exceeded by user ..." }

I campi di questo tipo di struttura possono essere mappati abbastanza facilmente ad es. Nomi di colonne di tabelle SQL, il che significa che la ricerca può essere più specifica / granulare:

SELECT user, text FROM logs WHERE error_type = "disk";

Puoi posizionare gli indici sulle colonne di cui ti aspetti di cercare / cercare frequentemente i valori, purché non utilizzi LIKEclausole per tali valori di colonna . Più è possibile suddividere il messaggio di registro in categorie specifiche, più mirato è possibile effettuare la ricerca. Ad esempio, oltre al error_typecampo / colonna nell'esempio sopra, potresti anche essere "error_category": "disk", "error_type": "quota"o meno.

La struttura più che avete nelle vostre messaggi di log, i sistemi più vostro di analisi / ricerca (ad esempio fluentd, elasticsearch, kibana) possono usufruire di quella struttura, e svolgere i loro compiti con maggiore velocità e meno CPU / memoria.

Spero che sia di aiuto!


1
+1 Vuoi aggiungere che non si tratta solo di velocità ed efficienza. La pertinenza dei risultati della ricerca sarà molto più elevata quando si utilizza la registrazione strutturata e quindi le "query strutturate". Senza quella ricerca di qualsiasi parola che si presenti in contesti diversi ti darà tonnellate di successi irrilevanti.
Marjan Venema

1
+1 anche da me, penso che questo inchioda. Aggiunta una formulazione leggermente diversa di seguito, per espandere anche il caso dei tipi di eventi.
Nicholas Blumhardt,

8

Non troverai molti vantaggi dalla registrazione strutturata quando la tua app crea alcune centinaia di messaggi di registro al giorno. Lo farai sicuramente quando hai qualche centinaio di messaggi di log al secondo provenienti da diverse app distribuite.

Relativamente, l'installazione in cui i messaggi di registro finiscono nello stack ELK è appropriata anche per la scala in cui la registrazione in SQL diventa un collo di bottiglia.

Ho visto la configurazione della "registrazione e ricerca di base" con SQL select .. likee regexps spinti ai suoi limiti quando cade a pezzi - ci sono falsi positivi, omissioni, codice filtro orribile con bug noti che è difficile da mantenere e nessuno vuole toccare, nuovi messaggi di registro che non seguono i presupposti del filtro, riluttanza a toccare le istruzioni di registrazione nel codice per non interrompere i rapporti, ecc.

Quindi stanno emergendo diversi pacchetti software per affrontare meglio questo problema. C'è Serilog, ho sentito che il team NLog lo sta guardando , e abbiamo scritto StructuredLogging.Jsonper Nlog , vedo anche che le nuove astrazioni di logging core ASP.Net "consentono ai provider di log di implementare ... il log strutturato".

Un esempio con StructuredLogging. Si accede a un logger NLog in questo modo:

logger.ExtendedError("Order send failed", new { OrderId = 1234, RestaurantId = 4567 } );

Questi dati strutturati vanno al kibana. Il valore 1234è memorizzato nel OrderIdcampo della voce di registro. È quindi possibile eseguire la ricerca utilizzando la sintassi della query kibana, ad esempio tutte le voci di registro in cui @LogType:nlog AND Level:Error AND OrderId:1234.

Messagee OrderIdora sono solo campi che possono essere cercati per corrispondenze esatte o inesatte di cui hai bisogno o aggregati per conteggi. Questo è potente e flessibile.

Dalle best practice di StructuredLogging :

Il messaggio registrato dovrebbe essere lo stesso ogni volta. Dovrebbe essere una stringa costante, non una stringa formattata per contenere valori di dati come ID o quantità. Quindi è facile da cercare.

Il messaggio registrato deve essere distinto, cioè non uguale al messaggio prodotto da un'istruzione di registro non correlata. Quindi la ricerca non corrisponde anche a cose non correlate.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.