Filtrage des journaux OpenTelemetry
Le collecteur OpenTelemetry permet de filtrer les données de journal qu'il collecte de différentes manières. Ce document fournit des exemples de filtrage des journaux dans certains scénarios courants. Ces fonctions étant incluses uniquement dans le référentiel OpenTelemetry Collector Contrib, ces exemples requièrent cette version. Pour plus d'informations, consultez la documentation relative aux contributions du collecteur « OpenTelemetry ».
Filtrer les journaux en fonction de leur contenu
Le processeur de filtre accepte les expressions régulières qui sont appliquées au contenu des messages de journal. Tous les messages de journal qui correspondent à l'expression régulière indiquée sont supprimés et ne sont jamais transmis au destinataire à l'autre extrémité.
Exemples
Tous ces exemples suivent un modèle similaire. Une section filter doit être ajoutée au fichier de configuration d'opentelemetry-collector et ce filtre doit être inclus dans le pipeline logs/processors dans le même fichier. Si vous utilisez Helm pour installer le collecteur, la configuration se trouve dans la section config: du fichier values.yaml lors de l'installation.
Exclure les messages de journal contenant une sous-chaîne spécifique
Prenons un fichier journal contenant un horodatage, un niveau de journalisation et un message, comme dans l'exemple suivant:
2024-02-09 13:00:51 ERROR This is a test error message
2024-02-09 13:02:49 ERROR This is a test error message containing a secret
Ces journaux peuvent être mis en correspondance de manière plus générale à l'aide d'une configuration de récepteur filelog telle que celle-ci:
receivers:
filelog/simple:
include: [ /tmp/foo.log ]
operators:
- type: regex_parser
regex: '^(?P<time>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) (?P<sev>[A-Z]*) (?P<msg>.*)$'
timestamp:
parse_from: attributes.time
layout: '%Y-%m-%d %H:%M:%S'
severity:
parse_from: attributes.sev
L'expression régulière donnée affecte l'horodatage et la gravité aux groupes de capture nommés. L'horodatage layout est défini de sorte que le collecteur comprenne le format, ce qui permet d'utiliser l'horodatage correct du message de journal comme horodatage de l'enregistrement que le collecteur envoie au serveur. La gravité est envoyée sans modification.
Ce récepteur doit être ajouté au pipeline logs/receivers :
pipelines:
logs:
receivers:
- filelog/simple
Cette configuration signale tous les messages correctement formatés du journal au serveur.
Cependant, l'un des messages du journal recèle un secret. Pour exclure les messages qui contiennent des secrets, ajoutez un filtre à la section processors de la configuration. Le filtre doit contenir une expression régulière qui correspond à toute chaîne de caractères contenant le mot secret. L'exemple suivant utilise la fonction OTTL IsMatch(...) pour rechercher toute chaîne de caractères contenant le mot secret.
processors:
filter/remove_secret:
error_mode: ignore
logs:
log_record:
- 'IsMatch(body, ".*secret.*")'
Ajoutez ce filtre au pipeline processors :
pipelines:
logs:
receivers:
- filelog/simple
processors:
- filter/remove_secret
Avec cette configuration en place, seul le premier message de l'exemple de lignes de journal est signalé, mais le second, qui contient le mot "secret", est supprimé.
Exclure les messages syslog d'un service particulier
Prenons l'exemple d'un syslog sur un système Linux® . Si quelqu'un utilise le bureau Gnome sur ce système, il peut créer des journaux bruyants:
Feb 9 09:10:00 li-8dc514cc-2e0d-11b2-a85c-f1d7ce42b83b org.gnome.Shell.desktop[4771]: Window manager warning: Overwriting existing binding of keysym 31 with keysym 31 (keycode a).
Feb 9 09:10:00 li-8dc514cc-2e0d-11b2-a85c-f1d7ce42b83b org.gnome.Shell.desktop[4771]: Window manager warning: Overwriting existing binding of keysym 32 with keysym 32 (keycode b).
Feb 9 09:10:00 li-8dc514cc-2e0d-11b2-a85c-f1d7ce42b83b org.gnome.Shell.desktop[4771]: Window manager warning: Overwriting existing binding of keysym 33 with keysym 33 (keycode c).
Feb 9 09:10:00 li-8dc514cc-2e0d-11b2-a85c-f1d7ce42b83b org.gnome.Shell.desktop[4771]: Window manager warning: Overwriting existing binding of keysym 34 with keysym 34 (keycode d).
Feb 9 09:10:00 li-8dc514cc-2e0d-11b2-a85c-f1d7ce42b83b org.gnome.Shell.desktop[4771]: Window manager warning: Overwriting existing binding of keysym 35 with keysym 35 (keycode e).
Feb 9 09:10:00 li-8dc514cc-2e0d-11b2-a85c-f1d7ce42b83b org.gnome.Shell.desktop[4771]: Window manager warning: Overwriting existing binding of keysym 36 with keysym 36 (keycode f).
Feb 9 09:10:00 li-8dc514cc-2e0d-11b2-a85c-f1d7ce42b83b org.gnome.Shell.desktop[4771]: Window manager warning: Overwriting existing binding of keysym 37 with keysym 37 (keycode 10).
Feb 9 09:10:00 li-8dc514cc-2e0d-11b2-a85c-f1d7ce42b83b org.gnome.Shell.desktop[4771]: Window manager warning: Overwriting existing binding of keysym 38 with keysym 38 (keycode 11).
Feb 9 09:10:00 li-8dc514cc-2e0d-11b2-a85c-f1d7ce42b83b org.gnome.Shell.desktop[4771]: Window manager warning: Overwriting existing binding of keysym 39 with keysym 39 (keycode 12).
Feb 9 09:10:26 li-8dc514cc-2e0d-11b2-a85c-f1d7ce42b83b systemd[1]: fprintd.service: Succeeded.
Comme dans le premier exemple, le récepteur filelog peut surveiller ce journal et mapper l'horodatage à l'aide d'une expression régulière:
receivers:
filelog/syslog:
include: [ /var/log/syslog ]
operators:
- type: regex_parser
regex: '^(?P<time>[A-Za-z]{3}[ ]+\d{1,2} \d{2}:\d{2}:\d{2}) (?P<msg>.*)$'
timestamp:
parse_from: attributes.time
layout: '%b %e %H:%M:%S'
L'horodatage semble différent de celui du premier exemple, mais avec l'expression régulière et la définition de mise en forme appropriées, il est possible de le comprendre. Ce journal ne contient aucune gravité. Le récepteur, comme toujours, doit être inclus dans le pipeline logs/receivers :
pipelines:
logs:
receivers:
- filelog/simple
- filelog/syslog
Sur un système serveur, vous pouvez surveiller les processus système mais exclure les journaux générés par l'environnement de bureau. Un filtre d'expression régulière peut bloquer tous les messages d'un service particulier:
processors:
filter/remove_gnomeshell:
error_mode: ignore
logs:
log_record:
# message body will have the timestamp stripped off by the regex_parser, so it looks like:
# "hostname service[pid]: message"
# Regex matches this as:
# [^ ]+ <hostname> One or more non-whitespace characters, followed by
# A space, followed by
# org.gnome.Shell.desktop <service name> followed by
# [ followed by
# [0-9]+ <pid> one or more numeric digits, followed by
# ]: followed by
# .* <message> the rest of the log message
- 'IsMatch(body, "[^ ]+ org.gnome.Shell.desktop\\[[0-9]+\\]:.*")'
Ajoutez le filtre au pipeline logs/processors :
logs:
receivers:
- filelog/simple
- filelog/syslog
processors:
- filter/remove_secret
- filter/remove_gnomeshell
A présent, tous les enregistrements de journal dans lesquels la zone de service est org.gnome.Shell.desktop sont supprimés.
Filtrer les journaux en fonction des données d'infrastructure
Le processeur de filtrage est capable d'effectuer un filtrage en fonction des informations fournies dans la resource attributes section de la charge utile. Ce processeur permet d'exclure tous les messages provenant, par exemple, d'un pod Kubernetes spécifique, d'un espace de noms Kubernetes entier ou d'un hôte particulier. Pour plus d'informations sur les données d'infrastructure prises en charge, consultez la section « Données d'infrastructure ».
Filtrer les journaux en fonction de leur niveau de gravité
Il peut arriver que des conteneurs soient configurés pour générer des journaux présentant différents niveaux de gravité. Dans ce cas, vous pouvez filtrer tous les messages à l'exception des messages ERROR et FATAL afin d'éviter de saturer le collecteur avec des données superflues.
Prenons l'exemple des journaux suivants :
[15:52:30 DEBUG] Some debug message.
[15:52:30 INFO] Some info message.
[15:52:30 ERROR] Some error message.
[15:52:30 FATAL] Some fatal message.
Pour filtrer les journaux DEBUG et INFO en fonction du niveau de gravité, vous devez d'abord définir le severity_text champ pour chaque entrée du journal. Pour ce faire, on peut utiliser le processeur transform suivant :
transform/set_log_severity:
log_statements:
- context: log
statements:
- set(severity_text, "Debug") where IsMatch(body.string, "\\[[0-9]{2}:[0-9]{2}:[0-9]{2} DEBUG\\]")
- set(severity_text, "Info") where IsMatch(body.string, "\\[[0-9]{2}:[0-9]{2}:[0-9]{2} INFO\\]")
- set(severity_text, "Error") where IsMatch(body.string, "\\[[0-9]{2}:[0-9]{2}:[0-9]{2} ERROR\\]")
- set(severity_text, "Fatal") where IsMatch(body.string, "\\[[0-9]{2}:[0-9]{2}:[0-9]{2} FATAL\\]")
severity_text sera définie sur une chaîne vide, ce que Instana interprétera comme un niveau de Nonegravité.Une fois ce paramètre severity_text défini dans le fichier de journaux, vous pouvez utiliser l'exemple filter de processeur suivant pour ignorer les entrées de journal dont le niveau de gravité est inférieur à ERROR, ainsi que celles qui ne comportent pas de niveau de gravité.
filter/remove_unnecessary_logs:
logs:
log_record:
- IsMatch(severity_text, "^(|Debug|Info)$")
Cet exemple utilise la fonction OTTL ( IsMatch(...) pour exclure les journaux dans lesquels l'expression régulière spécifiée correspond à une chaîne vide, au caractère Debug«, » et aux niveaux de Info gravité des journaux.
Vous pouvez également indiquer les journaux que vous souhaitez inclure plutôt qu'exclure en fonction du niveau de gravité, en utilisant le mot-clé « not ». De cette façon, vous filtrez désormais les journaux qui ne correspondent pas aux niveaux de Error gravité ou Fatal.
filter/remove_unnecessary_logs:
logs:
log_record:
- not IsMatch(severity_text, "^(Error|Fatal)$")
Dans la service/pipelines/logs/processors section, ajoutez le nouveau filtre :
processors:
- resourcedetection
- transform/set_log_severity
- filter/remove_unnecessary_logs
- batch
Filtrer les journaux en fonction des attributs des ressources
Voici une liste non exhaustive d'exemples d'attributs de ressources pouvant être utilisés pour le filtrage des journaux :
Exemples d'attributs collectés par le processeur « k8sattributes » et le processeur « resourcedetection » :
resource.attributes["k8s.pod.name"]: Le nom du pod « Kubernetes » qui a généré le message de journalresource.attributes["k8s.container.name"]: Nom du conteneur sous-jacent à l'origine du message de journalresource.attributes["k8s.namespace.name"]: Le nom de l'espace de noms contenant le pod qui a généré le message de journalresource.attributes["k8s.deployment.name"]: Nom de l'objet de déploiement d' Kubernetes s qui gère le pod ayant généré le message de journalresource.attributes["k8s.node.name"]: Nom du nœud de l' Kubernetes s sur lequel s'exécute le pod à l'origine du message de journalisationresource.attributes["k8s.pod.hostname"]: Nom de l'hôte sur lequel s'exécute le processus à l'origine du message de journal. Si le collecteur s'exécute à l'intérieur d'un conteneur, le nom d'hôte correspond généralement au nom du conteneur, et non au nom de l'hôte sous-jacent proprement ditresource.attributes["os.type"]: Le type de système d'exploitation de l'hôte sur lequel s'exécute le processus à l'origine du message de journal
En utilisant les process eurs k8sattributes,resource ettransform, les attributs définis par l'utilisateur dans le resource.attributes mappage peuvent être définis de manière dynamique et utilisés pour un filtrage personnalisable des journaux.
Exemples
Tous ces exemples suivent un modèle similaire. Une section filter doit être ajoutée au fichier de configuration d'opentelemetry-collector et ce filtre doit être inclus dans le pipeline logs/processors dans le même fichier. Si vous utilisez Helm pour installer le collecteur, la configuration se trouve dans la section config: du fichier values.yaml lors de l'installation.
Exclure les messages de journalisation d'un conteneur d' Kubernetes s spécifique
Supposons que vous souhaitiez filtrer tous les messages de journal d'un conteneur Kubernetes appelé calico-node. Dans la section processors de la configuration, ajoutez un bloc comme celui-ci:
filter/remove_calico:
error_mode: ignore
logs:
log_record:
- resource.attributes["k8s.container.name"] == "calico-node"
Ensuite, dans la section service/pipelines/logs/processors , incluez le nouveau filtre:
processors:
- resourcedetection
- transform/set_log_severity
- filter/remove_calico
- batch
Le nouveau filtre est répertorié en dernier. Les autres processeurs affichés sont uniquement destinés au contexte et ne sont pas nécessaires au fonctionnement du processeur de filtre.
Exclure les messages de journalisation de tous les systèmes d' Linux®
Si vous souhaitez bloquer tous les messages de journal provenant d'un système Linux®, dans la section 'processors de la configuration, vous pouvez ajouter:
filter/remove_linux:
error_mode: ignore
logs:
log_record:
- resource.attributes["os.type"] == "linux"
De même, dans la section service/pipelines/logs/processors , en vous fondant sur l'exemple précédent, incluez le nouveau filtre:
processors:
- resourcedetection
- transform/set_log_severity
- filter/remove_calico
- filter/remove_linux
- batch
Exclure les messages de journalisation provenant d'un pod ou d'un déploiement « Kubernetes » comportant des étiquettes ou des annotations spécifiques
Supposons que vous disposiez du déploiement Kubernetes suivant, avec les étiquettes et les annotations à partir desquelles vous souhaitez filtrer tous les messages de journal :
apiVersion: apps/v1
kind: Deployment
metadata:
[...]
spec:
[...]
template:
metadata:
labels:
some-keyword-label: "ABCD-label-substring-ABCD"
annotations:
some-keyword-annotation: "ABCD-annotation-substring-ABCD
Si vous souhaitez filtrer par some-keyword-label ou some-keyword-annotation, vous pouvez étendre le k8sattribute processeur comme indiqué dans l'exemple suivant afin de récupérer toutes les étiquettes et annotations des pods :
processors:
k8sattributes:
[...]
extract:
metadata:
[...]
## Note: The '$$1' is a placeholder for the label or annotation name and will be used in the 'resource.attributes' mapping.
labels:
- tag_name: $$1
key_regex: (.*)
from: pod
annotations:
- tag_name: $$1
key_regex: (.*)
from: pod
Utilisez l'exemple suivant pour extraire some-keyword-label l'étiquette et some-keyword-annotation l'annotation :
processors:
k8sattributes:
[...]
extract:
metadata:
[...]
## Note: In this example same label or annotation names are used as the ones to be extracted.
## The 'tag_name' corresponds to the key in the 'resource.attributes' mapping.
## The 'key' corresponds to the label or annotation you want to extract.
labels:
- tag_name: some-keyword-label
key: some-keyword-label
from: pod
annotations:
- tag_name: some-keyword-annotation
key: some-keyword-annotation
from: pod
Une fois que vous avez configuré le k8sattributes processeur pour extraire les étiquettes et annotations souhaitées, vous pouvez utiliser le filter processeur filter_by_keyword ou pour exclure les messages de journal provenant des pods qui possèdent some-keyword-label l'étiquette ou some-keyword-annotation l'annotation :
filter/keyword_filter:
logs:
log_record:
## Note: You can add as many filters as you would like if there are multiple labels/annotations.
- IsMatch(resource.attributes["some-keyword-label"], ".*(label-substring).*")
- IsMatch(resource.attributes["some-keyword-annotation"], ".*(annotation-substring).*")
Dans la service/pipelines/logs/processors section, en reprenant l'exemple précédent, ajoutez le nouveau filtre :
processors:
- resourcedetection
- filter/filter_by_keyword
- batch
Le nouveau filtre est répertorié en dernier. Les autres processeurs affichés sont uniquement destinés au contexte et ne sont pas nécessaires au fonctionnement du processeur de filtre.
Masquer les informations sensibles dans les journaux
Les messages de journal contiennent parfois des informations identifiant la personne (PII) ou d'autres données sensibles qui doivent rester privées et ne pas être envoyées au serveur ou sauvegardées. Ces informations peuvent inclure des éléments tels que des mots de passe, des numéros de carte de crédit ou un certain nombre d'autres éléments. Le processeur transform peut détecter de telles informations à l'aide d'une expression régulière et les remplacer par autre chose.
Exemples
Ces exemples suivent un modèle similaire. Une section transform doit être ajoutée au fichier de configuration d'opentelemetry-collector et cette transformation doit être incluse dans le pipeline logs/processors dans le même fichier. Si vous utilisez Helm pour installer le collecteur, la configuration se trouve dans la section config: du fichier values.yaml lors de l'installation.
Suppression des mots de passe dans les messages de journal
Supposons qu'une application consigne le mot de passe fourni chaque fois qu'un échec d'authentification se produit. L'enregistrement de journal peut se présenter comme suit:
2024-02-14 19:40:31 WARNING failed login for user bob, password=bobo
Il est important de savoir qu'une tentative de connexion a échoué, mais il n'est pas approprié de consigner le mot de passe utilisé.
L'application consigne le mot de passe dans un format connu. Le modèle est toujours password=xyz. Une expression régulière peut détecter ce modèle et le remplacer par quelque chose d'autre:
transform/redact_password:
log_statements:
- context: log
statements:
# Any log messages containing "password=xxx" or "passwd=yyy" will be matched.
# Regex matches these as:
# passw The literal string 'passw', followed by
# (?:or)?? The literal string "or" 0 or 1 times (this allows either password or passwd)
# d= The literal string "d=", followed by
# [^\s]* Any non-whitespace characters (the password), followed by
# (\s?)* 0 or more whitespace characters, marking the end of the password.
- replace_pattern(body, "passw(?:or)??d\\=[^\\s]*(\\s?)", "password=REDACTED")
- replace_pattern(attributes["msg"], "passw(?:or)??d\\=[^\\s]*(\\s?)", "password=REDACTED")
La directive replace_pattern apparaît une fois pour le message body et une fois pour l'attribut msg . Le collecteur de télémétrie ouvert place le contenu du message dans les deux emplacements, de sorte que les deux doivent être mis à jour.
Et ajoutez la transformation au pipeline logs/processors :
logs:
receivers:
- otlp
- filelog/simple
processors:
- transform/redact_password
La transformation transforme le message de journal initial en:
2024-02-15 15:45:37 WARNING failed login for user bob, password=REDACTED
Suppression des noms d'hôte des messages de journal
Supposons qu'une autre application écrit des noms d'hôte dans le syslog:
Feb 15 15:52:36 li-8dc514cc-2e0d-11b2-a85c-f1d7ce42b83b service[45568]: This is a test error message from where.ever.ibm.com
Si les noms d'hôte sont considérés comme confidentiels, il est possible de les empêcher d'être ajoutés au journal. Si tous les hôtes se trouvent dans le même domaine, dans cet exemple .ibm.com, une expression régulière peut reconnaître le modèle et masquer les noms:
transform/remove_hostnames:
log_statements:
- context: log
statements:
# Any log message containing a hostname ending in ".ibm.com" will have the hostname removed.
# Regex matches as:
# ([a-zA-Z0-9-_\.]+) One or more letters, digits, dashes, underscores, or dots, followed by
# \.ibm\.com The literal string ".ibm.com"
- replace_pattern(body, "([a-zA-Z0-9-_\\.]+)\\.ibm\\.com", "<hidden hostname>")
- replace_pattern(attributes["msg"], "([a-zA-Z0-9-_\\.]+)\\.ibm\\.com", "<hidden hostname>")
A nouveau, l'attribut body et l'attribut msg sont réécrits car le texte du message de journal apparaît dans les deux emplacements.
Et encore une fois, ajoutez la transformation au pipeline:
logs:
receivers:
- filelog/syslog
processors:
- transform/redact_password
- transform/remove_hostnames
Le message est ensuite réécrit comme suit:
Feb 15 15:52:36 li-8dc514cc-2e0d-11b2-a85c-f1d7ce42b83b service[45568]: This is a test error message from <hidden hostname>