J'ai un fichier journal généré personnalisé qui a le modèle suivant:
[2014-03-02 17:34:20] - 127.0.0.1|ERROR| E:\xampp\htdocs\test.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-lignes est terminé, cette ligne est supprimé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 }
}
Le résultat pour le champ content est: The error message goes here ; array (
Mon problème est que je veux stocker le reste du champ multiligne dans le contenu:
The error message goes here ; array (
'create' =>
array (
'key1' => 'value1',
'key2' => 'value2',
'key3' => 'value3'
),
)
Je peux donc supprimer le champ de message plus tard.
Le champ @ message contient tout l'événement multiligne, j'ai donc essayé la fonction mutate filter, avec la fonction replace là-dessus, mais je ne peux tout simplement pas pour le faire fonctionner :(.
Je ne comprends pas la façon de travailler du filtre multiligne, si quelqu'un pouvait faire la lumière là-dessus, ce serait vraiment apprécié.
Merci,
Abdou.
J'ai parcouru le code source et découvert que:
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 }
}
À votre santé,
Abdou
la gestion des groks et des multilignes est mentionnée dans ce numéro https://logstash.jira.com/browse/LOGSTASH-509
Ajoutez simplement "(? M)" devant votre grok regex et vous n'aurez pas besoin de mutation. Exemple de problème:
pattern => "(?m)<%{POSINT:syslog_pri}>(?:%{SPACE})%{GREEDYDATA:message_remainder}"
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 remplacer le\n par un autre caractère, dit un espace vide.
mutate {
gsub => ['message', "\n", " "]
}
Ensuite, grok pattern peut analyser le message. Par exemple:
"content" => "The error message goes here ; array ( 'create' => array ( 'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3' ), )"
Le problème n'est-il pas simplement la commande des filtres. L'ordre est très important de consigner la cachette. Vous n'avez pas besoin d'une autre ligne pour indiquer que vous avez terminé la sortie de la ligne de journal multiligne. Assurez-vous simplement que le filtre multiligne apparaît avant le grok (voir ci-dessous)
P.s. J'ai réussi à analyser correctement une ligne de journal multiligne où xml a été ajouté à la fin de la ligne de journal et il s'étendait sur plusieurs lignes et j'ai toujours un objet XML propre et agréable dans ma variable équivalente de contenu (nommée xmlrequest ci-dessous). Avant de dire quoi que ce soit sur la journalisation du xml dans les journaux ... Je sais ... ce n'est pas idéal ... mais c'est pour 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"
}
}