Share via


log_reduce_fl()

La funzione log_reduce_fl() trova modelli comuni in colonne testuali semistrutturate, ad esempio linee di log e raggruppa le righe in base ai modelli estratti. Restituisce una tabella di riepilogo contenente i modelli trovati ordinati in base alla rispettiva frequenza.

Prerequisiti

  • Il plug-in Python deve essere abilitato nel cluster. Questa operazione è necessaria per Python inline usato nella funzione .
  • Il plug-in Python deve essere abilitato nel database. Questa operazione è necessaria per Python inline usato nella funzione .

Sintassi

T|invokelog_reduce_fl(reduce_col [,use_logram [,use_drain [custom_regexes [,custom_regexes_policy [,delimitatori [,,similarity_th [,tree_depth [,trigram_th [,bigram_th ]]]]]]]]])

Altre informazioni sulle convenzioni di sintassi.

Parametri

La descrizione dei parametri seguente è un riepilogo. Per altre informazioni, vedere Altre informazioni sulla sezione algoritmo .

Nome Tipo Obbligatoria Descrizione
reduce_col string ✔️ Nome della colonna stringa a cui viene applicata la funzione.
use_logram bool Abilitare o disabilitare l'algoritmo Logram. Il valore predefinito è true.
use_drain bool Abilitare o disabilitare l'algoritmo Drain. Il valore predefinito è true.
custom_regexes dynamic Matrice dinamica contenente coppie di simboli di espressione regolare e di sostituzione da cercare in ogni riga di input e sostituita con il rispettivo simbolo corrispondente. Il valore predefinito è dynamic([]). La tabella regex predefinita sostituisce numeri, INDIRIZZI IP e GUID.
custom_regexes_policy string 'prepend', 'append' o 'replace'. Controlla se custom_regexes sono anteporte/accodate/sostituisci quelle predefinite. Il valore predefinito è 'prepend'.
Delimitatori dynamic Matrice dinamica contenente stringhe delimitatori. Il valore predefinito è dynamic([" "]), definendo lo spazio come unico delimitatore di caratteri singolo.
similarity_th real Soglia di somiglianza, utilizzata dall'algoritmo Drain. Aumentando similarity_th si ottengono cluster più perfezionati. Il valore predefinito è 0,5. Se Drain è disabilitato, questo parametro non ha alcun effetto.
tree_depth int L'aumento tree_depth migliora il runtime dell'algoritmo Drain, ma potrebbe ridurne l'accuratezza. Il valore predefinito è 4. Se Drain è disabilitato, questo parametro non ha alcun effetto.
trigram_th int La diminuzione trigram_th aumenta le probabilità di sostituzione dei token con caratteri jolly. Il valore predefinito è 10. Se Logram è disabilitato, questo parametro non ha alcun effetto.
bigram_th int Riducendo bigram_th aumentano le probabilità di sostituzione dei token con caratteri jolly. Il valore predefinito è 15. Se Logram è disabilitato, questo parametro non ha alcun effetto.

Altre informazioni sull'algoritmo

