Fluent-bit Parser for logback JSON
... / Fluent-bit Parser for log...
BMPCreated with Sketch.BMPZIPCreated with Sketch.ZIPXLSCreated with Sketch.XLSTXTCreated with Sketch.TXTPPTCreated with Sketch.PPTPNGCreated with Sketch.PNGPDFCreated with Sketch.PDFJPGCreated with Sketch.JPGGIFCreated with Sketch.GIFDOCCreated with Sketch.DOC Error Created with Sketch.
question

Fluent-bit Parser for logback JSON

Par
JohannR3
Créé le 2022-10-04 08:38:27 (edited on 2024-09-04 12:47:35) dans Logs & Metrics-old

Bonjour,

J'aurais besoin d'aide svp.

J'ai une application Spring Boot avec le logger logback. Les logs sont écrites sous format JSON.
Je remonte les logs vers Graylog avec Fluent-bit.

Mais le contenu de mes logs n'est pas parsé, et se retrouve dans le champ message sous Graylog.

Voici ma config logback.xml
image

Voici ma config Fluent-bit :
> apiVersion: v1
> kind: ConfigMap
> metadata:
> name: fluent-bit-config
> namespace: logging
> labels:
> k8s-app: fluent-bit
> data:
> # Configuration files: server, input, filters and output
> # ======================================================
> fluent-bit.conf: |
> SERVICE]
> Flush 1
> Log_Level info
> Daemon off
> Parsers_File parsers.conf
> HTTP_Server On
> HTTP_Listen 0.0.0.0
> HTTP_Port 2020

> @INCLUDE input-kubernetes.conf
> @INCLUDE filter-kubernetes.conf
> @INCLUDE output-ldp.conf

