Verwendung von Regex bei der Abfrage von Daten
Bei der Abfrage von IBM Cloud Logs-Daten können Sie reguläre Ausdrücke (Regex) zur Mustersuche und zum Ersetzen von Zeichenfolgen verwenden.
Sie können bestimmte Daten aus Ihren Protokollen extrahieren, um die Analyse und Visualisierung zu erleichtern. Manchmal möchten Sie vielleicht bestimmte protokollierte Daten erfassen. In anderen Fällen müssen Sie möglicherweise sensible Daten in Protokollen verbergen, bevor sie gespeichert werden.
Sie können auch mit einem Regex-Muster statt einer exakten Textsuche suchen.
Was ist regex und wie funktioniert es?
Reguläre Ausdrücke, auch als Regex bekannt, sind eine domänenspezifische Sprache (DSL), die für Mustersuchen und Ersetzungen verwendet wird.
Die Informationen in diesem Thema sind nicht als vollständige Anleitung zu Regex gedacht. Wenn Sie mit Regex nicht vertraut sind, sollten Sie sich öffentlich zugängliche Informationen zu Regex ansehen, bevor Sie versuchen, die hier enthaltenen spezifischen Konzepte zu verstehen.
Regex-Konzepte
Es gibt einige grundlegende Konzepte, die Sie kennen müssen, um die Beispiele in diesem Thema zu verstehen.
- Erfassungsgruppe
- Regex in Klammern. Die Operatoren werden auf den Text angewendet, der der Spezifikation in der Klammer entspricht.
- Benannte Erfassungsgruppe
- Eine Erfassungsgruppe, die mit einem Namen verknüpft ist. Die übereinstimmenden Ergebnisse können über den Namen aufgerufen werden
- Charakterklasse
- Eine Reihe von Zeichen, die abgeglichen werden sollen, wird in eckige Klammern gesetzt (
[]). Ein Bindestrich kann als Abkürzung verwendet werden, um mehrere Zeichen aufzulisten:[1-5]ist dasselbe wie[12345].
Wann sollte man Regex verwenden?
Manchmal benötigen Sie keinen regulären Ausdruck und können einfach nach einem bestimmten Text suchen. Wenn Sie beispielsweise nur nach Logzeilen mit dem Text user logged in suchen möchten, können Sie diesen Text einfach in Ihre
Logsuche eingeben. Wenn Ihre Log-Zeilen jedoch so aussehen: user_32 logged in, können Sie nicht nach dem genauen Text suchen, da die Benutzer-ID eine Variable ist, die sich ändert.
Glücklicherweise gibt es für diesen Fall ein Regex-Muster, das die Sequenz "match anything" verwendet:
user_d+ logged in
Verwendung von Regex, um Text in benutzerdefinierte JSON-Felder zu extrahieren
Angenommen, Sie haben ein unstrukturiertes Protokoll im folgenden Format:
${logLevel}: World-${worldName}: ${logText}
Und Sie möchten alle Einträge in diesem Format in ein JSON-Objekt im folgenden Format umwandeln:
{
"level": `${log-level}`,
"tag": `World-${worldName}`,
"text": `${logText}`
}
Sie können diesen regulären Ausdruck verwenden, um die Konvertierung durchzuführen:
^(?P.*?):s*(?P.*?):
Dabei gilt:
^ist das Symbol für den Zeilenanfang, d. h., die Übereinstimmung muss mit dem Zeilenanfang beginnen.(?PX)wobeiXdas übereinstimmende Element ist und die benannte Erfassungsgruppensyntax ist. Diese Regex hat drei Erfassungsgruppen, eine für jeden benötigten JSON-Schlüssel.sbedeutet "jedes Leerzeichen"..bedeutet "ein beliebiges Zeichen".*bedeutet "0 oder mehr Übereinstimmungen mit dem vorherigen Symbol oder Zeichen"..*bedeutet "1 oder mehrere Übereinstimmungen des vorherigen Symbols oder Zeichens"..*?bedeutet "beliebige Zeichen beliebig oft mit der geringstmöglichen Anzahl an Token".
Also, die Regex:
^(?P.*?):s*(?P.*?):
Wird wie folgt bearbeitet:
-
Text, der am Anfang einer Zeile beginnt, bis zum ersten
:-Symbol wird als Gruppelevelerfasst. -
Nach einer beliebigen Anzahl von Leerzeichen wird jeder Text bis zum nächsten
:-Symbol als Gruppetagerfasst. -
Der Logtext wird automatisch von IBM Cloud Logs in das Feld
textgesetzt, sodass wir automatisch das Feldtexthaben.
Mit demselben regulären Ausdruck wird das folgende Protokoll erstellt:
"info: World-w-8: generate: new world"
Wird in dieses JSON-Objekt umgewandelt:
{
"level": "info",
"tag": "World-w-8",
"text": "info: World-w-8: generate: new world"
}
Extrahieren von Text in vordefinierte Felder
Sie können Text in vordefinierte Felder extrahieren. Betrachten Sie dieses Protokoll:
"info: World-w-8: generate: new world"
Sie können den Text von info in die Spalte Severity und den Text von World in die Spalte Class extrahieren.
Sie können die Regex wie folgt ändern, um die korrekten Namen der Erfassungsgruppen festzulegen:
^(?P.*?):s*(?P.*?)-(?P.*?):
Diese Regex formatiert das Protokoll so, dass es wie abgebildet angezeigt wird.
Extrahieren spezifischer Daten aus strukturierten Protokollen
Eine ähnliche Methode kann verwendet werden, um Daten aus strukturierten Protokollen zu extrahieren. Im Folgenden wird anhand eines Beispiels gezeigt, wie Daten aus einem bestimmten JSON-Feld extrahiert werden.
Angenommen, Sie haben eine strukturierte Log-Zeile, die dieser ähnelt:
{
"type": `${text}`,
"log": `${text}`,
"region": "rg-europe-2"
}
Wenn das Feld region nun die folgende Form hat:
`rg-${"europe"|"asia"|"na"}-${number}`
Wir wollen den Teil extrahieren, der uns sagt, ob die Region europe, asia oder na ist. Die Regex zum Extrahieren der Daten wäre:
"region"s*:s*"rg-(?P.*?)-
Die benannte Erfassungsgruppe regionName extrahiert den Text. Der Name der Region ist nach dem Schlüsselnamen region und den Zeichen rg- gemäß unserem Format benannt. Der Zweck der s*-Symbole
besteht darin, dass regex auch dann noch funktioniert, wenn vor oder nach dem :-Symbol Leerzeichen stehen.
Das Ergebnis wird in etwa wie folgt aussehen:
{
"log" : "Bye",
"regionName" : "na",
"region" : "rg-na-1",
"type" : "ltest-w-9"
}
Werte ersetzen und entfernen
Eines der häufigsten Beispiele, bei denen wir Werte ersetzen oder entfernen müssen, ist das Verbergen persönlicher Daten. Angenommen, Sie haben Telefonnummern irgendwo notiert und möchten nicht, dass diese in IBM Cloud Logs gespeichert werden.
Nehmen wir an, wir haben eine unstrukturierte Log-Zeile wie diese:
"info: Sender: sendSms: sending sms to phone number +12345678910 to user Andrew"
Sie möchten die Telefonnummer und den Namen aus dieser Zeile entfernen. Diese Regex wird mit der Zeile übereinstimmen, die mit "sending sms" beginnt:
sending sms to phone number +*d+ to user .*
Wir müssen das +-Symbol durch ein Leerzeichen ersetzen, da + in der Regex-Syntax eine besondere Bedeutung hat. Diese Bedeutung ist "1 oder mehrere vorherige Zeichen".
Das Symbol d passt zu jeder einzelnen Ziffer. Denken Sie daran, dass das Symbol * "0 oder mehr vorherige Zeichen" bedeutet. Also entspricht +*d+ einer oder mehreren Ziffern, denen ein +-Symbol
vorangestellt werden kann (oder auch nicht).
Diese Regex ersetzt den Text, der mit der vorherigen Regex übereinstimmt, durch denselben Text, jedoch ohne die Telefonnummer und den Namen:
sending sms to phone number * to user *
Und hier ist das Ergebnis der Anwendung der obigen Regel:
"info: Sender: sendSms: sending sms to phone number * to user *"
Ersetzen von JSON-Werten in strukturierten Protokollen
Das Ersetzen von JSON-Werten in strukturierten Protokollen ähnelt dem Ersetzen von Werten in unstrukturierten Protokollen. Der gesamte JSON-String wird als Eingabe für die Ersetzungsregel verwendet.
Verwenden Sie die folgende JSON-Struktur:
{
"type": `${text}`,
"log": `${text}`,
"region": "rg-europe-2"
}
Angenommen, Sie müssen den Wert des Feldes type durch einen anderen Wert ersetzen. So können Sie den Wert des Feldes type abgleichen:
"type"s*:s*".*?"
Denken Sie daran, dass wir die s*-Symbole benötigen, um sicherzustellen, dass die Regex funktioniert, wenn vor oder nach dem :-Zeichen Leerzeichen stehen.
Hier ist der Regex, um jeden Wert im Feld type durch newType zu ersetzen:
"type":"newType"
Verwendung von Rückverweisen
Angenommen, wir müssen europe durch eu in den Zeichenketten im Format west-europe-2 ersetzen. Und nehmen wir an, wir müssen dies nicht nur im Feld region tun, sondern in jedem anderen Teil
des Protokolls, in dem die Zeichenfolge gefunden wird. Dieses Muster lässt sich mit diesem regulären Ausdruck leicht abgleichen:
.+?-europe-d+
Allerdings könnte es ziemlich schwierig sein, die Saite mit den Methoden zu ersetzen, die wir zuvor verwendet haben. Das liegt daran, dass wir vor und nach dem Text europe zwei Zeichenfolgen einfügen müssen, die variieren können.
Dazu müssen wir zunächst die Strings in Erfassungsgruppen erfassen:
(.+?)-europe-(d+)
Denken Sie daran, dass das Symbol d "eine beliebige Ziffer" bedeutet und zusammen mit + "eine beliebige Ziffer ein- oder mehrmals". In ähnlicher Weise bedeutet .+ ein oder mehrere Symbole,
aber mit der geringsten Anzahl an Token, um die Übereinstimmung zu erzielen.
Diese Regex erfasst den Text vor europe als Erfassungsgruppe 1 und den Text nach europe als Erfassungsgruppe 2. Der folgende reguläre Ausdruck verwendet Rückverweise, um den übereinstimmenden Inhalt dieser Gruppen einzufügen:
$1-eu-$2
Zum Beispiel ein Protokoll vor der Anwendung unserer Regel:
{
"log" : "Here region is east-europe-1. That's it",
"type" : "newType",
"region" : "east-europe-1"
}
Und das Protokoll nach Anwendung der Regel:
{
"log" : "Here region is east-eu-1. That's it",
"type" : "newType",
"region" : "east-eu-1"
}
Suche mit regulären Ausdrücken über die Suchleiste der Protokolle
Ein weiterer Ort, an dem Sie Regex verwenden können, ist die Suchleiste auf der Seite "UI Logs" (Benutzeroberflächenprotokolle) von IBM Cloud Logs.
Bei der Suche über die Seitensuchleiste können Sie exakte Text-, Lucene- oder Dataprime-Abfragen eingeben. Sie können auch nach bestimmten Mustern suchen, indem Sie Regex verwenden. Regex-Abfragen haben ihr eigenes Format, das wie folgt aussieht:
/${fieldName}.keyword:/REGEX//
Angenommen, wir haben viele JSON-strukturierte Protokolle im folgenden Format:
{
"log": `${text}` ,
"regionName": `${text}`,
"region": `${text}`,
"type" : `ltest-w-${number}`
}
Und wir möchten nur die Einträge abgleichen, bei denen type gleich ltest-w-1, ltest-w-2 oder ltest-w-3 ist. Die folgende Suchanfrage führt dazu:
/type.keyword:/ltest-w-[1-3]//
Der Text zwischen den eckigen Klammern [ und ] wird als Zeichenklasse bezeichnet. Es passt zu jedem Zeichen, das zwischen eckigen Klammern aufgeführt ist. Strichpunktierung kann als Abkürzung verwendet werden,
um mehrere Zeichen aufzulisten: [1-5] ist dasselbe wie [12345].
Sie können dieselbe Syntax verwenden, um Daten in unstrukturierten Protokollen mit Regex abzugleichen. Sie müssen nur den Feldnamen auf text.keyword setzen. Zum Beispiel:
/text.keyword:/.*ltest-w-[1-3].*//
Diese Regex sucht im Hauptprotokoll nach dem Text ltest-w-1, ltest-w-2 oder ltest-w-3.
Auslösen von Warnungen mit Regex
Ein weiterer beliebter Anwendungsfall für Regex in IBM Cloud Logs ist die Definition von Warnmeldungen. Die Syntax für Warnmeldungen ist dieselbe wie die Syntax für Protokollabfragen.
Nehmen wir an, wir möchten uns über eine Zeile der folgenden Form benachrichtigen lassen:
`App: init: World-${name}: generation error: ${err}`
Und nehmen wir an, wir möchten nur Benachrichtigungen für die Welten w-1, w-2, w-3 oder w-4 erhalten. Unser Regex-Alarm sieht dann so aus:
/text.keyword:/.*World-w-[1-4]: generation error.*//
Denken Sie daran, dass [1-4] mit jedem einzelnen Zeichen von 1 bis 4 übereinstimmt und .* mit jedem beliebigen Zeichen beliebig oft übereinstimmt.
Weitere Informationen zu Warnmeldungen finden Sie unter: