Tipps und Fehlerbehebung beim Schreiben von Parsern
In diesem Dokument werden Probleme beschrieben, die beim Schreiben von Parsercode auftreten können.
Beim Schreiben von Parsercode können Fehler auftreten, wenn die Parseanweisungen nicht wie erwartet funktionieren. Folgende Situationen können zu Fehlern führen:
- Ein
Grok
-Muster schlägt fehl - Ein
rename
- oderreplace
-Vorgang schlägt fehl - Syntaxfehler im Parsercode
Gängige Praktiken im Parsercode
In den folgenden Abschnitten werden Best Practices, Tipps und Lösungen zur Fehlerbehebung beschrieben.
Verwenden Sie in Variablennamen keine Punkte oder Bindestriche.
Die Verwendung von Bindestrichen und Punkten in Variablennamen kann zu unerwartetem Verhalten führen, oft bei merge
-Vorgängen zum Speichern von Werten in UDM-Feldern. Außerdem können vorübergehende Probleme beim Parsen auftreten.
Verwenden Sie beispielsweise nicht die folgenden Variablennamen:
my.variable.result
my-variable-result
Verwenden Sie stattdessen den folgenden Variablennamen: my_variable_result
.
Verwenden Sie keine Begriffe mit besonderer Bedeutung als Variablennamen.
Bestimmte Wörter wie event
und timestamp
können im Parsercode eine besondere Bedeutung haben.
Der String event
wird häufig verwendet, um einen einzelnen UDM-Eintrag darzustellen, und wird in der @output
-Anweisung verwendet. Wenn eine Protokollmeldung ein Feld namens event
enthält oder Sie eine Zwischenvariable namens event
definieren und im Parsercode das Wort event
in der @output
-Anweisung verwendet wird, erhalten Sie eine Fehlermeldung wegen eines Namenskonflikts.
Benennen Sie die Zwischenvariable um oder verwenden Sie den Begriff event1
als Präfix in UDM-Feldnamen und in der @output
-Anweisung.
Das Wort timestamp
steht für den Erstellungszeitstempel des ursprünglichen Rohlogs. Ein in dieser Zwischenvariablen festgelegter Wert wird im UDM-Feld metadata.event_timestamp
gespeichert. Der Begriff @timestamp
steht für das Datum und die Uhrzeit, zu dem das Rohprotokoll geparst wurde, um einen UDM-Eintrag zu erstellen.
Im folgenden Beispiel wird das UDM-Feld metadata.event_timestamp
auf das Datum und die Uhrzeit festgelegt, zu dem das Rohprotokoll geparst wurde.
# Save the log parse date and time to the timestamp variable
mutate {
rename => {
"@timestamp" => "timestamp"
}
}
Im folgenden Beispiel wird das UDM-Feld metadata.event_timestamp
auf das Datum und die Uhrzeit festgelegt, die aus dem ursprünglichen Rohprotokoll extrahiert und in der Zwischenvariablen when
gespeichert wurden.
# Save the event timestamp to timestamp variable
mutate {
rename => {
"when" => "timestamp"
}
}
Verwenden Sie die folgenden Begriffe nicht als Variablen:
- collectiontimestamp
- createtimestamp
- event
- filename
- Nachricht
- Namespace
- Ausgabe
- onerrorcount
- timestamp
- Zeitzone
Speichern Sie jeden Datenwert in einem separaten UDM-Feld.
Speichern Sie nicht mehrere Felder in einem einzigen UDM-Feld, indem Sie sie mit einem Trennzeichen zusammenführen. Hier ein Beispiel:
"principal.user.first_name" => "first:%{first_name},last:%{last_name}"
Speichern Sie stattdessen jeden Wert in einem separaten UDM-Feld.
"principal.user.first_name" => "%{first_name}"
"principal.user.last_name" => "%{last_name}"
Verwenden Sie im Code Leerzeichen anstelle von Tabulatoren.
Verwenden Sie im Parsercode keine Tabulatoren. Verwenden Sie nur Leerzeichen und rücken Sie jeweils zwei Leerzeichen ein.
Führen Sie nicht mehrere Zusammenführungsaktionen in einem einzigen Vorgang aus.
Wenn Sie mehrere Felder in einem einzigen Vorgang zusammenführen, kann dies zu inkonsistenten Ergebnissen führen. Platzieren Sie merge
-Anweisungen stattdessen in separaten Vorgängen.
Ersetzen Sie beispielsweise Folgendes:
mutate {
merge => {
"security_result.category_details" => "category_details"
"security_result.category_details" => "super_category_details"
}
}
durch diesen Codeblock:
mutate {
merge => {
"security_result.category_details" => "category_details"
}
}
mutate {
merge => {
"security_result.category_details" => "super_category_details"
}
}
if
- oder if else
-Bedingte Ausdrücke auswählen
Wenn der getestete bedingte Wert immer nur eine Übereinstimmung haben kann, verwenden Sie die bedingte Anweisung if else
. Dieser Ansatz ist etwas effizienter. Wenn der getestete Wert jedoch mehrmals übereinstimmen könnte, verwenden Sie mehrere if
-Anweisungen und ordnen Sie die Anweisungen vom allgemeinsten Fall zum spezifischen Fall an.
Einen repräsentativen Satz von Logdateien zum Testen von Parseränderungen auswählen
Es empfiehlt sich, Parsercode mit Rohprotokollbeispielen in einer Vielzahl von Formaten zu testen. So können Sie eindeutige Protokolle oder Grenzfälle finden, die der Parser möglicherweise verarbeiten muss.
Dem Parsercode beschreibende Kommentare hinzufügen
Fügen Sie dem Parsercode Kommentare hinzu, in denen erklärt wird, warum die Anweisung wichtig ist, anstatt was sie bewirkt. Der Kommentar hilft allen, die den Parser verwalten, den Ablauf zu verfolgen. Hier ein Beispiel:
# only assign a Namespace if the source address is RFC 1918 or Loopback IP address
if [jsonPayload][id][orig_h] =~ /^(127(?:\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\{3\}$)|(10(?:\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\{3\}$)|(192\.168(?:\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\{2\}$)|(172\.(?:1[6-9]|2\d|3[0-1])(?:\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\{2\}$)/ {
mutate {
replace => {
"event1.idm.read_only_udm.principal.namespace" => "%{resource.labels.project_id}"
}
}
}
Zwischenvariablen frühzeitig initialisieren
Bevor Sie Werte aus dem ursprünglichen Rohprotokoll extrahieren, müssen Sie Zwischenvariablen initialisieren, die zum Speichern von Testwerten verwendet werden.
So wird verhindert, dass ein Fehler zurückgegeben wird, der darauf hinweist, dass die Zwischenvariable nicht vorhanden ist.
In der folgenden Anweisung wird der Wert in der Variablen product
dem UDM-Feld metadata.product_name
zugewiesen.
mutate{
replace => {
"event1.idm.read_only_udm.metadata.product_name" => "%{product}"
}
}
Wenn die Variable product
nicht vorhanden ist, erhalten Sie die folgende Fehlermeldung:
"generic::invalid_argument: pipeline failed: filter mutate (4) failed: replace failure: field \"event1.idm.read_only_udm.metadata.product_name\": source field \"product\": field not set"
Sie können eine on_error
-Anweisung hinzufügen, um den Fehler zu erfassen. Hier ein Beispiel:
mutate{
replace => {
"event1.idm.read_only_udm.metadata.product_name" => "%{product}"
}
on_error => "_error_does_not_exist"
}
In der vorherigen Beispielanweisung wird der Parsefehler in einer booleschen Zwischenvariablen namens _error_does_not_exist
abgefangen. Sie können die Variable product
nicht in einer bedingten Anweisung verwenden, z. B. if
.
Hier ein Beispiel:
if [product] != "" {
mutate{
replace => {
"event1.idm.read_only_udm.metadata.product_name" => "%{product}"
}
}
on_error => "_error_does_not_exist"
}
Im vorherigen Beispiel wird der folgende Fehler zurückgegeben, da die if
-Bedingungsklausel keine on_error
-Anweisungen unterstützt:
"generic::invalid_argument: pipeline failed: filter conditional (4) failed: failed to evaluate expression: generic::invalid_argument: "product" not found in state data"
Fügen Sie dazu einen separaten Anweisungsblock hinzu, in dem die Zwischenvariablen vor Ausführung der Anweisungen für den Extraktionsfilter (json
, csv
, xml
, kv
oder grok
) initialisiert werden.
Folgendes ist ein Beispiel.
filter {
# Initialize intermediate variables for any field you will use for a conditional check
mutate {
replace => {
"timestamp" => ""
"does_not_exist" => ""
}
}
# load the logs fields from the message field
json {
source => "message"
array_function => "split_columns"
on_error => "_not_json"
}
}
Im aktualisierten Parser-Code-Snippet werden die verschiedenen Szenarien mit einer bedingten Anweisung verarbeitet, um zu prüfen, ob das Feld vorhanden ist. Außerdem werden mit der on_error
-Anweisung mögliche Fehler behandelt.
SHA-256 in Base64 konvertieren
Im folgenden Beispiel wird der SHA-256-Wert extrahiert, in Base64 codiert, in einen Hexadezimalstring konvertiert und dann werden bestimmte Felder durch die extrahierten und verarbeiteten Werte ersetzt.
if [Sha256] != ""
{
base64
{
encoding => "RawStandard"
source => "Sha256"
target => "base64_sha256"
on_error => "base64_message_error"
}
mutate
{
convert =>
{
"base64_sha256" => "bytestohex"
}
on_error => "already_a_string"
}
mutate
{
replace =>
{
"event.idm.read_only_udm.network.tls.client.certificate.sha256" => "%{base64_sha256}"
"event.idm.read_only_udm.target.resource.name" => "%{Sha256}"
}
}
}
Fehler in Parseranweisungen verarbeiten
Es ist nicht ungewöhnlich, dass eingehende Protokolle ein unerwartetes Protokollformat haben oder fehlerhaft formatierte Daten enthalten.
Sie können den Parser so erstellen, dass er diese Fehler behandelt. Es wird empfohlen, dem Extraktionsfilter on_error
-Handler hinzuzufügen und dann die Zwischenvariable zu testen, bevor mit dem nächsten Segment der Parserlogik fortgefahren wird.
Im folgenden Beispiel wird der json
-Extraktionsfilter mit einer on_error
-Anweisung verwendet, um die boolesche Variable _not_json
festzulegen. Wenn _not_json
auf true
festgelegt ist, bedeutet das, dass der eingehende Logeintrag nicht im gültigen JSON-Format war und nicht erfolgreich geparst wurde. Wenn die Variable _not_json
den Wert false
hat, war der eingehende Logeintrag im gültigen JSON-Format.
# load the incoming log from the default message field
json {
source => "message"
array_function => "split_columns"
on_error => "_not_json"
}
Sie können auch testen, ob ein Feld das richtige Format hat. Im folgenden Beispiel wird geprüft, ob _not_json
auf true
gesetzt ist, was bedeutet, dass das Protokoll nicht im erwarteten Format vorliegt.
# Test that the received log matches the expected format
if [_not_json] {
drop { tag => "TAG_MALFORMED_MESSAGE" }
} else {
# timestamp is always expected
if [timestamp] != "" {
# ...additional parser logic goes here …
} else {
# if the timestamp field does not exist, it's not a log source
drop { tag => "TAG_UNSUPPORTED" }
}
}
So wird verhindert, dass das Parsen fehlschlägt, wenn Protokolle in einem falschen Format für den angegebenen Protokolltyp aufgenommen werden.
Verwenden Sie den Filter drop
mit der Variablen tag
, damit die Bedingung in der Tabelle „Aufnahmemesswerte“ in BigQuery erfasst wird.
TAG_UNSUPPORTED
TAG_MALFORMED_ENCODING
TAG_MALFORMED_MESSAGE
TAG_NO_SECURITY_VALUE
Der drop
-Filter verhindert, dass der Parser das Rohprotokoll verarbeitet, die Felder normalisiert und einen UDM-Eintrag erstellt. Das ursprüngliche Rohprotokoll wird weiterhin in Google Security Operations aufgenommen und kann dort mithilfe der Rohprotokollsuche durchsucht werden.
Der an die Variable tag
übergebene Wert wird in der Tabelle „Aufnahmemesswerte“ im Feld drop_reason_code
gespeichert. Sie können eine Ad-hoc-Abfrage für die Tabelle ausführen, die etwa so aussieht:
SELECT
log_type,
drop_reason_code,
COUNT(drop_reason_code) AS count
FROM `datalake.ingestion_metrics`
GROUP BY 1,2
ORDER BY 1 ASC
Fehlerbehebung bei Validierungsfehlern
Beim Erstellen eines Parsers können Validierungsfehler auftreten, z. B. wenn ein Pflichtfeld im UDM-Eintrag nicht festgelegt ist. Der Fehler sieht in etwa so aus:
Error: generic::unknown: invalid event 0: LOG_PARSING_GENERATED_INVALID_EVENT: "generic::invalid_argument: udm validation failed: target field is not set"
Der Parsercode wird erfolgreich ausgeführt, aber der generierte UDM-Eintrag enthält nicht alle erforderlichen UDM-Felder, wie durch den für metadata.event_type
festgelegten Wert definiert. Weitere Beispiele für mögliche Ursachen für diesen Fehler:
- Wenn
metadata.event_type
=USER_LOGIN
und das UDM-Feldtarget.user value
nicht festgelegt ist. - Wenn
metadata.event_type
=NETWORK_CONNECTION
und das UDM-Feldtarget.hostname
nicht festgelegt ist.
Weitere Informationen zum UDM-Feld metadata.event_type
und zu den erforderlichen Feldern finden Sie im Leitfaden zur UDM-Nutzung.
Eine Möglichkeit zur Fehlerbehebung bei dieser Art von Fehler besteht darin, zuerst statische Werte für UDM-Felder festzulegen. Nachdem Sie alle erforderlichen UDM-Felder definiert haben, sehen Sie sich das ursprüngliche Rohprotokoll an, um zu ermitteln, welche Werte geparst und im UDM-Eintrag gespeichert werden sollen. Wenn das ursprüngliche Rohprotokoll bestimmte Felder nicht enthält, müssen Sie möglicherweise Standardwerte festlegen.
Im Folgenden finden Sie eine Beispielvorlage für einen USER_LOGIN
-Ereignistyp, die diesen Ansatz veranschaulicht.
Beachten Sie Folgendes:
- In der Vorlage werden Zwischenvariablen initialisiert und jeweils auf einen statischen String gesetzt.
- Mit dem Code im Abschnitt Feldzuweisung werden die Werte in Zwischenvariablen auf UDM-Felder festgelegt.
Sie können diesen Code erweitern, indem Sie zusätzliche Zwischenvariablen und UDM-Felder hinzufügen. Nachdem Sie alle UDM-Felder ermittelt haben, die ausgefüllt werden müssen, gehen Sie so vor:
Fügen Sie unter Eingabekonfiguration Code hinzu, mit dem Felder aus dem ursprünglichen Rohprotokoll extrahiert und die Werte den Zwischenvariablen zugewiesen werden.
Fügen Sie unter Datenextraktion Code hinzu, mit dem der Ereigniszeitstempel aus dem ursprünglichen Rohprotokoll extrahiert, transformiert und der Zwischenvariablen zugewiesen wird.
Ersetzen Sie bei Bedarf den in jeder Zwischenvariablen festgelegten initialisierten Wert durch einen leeren String.
filter {
mutate {
replace => {
# UDM > Metadata
"metadata_event_timestamp" => ""
"metadata_vendor_name" => "Example"
"metadata_product_name" => "Example SSO"
"metadata_product_version" => "1.0"
"metadata_product_event_type" => "login"
"metadata_product_log_id" => "12345678"
"metadata_description" => "A user logged in."
"metadata_event_type" => "USER_LOGIN"
# UDM > Principal
"principal_ip" => "192.168.2.10"
# UDM > Target
"target_application" => "Example Connect"
"target_user_user_display_name" => "Mary Smith"
"target_user_userid" => "mary@example.com"
# UDM > Extensions
"auth_type" => "SSO"
"auth_mechanism" => "USERNAME_PASSWORD"
# UDM > Security Results
"securityResult_action" => "ALLOW"
"security_result.severity" => "LOW"
}
}
# ------------ Input Configuration --------------
# Extract values from the message using one of the extraction filters: json, kv, grok
# ------------ Date Extract --------------
# If the date {} function is not used, the default is the normalization process time
# ------------ Field Assignment --------------
# UDM Metadata
mutate {
replace => {
"event1.idm.read_only_udm.metadata.vendor_name" => "%{metadata_vendor_name}"
"event1.idm.read_only_udm.metadata.product_name" => "%{metadata_product_name}"
"event1.idm.read_only_udm.metadata.product_version" => "%{metadata_product_version}"
"event1.idm.read_only_udm.metadata.product_event_type" => "%{metadata_product_event_type}"
"event1.idm.read_only_udm.metadata.product_log_id" => "%{metadata_product_log_id}"
"event1.idm.read_only_udm.metadata.description" => "%{metadata_description}"
"event1.idm.read_only_udm.metadata.event_type" => "%{metadata_event_type}"
}
}
# Set the UDM > auth fields
mutate {
replace => {
"event1.idm.read_only_udm.extensions.auth.type" => "%{auth_type}"
}
merge => {
"event1.idm.read_only_udm.extensions.auth.mechanism" => "auth_mechanism"
}
}
# Set the UDM > principal fields
mutate {
merge => {
"event1.idm.read_only_udm.principal.ip" => "principal_ip"
}
}
# Set the UDM > target fields
mutate {
replace => {
"event1.idm.read_only_udm.target.user.userid" => "%{target_user_userid}"
"event1.idm.read_only_udm.target.user.user_display_name" => "%{target_user_user_display_name}"
"event1.idm.read_only_udm.target.application" => "%{target_application}"
}
}
# Set the UDM > security_results fields
mutate {
merge => {
"security_result.action" => "securityResult_action"
}
}
# Set the security result
mutate {
merge => {
"event1.idm.read_only_udm.security_result" => "security_result"
}
}
# ------------ Output the event --------------
mutate {
merge => {
"@output" => "event1"
}
}
}
Unstrukturierten Text mit einer Grok-Funktion parsen
Wenn Sie eine Grok-Funktion zum Extrahieren von Werten aus unstrukturiertem Text verwenden, können Sie vordefinierte Grok-Muster und reguläre Ausdrucksanweisungen verwenden. Grok-Muster machen Code leichter lesbar. Wenn der reguläre Ausdruck keine Kurzzeichen (z. B. \w
, \s
) enthält, können Sie die Anweisung direkt in den Parsercode kopieren und einfügen.
Da Grok-Muster eine zusätzliche Abstraktionsebene in der Anweisung sind, kann die Fehlerbehebung bei einem Fehler komplizierter werden. Im folgenden Beispiel wird eine Grok-Funktion mit vordefinierten Grok-Mustern und regulären Ausdrücken verwendet.
grok {
match => {
"message" => [
"%{NUMBER:when}\\s+\\d+\\s%{SYSLOGHOST:srcip} %{WORD:action}\\/%{NUMBER:returnCode} %{NUMBER:size} %{WORD:method} (?P<url>\\S+) (?P<username>.*?) %{WORD}\\/(?P<tgtip>\\S+).*"
]
}
}
Eine Extraktionsabfrage ohne Grok-Muster kann leistungsfähiger sein. Im folgenden Beispiel werden beispielsweise weniger als die Hälfte der Verarbeitungsschritte für die Übereinstimmung benötigt. Bei einer Protokollquelle mit potenziell hohem Volumen ist dies ein wichtiger Aspekt.
Unterschiede zwischen RE2- und PCRE-Regulären Ausdrücken
Die Parser von Google Security Operations verwenden RE2 als reguläre Ausdrucks-Engine. Wenn Sie mit der PCRE-Syntax vertraut sind, werden Ihnen möglicherweise Unterschiede auffallen. Hier ein Beispiel:
Hier eine PCRE-Anweisung: (?<_custom_field>\w+)\s
Im Folgenden finden Sie eine RE2-Anweisung für Parsercode: (?P<_custom_field>\\w+)\\s
Escape-Zeichen müssen mit einem Escapezeichen versehen werden.
Google Security Operations speichert eingehende Rohprotokolldaten im JSON-codierten Format. So wird sichergestellt, dass Zeichenfolgen, die wie eine Kurzschreibweise für reguläre Ausdrücke aussehen, als Literalstring interpretiert werden. Beispiel: \t
wird als Literalstring und nicht als Tabulatorzeichen interpretiert.
Das folgende Beispiel zeigt ein ursprüngliches Rohprotokoll und das im JSON-Format codierte Protokoll.
Beachten Sie das Escape-Zeichen vor jedem umgekehrten Schrägstrich, der den Begriff entry
umgibt.
Im Folgenden finden Sie das ursprüngliche Rohprotokoll:
field=\entry\
Im Folgenden sehen Sie das Protokoll im JSON-codierten Format:
field=\\entry\\
Wenn Sie einen regulären Ausdruck im Parsercode verwenden, müssen Sie zusätzliche Escape-Zeichen hinzufügen, wenn Sie nur den Wert extrahieren möchten. Wenn Sie einen umgekehrten Schrägstrich im ursprünglichen Rohprotokoll abgleichen möchten, verwenden Sie in der Extraktionsanweisung vier umgekehrte Schrägstriche.
Hier ist ein regulärer Ausdruck für Parsercode:
^field=\\\\(?P<_value>.*)\\\\$
Das ist das generierte Ergebnis. In der Gruppe mit dem Namen _value
wird der Begriff entry
gespeichert:
"_value": "entry"
Wenn Sie eine Standard-Regulärausdrucksanweisung in Parsercode verschieben, müssen Sie die Kurzzeichen für reguläre Ausdrücke in der Extraktionsanweisung maskieren.
Ändern Sie beispielsweise \s
in \\s
.
Lassen Sie reguläre Ausdrucks-Sonderzeichen unverändert, wenn sie in der Extraktionsbeschreibung doppelt maskiert sind. \\
bleibt beispielsweise unverändert als \\
.
Hier ein Beispiel für einen regulären Ausdruck:
^.*?\\\"(?P<_user>[^\\]+)\\\"\s(?:(logged\son|logged\soff))\s.*?\\\"(?P<_device>[^\\]+)\\\"\.$
Der folgende reguläre Ausdruck wird so geändert, dass er im Parsercode funktioniert.
^.*?\\\"(?P<_user>[^\\\\]+)\\\"\\s(?:(logged\\son|logged\\soff))\\s.*?\\\"(?P<_device>[^\\\\]+)\\\"\\.$
In der folgenden Tabelle wird zusammengefasst, wann ein regulärer Ausdruck zusätzliche Escape-Zeichen enthalten muss, bevor er in den Parsercode eingefügt wird.
Regulärer Ausdruck | Geänderter regulärer Ausdruck für Parsercode | Beschreibung der Änderung |
---|---|---|
\s |
\\s |
Kurzzeichen müssen mit einem Escapezeichen versehen werden. |
\. |
\\. |
Reservierte Zeichen müssen mit Escapezeichen versehen werden. |
\\" |
\\\" |
Reservierte Zeichen müssen mit Escapezeichen versehen werden. |
\] |
\\] |
Reservierte Zeichen müssen mit Escapezeichen versehen werden. |
\| |
\\| |
Reservierte Zeichen müssen mit Escapezeichen versehen werden. |
[^\\]+ |
[^\\\\]+ |
Sonderzeichen innerhalb einer Zeichenklassengruppe müssen maskiert werden. |
\\\\ |
\\\\ |
Für Sonderzeichen außerhalb einer Zeichenklassengruppe oder Kurzzeichen ist kein zusätzliches Escapezeichen erforderlich. |
Reguläre Ausdrücke müssen eine benannte Erfassungsgruppe enthalten
Ein regulärer Ausdruck wie "^.*$"
ist eine gültige RE2-Syntax. Im Parsercode schlägt er jedoch mit folgendem Fehler fehl:
"ParseLogEntry failed: pipeline failed: filter grok (0) failed: failed to parse data with all match
patterns"
Sie müssen dem Ausdruck eine gültige Erfassungsgruppe hinzufügen. Grok-Muster enthalten standardmäßig eine benannte Erfassungsgruppe. Wenn Sie Überschreibungen mit regulären Ausdrücken verwenden, müssen Sie eine benannte Gruppe angeben.
Im Folgenden finden Sie ein Beispiel für einen regulären Ausdruck im Parsercode:
"^(?P<_catchall>.*$)"
Das folgende Ergebnis zeigt den Text, der der Gruppe mit dem Namen _catchall
zugewiesen ist.
"_catchall": "User \"BOB\" logged on to workstation \"DESKTOP-01\"."
Verwenden Sie zu Beginn eine allgemeine Gruppe, während Sie den Ausdruck erstellen.
Beginnen Sie beim Erstellen einer Extraktionsanweisung mit einem Ausdruck, der mehr erfasst, als Sie möchten. Erweitern Sie den Ausdruck dann nach und nach.
Im folgenden Beispiel wird zuerst eine benannte Gruppe (_catchall
) verwendet, die der gesamten Nachricht entspricht. Anschließend wird der Ausdruck in Schritten erstellt, indem zusätzliche Textabschnitte abgeglichen werden. Mit jedem Schritt enthält die Gruppe mit dem Namen _catchall
immer weniger vom ursprünglichen Text. Fahren Sie fort und wiederholen Sie die Schritte nacheinander, bis die Nachricht übereinstimmt._catchall
Schritt | Regulärer Ausdruck im Parsercode | Ausgabe der _catchall -erfassten Gruppe |
---|---|---|
1 | "^(?P<_catchall>.*$)" |
User \"BOB\" logged on to workstation \"DESKTOP-01\". |
2 | ^User\s\\\"(?P<_catchall>.*$) |
BOB\" logged on to workstation \"DESKTOP-01\". |
3 | ^User\s\\\"(?P<_user>.*?)\\\"\s(?P<_catchall>.*$) |
logged on to workstation \"DESKTOP-01\". |
Fahren Sie so lange fort, bis der Ausdruck mit dem gesamten Textstring übereinstimmt. |
Kurzzeichen im regulären Ausdruck maskieren
Denken Sie daran, reguläre Ausdruckskürzel zu maskieren, wenn Sie den Ausdruck im Parsercode verwenden. Im Folgenden finden Sie ein Beispiel für einen Textstring und den Standardregulären Ausdruck, mit dem das erste Wort This
extrahiert wird.
This is a sample log.
Mit dem folgenden Standardregulären Ausdruck wird das erste Wort This
extrahiert.
Wenn Sie diesen Ausdruck jedoch in Parsercode ausführen, fehlt im Ergebnis der Buchstabe s
.
Standardregulärer Ausdruck | Ausgabe der _firstWord -erfassten Gruppe |
---|---|
"^(?P<_firstWord>[^\s]+)\s.*$" |
"_firstWord": "Thi", |
Das liegt daran, dass reguläre Ausdrücke im Parsercode ein zusätzliches Escape-Zeichen erfordern, das den Kurzzeichen hinzugefügt wird. Im vorherigen Beispiel muss \s
in \\s
geändert werden.
Überarbeiteter regulärer Ausdruck für Parsercode | Ausgabe der _firstWord -genannten Erfassungsgruppe |
---|---|
"^(?P<_firstWord>[^\\s]+)\\s.*$" |
"_firstWord": "This", |
Dies gilt nur für die Kurzzeichen wie \s
, \r
und \t
.
Andere Zeichen wie „“ müssen nicht weiter maskiert werden.
Vollständiges Beispiel
In diesem Abschnitt werden die vorherigen Regeln als End-to-End-Beispiel beschrieben. Hier sehen Sie einen unstrukturierten Textstring und den Standardregulären Ausdruck, der zum Parsen des Strings geschrieben wurde. Schließlich enthält es den geänderten regulären Ausdruck, der im Parsercode verwendet wird.
Im Folgenden sehen Sie den ursprünglichen Textstring.
User "BOB" logged on to workstation "DESKTOP-01".
Im Folgenden finden Sie einen regulären RE2-Ausdruck, der den Textstring analysiert.
^.*?\\\"(?P<_user>[^\\]+)\\\"\s(?:(logged\son|logged\soff))\s.*?\\\"(?P<_device>[^\\]+)\\\"\.$
Mit diesem Ausdruck werden die folgenden Felder extrahiert.
Übereinstimmungsgruppe | Zeichenposition | Textstring |
---|---|---|
Vollständige Übereinstimmung | 0-53 | User \"BOB\" logged on to workstation \"DESKTOP-01\". |
Gruppe „_user“ | 7-10 | BOB |
Gruppe 2. | 13-22 | logged on |
Gruppe „_device“ | 40-50 | DESKTOP-01 |
Das ist der geänderte Ausdruck. Der standardmäßige RE2-Reguläre Ausdruck wurde so geändert, dass er im Parsercode funktioniert.
^.*?\\\"(?P<_user>[^\\\\]+)\\\"\\s(?:(logged\\son|logged\\soff))\\s.*?\\\"(?P<_device>[^\\\\]+)\\\"\\.$
Benötigen Sie weitere Hilfe? Antworten von Community-Mitgliedern und Google SecOps-Experten erhalten