La funzione esegue più passaggi sulle righe da ridurre ai modelli comuni. L'elenco seguente illustra i passaggi:

  • Sostituzioni di espressioni regolari: in questo passaggio ogni riga viene confrontata in modo indipendente con un set di espressioni regolari e ogni espressione corrispondente viene sostituita da un simbolo di sostituzione. Le espressioni regolari predefinite sostituiscono indirizzi IP, numeri e GUID con /IP, GUID> e /<NUM>. <>< L'utente può anteporre/aggiungere più espressioni regolari a tali espressioni oppure sostituirlo con nuovi o elenchi vuoti modificando custom_regexes e custom_regexes_policy. Ad esempio, per sostituire numeri interi con <WNUM> impostato custom_regexes=pack_array('/^\d+$/', '<WNUM>'); per annullare il set di sostituzione delle espressioni regolari custom_regexes_policy='replace''. Per ogni riga, la funzione mantiene l'elenco delle espressioni originali (prima delle sostituzioni) da restituire come parametri dei token di sostituzione generici.

  • Tokenizzazione: analogamente al passaggio precedente, ogni riga viene elaborata in modo indipendente e suddivisa in token basati su un set di delimitatori. Ad esempio, per definire l'interruzione dei token in base a virgole, punti o punti e virgola imposta delimitatori=pack_array(',', '.', ';').

  • Applica algoritmo Logram: questo passaggio è facoltativo, use_logram in sospeso è true. È consigliabile usare Logram quando è necessaria una scalabilità elevata e quando i parametri possono essere visualizzati nei primi token della voce di log. OTOH, disabilitarlo quando le voci di log sono brevi, in quanto l'algoritmo tende a sostituire i token con caratteri jolly troppo spesso in questi casi. L'algoritmo Logram considera 3 tuple e 2 tuple di token. Se una tupla di 3 token è comune nelle righe di log (appare più di trigram_th volte), è probabile che tutti e tre i token facciano parte del modello. Se la tupla a 3 è rara, è probabile che contenga una variabile che deve essere sostituita da un carattere jolly. Per le rare tuple a 3, si considera la frequenza con cui appaiono 2 tuple contenute nella tupla a 3. Se una tupla a 2 è comune (viene visualizzata più di bigram_th volte), è probabile che il token rimanente sia un parametro e non parte del modello.
    L'algoritmo Logram è facile da parallelizzare. Richiede due passaggi sul corpus dei log: il primo per contare la frequenza di ogni tupla a 3 tupla e 2 tupla e la seconda per applicare la logica descritta in precedenza a ogni voce. Per parallelizzare l'algoritmo, è sufficiente partizionare le voci di log e unificare i conteggi di frequenza di ruoli di lavoro diversi.

  • Applica algoritmo di svuotamento: questo passaggio è facoltativo, use_drain in sospeso è true. Drain è un algoritmo di analisi dei log basato su un albero dei prefissi di profondità troncato. I messaggi di log vengono suddivisi in base alla lunghezza e per ogni lunghezza vengono usati i primi token tree_depth del messaggio di log per compilare un albero dei prefissi. Se non è stata trovata alcuna corrispondenza per i token di prefisso, viene creato un nuovo ramo. Se è stata trovata una corrispondenza per il prefisso, si cerca il modello più simile tra i modelli contenuti nella foglia dell'albero. La somiglianza dei criteri viene misurata in base al rapporto dei token non disorientati corrispondenti su tutti i token. Se la somiglianza del modello più simile è superiore alla soglia di somiglianza (il parametro similarity_th), la voce di log viene confrontata con il modello. Per questo modello, la funzione sostituisce tutti i token non corrispondenti in base ai caratteri jolly. Se la somiglianza del modello più simile è inferiore alla soglia di somiglianza, viene creato un nuovo modello contenente la voce di log.
    L'impostazione predefinita tree_depth è impostata su 4 in base al test di vari log. L'aumento di questa profondità può migliorare il runtime, ma potrebbe compromettere l'accuratezza dei modelli; decrescente è più accurato ma più lento, poiché ogni nodo esegue molti test di somiglianza più.
    In genere, Drain generalizza e riduce in modo efficiente i modelli (anche se è difficile parallelizzare). Tuttavia, poiché si basa su un albero dei prefissi, potrebbe non essere ottimale nelle voci di log contenenti parametri nei primi token. Questo problema può essere risolto nella maggior parte dei casi applicando prima Logram.

Definizione di funzione

È possibile definire la funzione incorporando il codice come funzione definita da query o creandola come funzione archiviata nel database, come indicato di seguito:

Definire la funzione usando l'istruzione let seguente. Non sono necessarie autorizzazioni.

Importante

Un'istruzione let non può essere eseguita autonomamente. Deve essere seguito da un'istruzione espressione tabulare. Per eseguire un esempio funzionante di log_reduce_fl(), vedere Esempio.

