Utilisation d'expressions rationnelles lors de l'interrogation de données
Vous pouvez utiliser des expressions régulières (regex) lors de l'interrogation des données d' IBM Cloud Logs s pour la recherche de motifs et le remplacement de chaînes de caractères.
Vous voudrez peut-être extraire des données spécifiques de vos journaux pour faciliter l'analyse et la visualisation. Il peut arriver que vous souhaitiez capturer des données spécifiques enregistrées. Dans d'autres cas, il peut s'avérer nécessaire de dissimuler des données sensibles dans les journaux avant qu'ils ne soient enregistrés.
Vous pouvez également effectuer une recherche à l'aide d'une expression rationnelle plutôt qu'à l'aide d'un texte exact.
Qu'est-ce qu'une expression régulière et comment fonctionne-t-elle?
Les expressions régulières, également connues sous le nom de regex, sont un langage spécifique à un domaine (DSL) utilisé pour les recherches et les remplacements de motifs.
Les informations contenues dans cette rubrique n'ont pas pour but de fournir un didacticiel complet sur les expressions rationnelles. Si vous n'êtes pas familiarisé avec les expressions rationnelles, vous pouvez consulter les informations accessibles au public sur les expressions rationnelles avant d'essayer de comprendre les concepts spécifiques présentés ici.
Concepts de regex
Il y a quelques concepts de base que vous devez connaître pour comprendre les exemples de cette rubrique.
- Groupe de capture
- Regex contenue dans des parenthèses. Les opérateurs sont appliqués au texte correspondant à la spécification entre parenthèses.
- Groupe de capture nommé
- Groupe de capture associé à un nom. Les résultats obtenus peuvent être référencés par le nom
- Classe de caractères
- Une série de caractères à rechercher entre crochets (
[]). Un tiret peut être utilisé comme abréviation pour énumérer plusieurs caractères :[1-5]est identique à[12345].
Quand utiliser les expressions rationnelles
Dans certains cas, vous n'aurez pas besoin d'une expression régulière et vous pourrez vous contenter de rechercher un texte spécifique. Par exemple, si vous souhaitez uniquement trouver les lignes de journal contenant le texte user logged in,
il vous suffit de saisir ce texte dans votre recherche de journal. Mais si vos lignes de journal ressemblent à ceci : user_32 logged in vous ne pouvez pas rechercher le texte exact puisque l'identifiant de l'utilisateur est une
variable qui change.
Heureusement, il existe un modèle de regex pour ce cas qui utilise la séquence "match anything" :
user_d+ logged in
Utilisation d'une expression rationnelle pour extraire du texte dans des champs JSON personnalisés
Supposons que vous disposiez d'un journal non structuré au format suivant :
${logLevel}: World-${worldName}: ${logText}
Et vous souhaitez convertir toutes les entrées dans ce format en un objet JSON au format suivant :
{
"level": `${log-level}`,
"tag": `World-${worldName}`,
"text": `${logText}`
}
Vous pouvez utiliser cette expression rationnelle pour effectuer la conversion :
^(?P.*?):s*(?P.*?):
Où :
^est le symbole de début de ligne, ce qui signifie que la correspondance doit commencer par le début d'une ligne.(?PX)oùXcorrespond à ce qui est recherché et à la syntaxe du groupe de capture nommé. Cette expression rationnelle comporte trois groupes de capture, un pour chaque clé JSON nécessaire.ssignifie "tout caractère d'espacement"..signifie "un caractère quelconque".*signifie "0 ou plusieurs correspondances avec le symbole ou le caractère précédent"..*signifie "1 ou plusieurs correspondances avec le symbole ou le caractère précédent"..*?signifie "n'importe quel caractère, n'importe quel nombre de fois, avec le moins de jetons possible".
Donc, la regex :
^(?P.*?):s*(?P.*?):
Les demandes seront traitées comme suit :
-
Le texte commençant au début d'une ligne jusqu'au premier symbole
:sera capturé en tant que groupelevel. -
Après un nombre quelconque d'espaces blancs, tout texte jusqu'au prochain symbole
:sera capturé en tant que groupetag. -
Le texte du journal est automatiquement défini dans le champ
textpar IBM Cloud Logs, de sorte que nous aurons automatiquement le champtext.
En utilisant la même expression rationnelle, le journal suivant s'affiche :
"info: World-w-8: generate: new world"
Est converti en cet objet JSON :
{
"level": "info",
"tag": "World-w-8",
"text": "info: World-w-8: generate: new world"
}
Extraction de texte dans des champs prédéfinis
Vous pouvez vouloir extraire du texte dans des champs prédéfinis. Prenons l'exemple de ce journal :
"info: World-w-8: generate: new world"
Vous pouvez extraire le texte info dans la colonne Severity et le texte World dans la colonne Class.
Vous pouvez modifier l'expression rationnelle pour définir les noms corrects des groupes de capture comme suit :
^(?P.*?):s*(?P.*?)-(?P.*?):
Cette expression rationnelle formatera le journal de manière à ce qu'il s'affiche comme indiqué.
Extraction de données spécifiques à partir de journaux structurés
Une méthode similaire peut être utilisée pour extraire des données de journaux structurés. L'exemple suivant montre comment extraire des données d'un champ JSON spécifique.
Supposons que vous ayez une ligne de journal structurée semblable à celle-ci :
{
"type": `${text}`,
"log": `${text}`,
"region": "rg-europe-2"
}
Maintenant, si le champ region a la forme suivante :
`rg-${"europe"|"asia"|"na"}-${number}`
Nous voulons extraire la partie qui nous indique si la région est europe, asia ou na. L'expression rationnelle permettant d'extraire les données serait la suivante :
"region"s*:s*"rg-(?P.*?)-
C'est le groupe de capture nommé regionName qui extrait le texte. Le nom de la région se trouve après le nom de la clé region et les caractères rg- selon notre format. L'objectif des symboles s* est de faire en sorte que les expressions rationnelles fonctionnent toujours s'il y a des espaces blancs avant ou après le symbole :.
Le résultat sera similaire à ce qui suit :
{
"log" : "Bye",
"regionName" : "na",
"region" : "rg-na-1",
"type" : "ltest-w-9"
}
Remplacement et suppression de valeurs
L'un des exemples les plus courants où nous devons remplacer ou supprimer des valeurs est le masquage de données personnelles. Supposons que vous enregistrez des numéros de téléphone quelque part et que vous ne voulez pas qu'ils soient sauvegardés dans IBM Cloud Logs.
Supposons que nous ayons une ligne de journal non structurée comme celle-ci :
"info: Sender: sendSms: sending sms to phone number +12345678910 to user Andrew"
Vous souhaitez supprimer le numéro de téléphone et le nom de cette ligne. Cette expression rationnelle correspondra à la ligne commençant par "sending sms" :
sending sms to phone number +*d+ to user .*
Nous devons faire échapper le symbole + à un espace vide, car + a une signification particulière dans la syntaxe des expressions rationnelles. Ce sens est "1 ou plusieurs caractères précédents".
Le symbole d correspond à n'importe quel chiffre unique. N'oubliez pas que le symbole * signifie "0 ou plus caractères précédents". Ainsi, +*d+ correspond à un ou plusieurs chiffres qui peuvent être précédés
d'un symbole + (ou non).
Cette regex remplacera le texte correspondant à la regex précédente par le même texte, mais sans le numéro de téléphone et le nom :
sending sms to phone number * to user *
Et voici le résultat de l'application de la règle ci-dessus :
"info: Sender: sendSms: sending sms to phone number * to user *"
Remplacer les valeurs JSON dans les journaux structurés
Le remplacement des valeurs JSON dans les journaux structurés est similaire au remplacement des valeurs dans les journaux non structurés. La chaîne JSON entière est utilisée comme entrée pour la règle Replace.
En utilisant la structure JSON suivante :
{
"type": `${text}`,
"log": `${text}`,
"region": "rg-europe-2"
}
Supposons que vous deviez remplacer la valeur du champ type par une autre valeur. Voici comment vous pouvez faire correspondre la valeur du champ type:
"type"s*:s*".*?"
Rappelez-vous que nous avons besoin des symboles s* pour nous assurer que l'expression rationnelle fonctionne s'il y a des espaces blancs avant ou après le caractère :.
Voici l'expression rationnelle qui remplacera toute valeur du champ type par newType:
"type":"newType"
Utilisation des références rétrospectives
Supposons que nous devions remplacer europe par eu dans les chaînes au format west-europe-2. Et supposons que nous devions le faire non seulement dans le champ region, mais aussi dans toute
autre partie du journal où se trouve la chaîne de caractères. Il est facile de faire correspondre ce modèle avec cette expression rationnelle :
.+?-europe-d+
Cependant, le remplacement de la chaîne de caractères à l'aide des méthodes que nous avons utilisées précédemment risque d'être assez difficile. En effet, nous devons insérer deux chaînes de caractères avant et après le texte europe,
et ces chaînes peuvent varier. Pour ce faire, nous devons d'abord capturer les chaînes de caractères dans des groupes de capture :
(.+?)-europe-(d+)
Rappelons que le symbole d signifie "n'importe quel chiffre" et qu'avec + il signifie "n'importe quel chiffre une ou plusieurs fois". De la même manière, .+ désigne n'importe quel symbole
une ou plusieurs fois, mais avec le plus petit nombre de jetons pour obtenir la correspondance.
Cette expression rationnelle capturera le texte avant europe en tant que groupe de capture 1, et le texte après europe en tant que groupe de capture 2. L'expression rationnelle suivante utilisera les références arrière
pour insérer le contenu correspondant à ces groupes :
$1-eu-$2
Par exemple, un journal avant l'application de notre règle :
{
"log" : "Here region is east-europe-1. That's it",
"type" : "newType",
"region" : "east-europe-1"
}
Et le journal après application de la règle :
{
"log" : "Here region is east-eu-1. That's it",
"type" : "newType",
"region" : "east-eu-1"
}
Recherche à l'aide d'une expression rationnelle dans la barre de recherche des journaux
La barre de recherche de la page Logs de l'interface utilisateur IBM Cloud Logs est un autre endroit où vous pouvez utiliser des expressions rationnelles.
Lorsque vous effectuez une recherche à partir de la barre de recherche de la page, vous pouvez saisir du texte exact, des requêtes Lucene ou Dataprime. Vous pouvez également rechercher des motifs particuliers à l'aide d'une expression rationnelle. Les requêtes Regex ont leur propre format :
/${fieldName}.keyword:/REGEX//
Supposons que nous ayons de nombreux journaux structurés en JSON dans le format suivant :
{
"log": `${text}` ,
"regionName": `${text}`,
"region": `${text}`,
"type" : `ltest-w-${number}`
}
Et nous ne voulons faire correspondre que les entrées où type est égal à ltest-w-1, ltest-w-2 ou ltest-w-3. La requête de recherche suivante permet d'atteindre cet objectif :
/type.keyword:/ltest-w-[1-3]//
Le texte situé entre les crochets [ et ] est appelé classe de caractères. Il correspond à n'importe quel caractère listé entre crochets. Le tiret peut être utilisé comme raccourci pour énumérer plusieurs caractères
: [1-5] est identique à [12345].
Vous pouvez utiliser la même syntaxe pour faire correspondre des données dans des journaux non structurés avec des expressions rationnelles. Il vous suffit de définir le nom du champ sur text.keyword. Exemple :
/text.keyword:/.*ltest-w-[1-3].*//
Cette expression rationnelle recherchera le texte ltest-w-1, ltest-w-2 ou ltest-w-3 dans le corps du journal principal.
Déclenchement d'alertes avec des expressions rationnelles
Une autre utilisation courante des expressions rationnelles dans IBM Cloud Logs est la définition d'alertes. La syntaxe des alertes est la même que la syntaxe des requêtes logs.
Supposons que nous voulions nous alerter sur une ligne de la forme suivante :
`App: init: World-${name}: generation error: ${err}`
Et supposons que nous voulions recevoir des alertes uniquement pour les mondes w-1, w-2, w-3 ou w-4. Notre expression rationnelle d'alerte ressemblera à ceci :
/text.keyword:/.*World-w-[1-4]: generation error.*//
Rappelez-vous que [1-4] correspond à n'importe quel caractère de 1 à 4, et que .* correspond à n'importe quel caractère, quel que soit le nombre de fois.
Pour plus d'informations sur les alertes, voir