Comment traiter une entrée de journal multiligne avec un filtre logstash?

Contexte:

j'ai un fichier journal personnalisé qui a le motif suivant:

[2014-03-02 17:34:20] - 127.0.0.1|ERROR| E:xampphtdocstest.php|123|subject|The error message goes here ; array (
  'create' => 
  array (
    'key1' => 'value1',
    'key2' => 'value2',
    'key3' => 'value3'
  ),
)
[2014-03-02 17:34:20] - 127.0.0.1|DEBUG| flush_multi_line

La deuxième entrée [2014-03-02 17:34:20] - 127.0.0.1|DEBUG| flush_multi_line est une ligne fictive, juste pour faire savoir à logstash que l'événement multi-ligne est terminé, cette ligne est abandonnée plus tard.

mon fichier de configuration est le suivant :

input {
  stdin{}
}

filter{
  multiline{
      pattern => "^["
      what => "previous"
      negate=> true
  }
  grok{
    match => ['message',"[.+] - %{IP:ip}|%{LOGLEVEL:loglevel}"]
  }

  if [loglevel] == "DEBUG"{ # the event flush  line
    drop{}
  }else if [loglevel] == "ERROR"  { # the first line of multievent
    grok{
      match => ['message',".+|.+| %{PATH:file}|%{NUMBER:line}|%{WORD:tag}|%{GREEDYDATA:content}"] 
    }
  }else{ # its a new line (from the multi line event)
    mutate{
      replace => ["content", "%{content} %{message}"] # Supposing each new line will override the message field
    }
  }  
}

output {
  stdout{ debug=>true }
}

la sortie pour contenu le champ est:The error message goes here ; array (

Problème:

Mon problème est que je veux stocker le reste de le champ multiligne vers contenu:

The error message goes here ; array (
  'create' => 
  array (
    'key1' => 'value1',
    'key2' => 'value2',
    'key3' => 'value3'
  ),
)

pour que je puisse supprimer le champ de message plus tard.

@message le champ contient tout l'événement multiligne donc j'ai essayé le muter filtre, le remplacer fonctionnez là-dessus, mais je ne peux pas le faire fonctionner :( .

Je ne comprends pas la façon de travailler du filtre multiligne, si quelqu'un pouvait apporter un peu de lumière là-dessus, ce serait vraiment apprécier.

Merci,

Abdou.

27
demandé sur baudsp 2014-03-04 17:10:04

4 réponses

j'ai parcouru le code source et j'ai découvert que:

  • multiligne filtre annuler tous les événements qui sont considéré comme un suivi de l'attente de l'événement, puis ajoutez cette ligne au champ de message original, ce qui signifie que les filtres qui sont après le filtre multiligne ne s'appliqueront pas dans ce cas
  • Le seul événement qui ne sera jamais passer le filtre, est celui qui est considéré comme un nouveau ( quelque chose que commençant par [ dans mon cas )

voici le code de travail:

input {
   stdin{}
}  

filter{
      if "|ERROR|" in [message]{ #if this is the 1st message in many lines message
      grok{
        match => ['message',"\[.+\] - %{IP:ip}\|%{LOGLEVEL:loglevel}\| %{PATH:file}\|%{NUMBER:line}\|%{WORD:tag}\|%{GREEDYDATA:content}"]
      }

      mutate {
        replace => [ "message", "%{content}" ] #replace the message field with the content field ( so it auto append later in it )
        remove_field => ["content"] # we no longer need this field
      }
    }

    multiline{ #Nothing will pass this filter unless it is a new event ( new [2014-03-02 1.... )
        pattern => "^\["
        what => "previous"
        negate=> true
    }

    if "|DEBUG| flush_multi_line" in [message]{
      drop{} # We don't need the dummy line so drop it
    }
}

output {
  stdout{ debug=>true }
}

santé,

Abdou

12
répondu emonik 2014-03-05 11:51:51

Le grok et la manipulation multiligne sont mentionnés dans ce numérohttps://logstash.jira.com/browse/LOGSTASH-509

Simplement ajouter "(?m) " devant votre grok regex et vous n'aurez pas besoin de mutation. Exemple tiré du numéro:

pattern => "(?m)<%{POSINT:syslog_pri}>(?:%{SPACE})%{GREEDYDATA:message_remainder}"
10
répondu sbange 2014-10-22 07:51:07

le filtre multiligne ajoutera le "\n " au message. Par exemple:

"[2014-03-02 17:34:20] - 127.0.0.1|ERROR| E:\xampp\htdocs\test.php|123|subject|The error message goes here ; array (\n  'create' => \n  array (\n    'key1' => 'value1',\n    'key2' => 'value2',\n    'key3' => 'value3'\n  ),\n)"

cependant, le filtre grok ne peut pas analyser le "\N". Par conséquent, vous devez substituer le \N à un autre caractère, dit, espace vide.

mutate {
    gsub => ['message', "\n", " "]
}

alors, grok pattern peut analyser le message. Par exemple:

 "content" => "The error message goes here ; array (   'create' =>    array (     'key1' => 'value1',     'key2' => 'value2',     'key3' => 'value3'   ), )"
5
répondu Ben Lim 2014-03-05 09:14:33

N'est pas la question tout simplement de la commande des filtres. L'ordre est très important pour la cachette. Vous n'avez pas besoin d'une autre ligne pour indiquer que vous avez terminé la sortie multiligne ligne de journal. Assurez-vous juste que le filtre multiligne apparaît en premier avant le grok (voir ci-dessous)

P. S. J'ai réussi à analyser une ligne de log multiligne amende où xml a été ajouté à la fin de la ligne de log et il couvrait plusieurs lignes et j'ai quand même un objet xml propre agréable dans mon contenu de la variable équivalente (appelé xmlrequest dessous.) Avant de dire quoi que ce soit à propos de la journalisation xml dans les journaux... Je sais... ses pas l'idéal... mais c'est un autre débat :)):

filter { 
multiline{
        pattern => "^\["
        what => "previous"
        negate=> true
    }

mutate {
    gsub => ['message', "\n", " "]
}

mutate {
    gsub => ['message', "\r", " "]
}

grok{
        match => ['message',"\[%{WORD:ONE}\] \[%{WORD:TWO}\] \[%{WORD:THREE}\] %{GREEDYDATA:xmlrequest}"]
    }

xml {
source => xmlrequest
remove_field => xmlrequest
target => "request"
  }
}
1
répondu Luis Pereira 2014-12-05 18:52:46