let log_reduce_fl=(tbl:(*), reduce_col:string,
              use_logram:bool=True, use_drain:bool=True, custom_regexes: dynamic = dynamic([]), custom_regexes_policy: string = 'prepend',
              delimiters:dynamic = dynamic(' '), similarity_th:double=0.5, tree_depth:int = 4, trigram_th:int=10, bigram_th:int=15)
{
    let default_regex_table = pack_array('(/|)([0-9]+\\.){3}[0-9]+(:[0-9]+|)(:|)', '<IP>', 
                                         '([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})', '<GUID>', 
                                         '(?<=[^A-Za-z0-9])(\\-?\\+?\\d+)(?=[^A-Za-z0-9])|[0-9]+$', '<NUM>');
    let kwargs = bag_pack('reduced_column', reduce_col, 'delimiters', delimiters,'output_column', 'LogReduce', 'parameters_column', '', 
                          'trigram_th', trigram_th, 'bigram_th', bigram_th, 'default_regexes', default_regex_table, 
                          'custom_regexes', custom_regexes, 'custom_regexes_policy', custom_regexes_policy, 'tree_depth', tree_depth, 'similarity_th', similarity_th, 
                          'use_drain', use_drain, 'use_logram', use_logram, 'save_regex_tuples_in_output', True, 'regex_tuples_column', 'RegexesColumn', 
                          'output_type', 'summary');
    let code = ```if 1:
        from log_cluster import log_reduce
        result = log_reduce.log_reduce(df, kargs)
    ```;
    tbl
    | extend LogReduce=''
    | evaluate python(typeof(Count:int, LogReduce:string, example:string), code, kwargs)
};
// Write your query to use the function here.

Esempio

Nell'esempio seguente viene usato l'operatore invoke per eseguire la funzione. In questo esempio vengono usati i log di file system distribuiti da Apache Hadoop.

Per usare una funzione definita da query, richiamarla dopo la definizione di funzione incorporata.

let log_reduce_fl=(tbl:(*), reduce_col:string,
              use_logram:bool=True, use_drain:bool=True, custom_regexes: dynamic = dynamic([]), custom_regexes_policy: string = 'prepend',
              delimiters:dynamic = dynamic(' '), similarity_th:double=0.5, tree_depth:int = 4, trigram_th:int=10, bigram_th:int=15)
{
    let default_regex_table = pack_array('(/|)([0-9]+\\.){3}[0-9]+(:[0-9]+|)(:|)', '\<IP>', 
                                         '([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})', '<GUID>', 
                                         '(?<=[^A-Za-z0-9])(\\-?\\+?\\d+)(?=[^A-Za-z0-9])|[0-9]+$', '\<NUM>');
    let kwargs = bag_pack('reduced_column', reduce_col, 'delimiters', delimiters,'output_column', 'LogReduce', 'parameters_column', '', 
                          'trigram_th', trigram_th, 'bigram_th', bigram_th, 'default_regexes', default_regex_table, 
                          'custom_regexes', custom_regexes, 'custom_regexes_policy', custom_regexes_policy, 'tree_depth', tree_depth, 'similarity_th', similarity_th, 
                          'use_drain', use_drain, 'use_logram', use_logram, 'save_regex_tuples_in_output', True, 'regex_tuples_column', 'RegexesColumn', 
                          'output_type', 'summary');
    let code = ```if 1:
        from log_cluster import log_reduce
        result = log_reduce.log_reduce(df, kargs)
    ```;
    tbl
    | extend LogReduce=''
    | evaluate python(typeof(Count:int, LogReduce:string, example:string), code, kwargs)
};
//
// Finding common patterns in HDFS logs, a commonly used benchmark for log parsing
//
HDFS_log
| take 100000
| invoke log_reduce_fl(reduce_col="data")

Output