> input-kubernetes.conf: |
> [INPUT]
> Name tail
> Tag kube.*
> Path /var/log/containers/*bako-admin*.log
> Parser json
> DB /var/log/flb_kube.db
> Mem_Buf_Limit 5MB
> Skip_Long_Lines On
> Refresh_Interval 10

> filter-kubernetes.conf: |
> [FILTER]
> Name kubernetes
> Match kube.*
> Kube_URL https://kubernetes.default.svc:443
> Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
> Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token
> Kube_Tag_Prefix kube.var.log.containers.
> Merge_Log Off
> Merge_Log_Key log_processed
> K8S-Logging.Parser On
> K8S-Logging.Exclude Off
> [FILTER]
> Name record_modifier
> Match *
> Record X-OVH-TOKEN ${FLUENT_LDP_TOKEN}
> [FILTER]
> Name record_modifier
> Match *
> Record fluent-bit-host ${HOSTNAME}
> [FILTER]
> Name nest
> Match *
> Wildcard pod_name
> Operation lift
> Nested_under kubernetes
> Add_prefix kubernetes_
> [FILTER]
> Name modify
> Match *
> Copy kubernetes_pod_name host
> [FILTER]
> Name modify
> Match *
> Rename log short_message

> output-ldp.conf: |
> [OUTPUT]
> Name gelf
> Match *
> Host ${FLUENT_LDP_HOST}
> Port ${FLUENT_LDP_PORT}
> Mode tls
> tls On
> Compress False

> parsers.conf: |
> [PARSER]
> Name apache
> Format regex
> Regex ^(?[^ ]*) [^ ]* (?[^ ]*) \[(?[^\]]*)\] "(?\S+)(?: +(?[^\"]*?)(?: +\S*)?)?" (?[^ ]*) (?[^ ]*)(?: "(?[^\"]*)" "(?[^\"]*)")?$
> Time_Key time
> Time_Format %d/%b/%Y:%H:%M:%S %z

> [PARSER]
> Name apache2
> Format regex
> Regex ^(?[^ ]*) [^ ]* (?[^ ]*) \[(?[^\]]*)\] "(?\S+)(?: +(?[^ ]*) +\S*)?" (?[^ ]*) (?[^ ]*)(?: "(?[^\"]*)" "(?[^\"]*)")?$
> Time_Key time
> Time_Format %d/%b/%Y:%H:%M:%S %z

> [PARSER]
> Name apache_error
> Format regex
> Regex ^\[[^ ]* (?[^\]]*)\] \[(?[^\]]*)\
\])?( \[client (?[^\]]*)\])? (?.*)$

> [PARSER]
> Name nginx
> Format regex
> Regex ^(?[^ ]*) (?[^ ]*) (?[^ ]*) \[(?[^\]]*)\] "(?\S+)(?: +(?[^\"]*?)(?: +\S*)?)?" (?[^ ]*) (?[^ ]*)(?: "(?[^\"]*)" "(?[^\"]*)")?$
> Time_Key time
> Time_Format %d/%b/%Y:%H:%M:%S %z

> [PARSER]
> Name json
> Format json
> Time_Key time
> Time_Format %d/%b/%Y:%H:%M:%S %z
> Decode_Field_As json message

> [PARSER]
> Name docker
> Format json
> Time_Key time
> Time_Format %Y-%m-%dT%H:%M:%S.%L
> Time_Keep On

> [PARSER]
> Name syslog
> Format regex
> Regex ^\<(?[0-9]+)\>(?[^ ]* {1,2}[^ ]* [^ ]*) (?[^ ]*) (?[a-zA-Z0-9_\/\.\-]*)(?:\[(?[0-9]+)\])?(?:[^\:]*\:)? *(?.*)$
> Time_Key time
> Time_Format %b %d %H:%M:%S



Qu'est ce que j'ai oublié ?

Merci pour votre aide

Johann


2 réponses ( Latest reply on 2022-11-09 09:24:48 Par
FabL
)

Bonjour,

Et merci pour votre utilisation de Logs Data Platform.
Désolé pour le délai tardif de réponse.

En effet votre configuration est correcte. Je dirais qu'il manque simplement l'operation **lift** afin que le JSON qui soit dans votre champ *message* soit mis au plus haut niveau. En effet le format GELF ne supporte que les JSONs de profondeur 1.

le filter LIFT ressemblerait à ceci pour vous :

[FILTER]
Name nest_log
Match *
Operation lift
Nested_under log
Ce filtre serait à remplacer à la place du filtre **modify** qui fait l'action suivante ` Rename log short_message ` afin qu'il puisse générer tous les champs. Le champ *log* disparaitra à ce moment là. Notez que vous pouvez ensuite positionner dans l'output **GELF**, l'option `Gelf_Short_Message_Key` à la valeur **message** afin que le champ message de votre log GELF soit le champ message. Cette option n'existait pas au moment de l'écriture de la documentation d'où son absence dans celle-ci.

La documentation officielle de fluent-bit détaille une partie de votre use case ici (càd la donnée utile est dans un objet imbriqué JSON) avec ces mêmes filtres et options :

https://docs.fluentbit.io/manual/pipeline/outputs/gelf

N'hésitez pas à nous dire si tout ça fonctionne ou non, on sera plus réactif pour itérer avec vous.

Happy logging

Babacar Diassé

Bonjour,

Désolé pour le délai de ma réponse, d'autres priorités...

J'ai enfin réussi à parser mes logs correctement.

Voici la configuration fluent-bit :
1) l'input :

input-kubernetes.conf: |
[INPUT]
Name tail
Tag kube.*
Path /var/log/containers/*your-log-filename*.log
Parser json
DB /var/log/flb_kube.db
Mem_Buf_Limit 5MB
Skip_Long_Lines On
Refresh_Interval 10

2) le parser :

parsers.conf: |
[PARSER]
Name json
Format json
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L
# IMPORTANT pour parser les logs applicatifs
Decode_Field_As json log

3) les filters

filter-kubernetes.conf: |
[FILTER]
Name kubernetes
Match kube.*
Kube_URL https://kubernetes.default.svc:443
Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token
Kube_Tag_Prefix kube.var.log.containers.
Merge_Log Off
Merge_Log_Key log_processed
K8S-Logging.Parser On
K8S-Logging.Exclude Off
[FILTER]
Name record_modifier
Match *
Record X-OVH-TOKEN ${FLUENT_LDP_TOKEN}
[FILTER]
Name record_modifier
Match *
Record fluent-bit-host ${HOSTNAME}
[FILTER]
Name nest
Match *
Wildcard pod_name
Operation lift
Nested_under kubernetes
Add_prefix kubernetes_
[FILTER]
Name modify
Match *
Copy kubernetes_pod_name host
[FILTER]
Name nest
Match *
Operation lift
# doit correspondre au champ log décodé par le parser
Nested_under log

l'output :

output-ldp.conf: |
# usefully to debug, log result in fluent-bit pods
# [OUTPUT]
# Name stdout
# Match *
[OUTPUT]
Name gelf
Match *
Host ${FLUENT_LDP_HOST}
Port ${FLUENT_LDP_PORT}
Mode tls
tls On
Compress False
# définit quel champ sera affiché dans graylog par défaut
Gelf_Short_Message_Key message


**Tips :**
Si votre app log un champ "level" "avec warn ou error, vous pouvez avoir une erreur de type :
`level is 'WARN', but should be in 0..7 or a syslog keyword`
La valeur ne correspond pas aux valeurs acceptées, cf https://en.wikipedia.org/wiki/Syslog#Severity_level

Dans ce cas, dans votre app, renommer le champ (ex: `_level`).


Merci.

Je teste maintenant le system d'alerting dans OVH pour recevoir des emails en cas d'erreurs.

Cdt,
Johann

Last question :
in the Log Data Platform, I created an Alert for a stream.
how to manage emails that received this alert ?

Hello @JohannR3,

Emails are sent to the address of the Nic-TECH associated to LDP account.
If you want to go further with alerting, we encourage you to read this: https://docs.ovh.com/fr/logs-data-platform/alerting/

Regards,

Bonjour à tous,

Hey merci pour vos contributions @BabacarD et @PierreD 😎!

@JohannR3 Je te remercie d'avoir répondu et d'avoir apporté la solution à ta propre demande.

Je clos le thread,

Bonne journée et bonne navigation à tous sur Community !

^FabL

Les réponses sont actuellement désactivées pour cette question.