Conteggio LogReduce Esempio
55356 081110 <NUM NUM><> INFO dfs. FSNamesystem: BLOCK* NameSystem.delete: blk_<NUM> viene aggiunto al valore invalidSet di <IP> 081110 220623 26 INFO dfs. FSNamesystem: BLOCK* NameSystem.delete: blk_1239016582509138045 viene aggiunto a invalidSet 10.251.123.195:50010
10278 081110 <NUM NUM><> INFO dfs. FSNamesystem: BLOCK* NameSystem.addStoredBlock: blockMap aggiornato: <IP> viene aggiunto a blk_NUM> size <NUM> 081110 215858< 27 INFO dfs. FSNamesystem: BLOCK* NameSystem.addStoredBlock: blockMap aggiornato: 10.250.11.85:50010 viene aggiunto a blk_5080254298708411681 dimensioni 67108864
10256 081110 <NUM NUM><> INFO dfs. DataNode$PacketResponder: PacketResponder <NUM for block blk_NUM> terminando 081110 215858<> 15496 INFO dfs. DataNode$PacketResponder: PacketResponder 2 per il blocco blk_-7746692545918257727 terminazione
10256 081110 <NUM NUM><> INFO dfs. DataNode$PacketResponder: blocco ricevuto blk_NUM di dimensioni <NUM>> da <IP> 081110 215858< 15485 INFO dfs. DataNode$PacketResponder: blocco ricevuto blk_5080254298708411681 di dimensioni 67108864 da /10.251.43.21
9140 081110 <NUM NUM><> INFO dfs. DataNode$DataXceiver: blocco di ricezione blk_NUM> src: IP dest: <<IP>> 081110 215858< 15494 INFO dfs. DataNode$DataXceiver: Ricezione di blocchi blk_-7037346755429293022 src: /10.251.43.21:45933 dest: /10.251.43.21:50010
3047 081110 <NUM NUM><> INFO dfs. FSNamesystem: BLOCK* NameSystem.allocateBlock: /user/root/rand3/temporary/task<><> NUM NUMm<> NUM_<>NUM/part-NUM<>. <> 081110 215858 26 INFO dfs. FSNamesystem: BLOCK NameSystem.allocateBlock: /user/root/rand3/_temporary/task_200811101024_0005_m_001805_0/part-01805. blk-7037346755429293022
1402 081110 <NUM NUM>>< INFO <>: <> blocco blk_NUM>>> << 081110 215957< 15556 INFO dfs. DataNode$DataTransfer: 10.250.15.198:50010:Blocco trasmesso blk_-3782569120714539446 a /10.251.203.129:50010
177 081110 <NUM NUM>>< INFO <>: <><>> <<*> 081110 215859 13 INFO dfs. DataBlockScanner: verifica riuscita per blk_-7244926816084627474
36 081110 <NUM NUM>>< INFO <>: <>>> <<per blocco <*> 081110 215924 15636 INFO dfs. DataNode$BlockReceiver: ricezione di pacchetti vuoti per il blocco blk_3991288654265301939
12 081110 <NUM NUM><> INFO dfs. FSNamesystem: BLOCK* <>><> <> <> <><><> <081110 215953 19 INFO dfs. FSNamesystem: BLOCK* ask 10.250.15.198:50010 per replicare blk_-3782569120714539446 ai datanode 10.251.203.129:50010
12 081110 <NUM NUM>>< INFO <>: <>><>> <> <<blocco blk_NUM>>> << 081110 215955< 18 INFO dfs. DataNode: 10.250.15.198:50010 Thread iniziale per trasferire il blocco blk_-3782569120714539446 a 10.251.203.129:50010
12 081110 <NUM NUM><> INFO dfs. DataNode$DataXceiver: blocco ricevuto blk_NUM src: IP dest: <<IP>> di dimensioni <NUM>> 081110 215957< 15226 INFO dfs. DataNode$DataXceiver: blocco ricevuto blk_-3782569120714539446 src: /10.250.15.198:51013 dest: /10.250.15.198:50010 di dimensioni 14474705
6 081110 <NUM NUM><><> dfs. FSNamesystem: BLOCK NameSystem.addStoredBlock: <>> <<><> <<> <> <>>size <NUM> 0811110 215924 27 WARN dfs. FSNamesystem: BLOCK* NameSystem.addStoredBlock: richiesta addStoredBlock ridondante ricevuta per blk_2522553781740514003 10.251.202.134:50010 dimensioni 67108864
6 081110 <NUM NUM><> INFO dfs. DataNode$DataXceiver: <>> <<> <<>>: <><><> <>> <081110 215936 15714 INFO dfs. DataNode$DataXceiver: writeBlock blk_720939897861061328 ricevuto eccezione java.io.IOException: Impossibile leggere dal flusso
3 081110 <NUM NUM><> INFO dfs. FSNamesystem: BLOCK* NameSystem.addStoredBlock: <>><> <<> <<> <>> size <NUM><>><> <<><> <<> <>>. 081110 220635 28 INFO dfs. FSNamesystem: BLOCK NameSystem.addStoredBlock: addStoredBlock richiesta ricevuta per blk_-81196479666306310 10.250.17.177:50010 dimensioni 53457811 Ma non appartiene a alcun file.
1 081110 <NUM NUM>>><<> <: >. <><<>> <> <><> <><> <><> <>< 081110 220631 19 WARN dfs. FSDataset: errore imprevisto che tenta di eliminare il blocco blk_-2012154052725261337. BlockInfo non trovato in volumeMap.

Questa funzionalità non è supportata.