Présente des références générales pour l'utilisation du langage Structured Process Language (SPL) dans différents scénarios.
Optimisation des instructions SPL
Plusieurs instructions SPL peuvent produire le même résultat de traitement des données. Rédiger des instructions SPL concises et efficaces simplifie la maintenance et améliore les performances. Le tableau suivant propose quelques suggestions.
|
Suggestion |
Avant optimisation |
Après optimisation |
|
Combinez les clauses where consécutives en une seule. |
|
|
|
Combinez les clauses extend consécutives en une seule. |
|
|
|
Remplacez extend + project-away par project-rename. |
|
|
|
Modifiez les valeurs des champs sur place au lieu d'utiliser extend pour créer de nouveaux champs, sauf si nécessaire. |
|
|
Gestion des champs spéciaux
Champs temporels
Lors de l'exécution SPL, le type de données des champs temporels dans les journaux Simple Log Service est toujours INTEGER ou BIGINT. Ces champs incluent le champ d'horodatage des données __time__ et la partie nanoseconde du champ d'horodatage des données __time_ns_part__.
Pour mettre à jour l'horodatage des données, utilisez l'instruction extend et assurez-vous que la nouvelle valeur est un INTEGER ou un BIGINT. Les autres instructions ne peuvent pas agir sur les champs temporels. Leur comportement est le suivant :
project, project-away et project-rename : ces instructions conservent les champs temporels par défaut. Vous ne pouvez ni les renommer ni les écraser.
parse-regexp et parse-json : si le résultat de l'extraction inclut des champs temporels, ils sont ignorés.
Exemple
Extrayez les valeurs des champs temporels à partir d'une chaîne de temps existante.
-
Instruction SPL
* | parse-regexp time, '([\d\-\s:]+)\.(\d+)' as ts, ms | extend ts=date_parse(ts, '%Y-%m-%d %H:%i:%S') | extend __time__=cast(to_unixtime(ts) as INTEGER) | extend __time_ns_part__=cast(ms as INTEGER) * 1000000 | project-away ts, ms -
Données d'entrée
time: '2023-11-11 01:23:45.678' -
Résultat de sortie
__time__: 1699637025 __time_ns_part__: 678000000 time: '2023-11-11 01:23:45.678'
Noms de champs contenant des caractères spéciaux
Si un nom de champ contient des espaces ou d'autres caractères spéciaux, entourez-le de guillemets doubles (") lorsque vous y faites référence. Par exemple, si un champ est nommé A B et contient un espace, référencez-le sous la forme "A B" dans une instruction SPL :
* | where "A B" like '%error%'
Noms de champs insensibles à la casse
Dans les requêtes d'analyse SLS, les noms de champs référencés dans les instructions SPL sont insensibles à la casse. Par exemple, si un journal contient un champ nommé Method, vous pouvez y faire référence sous la forme method ou METHOD dans une instruction SPL.
Cela s'applique à la fonctionnalité de requête d'analyse de Simple Log Service. Pour plus d'informations, consultez Requêtes d'analyse.
Exemple
Utilisez un nom de champ insensible à la casse dans une clause where.
-
Instruction SPL
* | where METHOD like 'Post%' -
Données d'entrée
Method: 'PostLogstoreLogs' -
Résultat de sortie
Method: 'PostLogstoreLogs'
Gestion des conflits de noms de champs
Lors du chargement des journaux ou de l'exécution SPL, le traitement sensible à la casse peut provoquer des conflits de noms de champs. Par exemple, un journal brut peut contenir à la fois les champs Method et method. SPL résout ces conflits différemment selon le scénario.
Pour éviter ces situations, standardisez les noms de champs dans vos journaux bruts.
Conflits dans les données d'entrée
Si un journal brut contient des champs dont les noms sont identiques lorsque la casse est ignorée, tels que Status et status, SPL sélectionne aléatoirement un champ pour l'entrée et ignore l'autre. Par exemple :
-
Instruction SPL
* | extend status_cast = cast(status as bigint) -
Données d'entrée
Status: '200' status: '404' -
Résultat du traitement
-
Possibilité 1 : La valeur du champ Status est conservée.
Status: '200' -- The first column is retained, and the second column is discarded. status_cast: '200' -
Possibilité 2 : La valeur du champ status est conservée.
status: '404' -- The second column is retained, and the first column is discarded. Status_cast: '404'
-
Conflits dans les résultats de sortie
Scénario 1 : Conflits de champs de données brutes
Lors de l'exécution SPL, des champs dont les noms sont identiques lorsque la casse est ignorée peuvent être générés. SPL en sélectionne un au hasard pour la sortie. Par exemple, si un champ de journal contient une chaîne JSON, l'utilisation de l'instruction parse-json peut créer des champs avec des noms conflictuels :
-
Instruction SPL
* | parse-json content -
Données d'entrée
content: '{"Method": "PostLogs", "method": "GetLogs", "status": "200"}' -
Résultat de sortie
-
Possibilité 1 : Le champ Method est conservé.
content: '{"Method": "PostLogs", "method": "GetLogs", "status": "200"}' Method: 'PostLogs' -- The Method field is retained. status: '200' -
Possibilité 2 : Le champ method est conservé.
content: '{"Method": "PostLogs", "method": "GetLogs", "status": "200"}' method: 'GetLogs' -- The method field is retained. status: '200'
-
Scénario 2 : Conflits avec les champs de données nouvellement générés
Pour éviter toute ambiguïté, SPL conserve la casse des nouveaux noms de champs générés explicitement par les instructions. Cela s'applique aux noms de champs générés par l'instruction extend et aux noms de champs explicitement spécifiés à l'aide de as dans les instructions parse-regexp et parse-csv.
Par exemple, si vous utilisez extend pour créer un nouveau champ Method, le nom du champ résultant reste Method.
-
Instruction SPL
* | extend Method = 'Post' -
Données d'entrée
Status: '200' -
Résultat de sortie
Status: '200' Method: 'Post'
Gestion des conflits de champs réservés SLS
Cela s'applique aux fonctionnalités de consommation en temps réel et de requête d'analyse de Simple Log Service.
Pour obtenir la liste complète des champs réservés, consultez Champs réservés. SPL lit les données depuis la structure LogGroup en tant qu'entrée. Pour plus d'informations sur la définition de LogGroup, consultez Encodage des données. Si les données brutes écrites dans Simple Log Service ne sont pas encodées au format LogGroup standard, certains champs réservés peuvent apparaître dans LogContent au lieu de leur emplacement standard. SPL gère ces champs réservés comme suit :
Pour les champs
__source__,__topic__,__time__et__time_ns_part__, SPL lit leurs valeurs à partir de la structure LogGroup standard et ignore tous les champs portant les mêmes noms dans LogContent.Pour les champs de tag avec le préfixe
__tag__:, SPL tente d'abord de lire leurs valeurs à partir de la structure LogGroup standard. Si aucune valeur n'est trouvée, SPL la lit depuis LogContent. Par exemple, pour le champ__tag__:ip, SPL tente d'abord de lire le champ avec la cléipdepuis la liste LogTag. Si le champ n'existe pas, SPL lit ensuite le champ de journal avec la clé__tag__:ipdepuis les champs de journal personnalisés dans LogContent.
Le champ __line__ pour la recherche en texte intégral
Cela s'applique à la fonctionnalité de requête d'analyse SLS.
Pour filtrer les journaux bruts dans la console ou en utilisant l'opération d'API GetLogstoreLogs, utilisez le champ __line__.
Exemple
-
Recherchez le mot-clé error dans les journaux.
* | where __line__ like '%error%' -
Si un journal contient un champ nommé
__line__, entourez le nom du champ de backticks pour y faire référence.* | where `__line__` ='20'
Politiques de conservation et d'écrasement des valeurs
Lorsqu'une instruction SPL est exécutée et qu'un champ de sortie porte le même nom qu'un champ d'entrée existant, la valeur du champ est déterminée par la politique suivante :
Ces politiques ne s'appliquent pas à l'instruction extend. Pour extend, en cas de conflit de nom de champ, la nouvelle valeur est toujours utilisée.
Types de données incohérents entre les anciennes et nouvelles valeurs
La valeur d'origine du champ d'entrée est conservée.
Exemple
-
Exemple 1 : Un champ renommé à partir d'une instruction project présente un nom conflictuel.
-
Instruction SPL
* | extend status=cast(status as BIGINT) -- Convert the type of the status field to BIGINT. | project code=status -- The new value's type (BIGINT) differs from the old value's type (VARCHAR), so the old value is kept. -
Données d'entrée
status: '200' code: 'Success' -
Résultat de sortie
code: 'Success'
-
-
Exemple 2 : Un champ extrait à partir d'une instruction parse-json présente un nom conflictuel.
-
Instruction SPL
* | extend status=cast(status as BIGINT) -- Convert the type of the status field to BIGINT. | parse-json content -- The old type of status is BIGINT and the new type is VARCHAR. The old value is retained. -
Données d'entrée
status: '200' content: '{"status": "Success", "body": "this is test"}' -
Résultat de sortie
content: '{"status": "Success", "body": "this is test"}' status: 200 body: 'this is test'
-
Types de données cohérents entre les anciennes et nouvelles valeurs
Si la valeur d'entrée est nulle, la nouvelle valeur est utilisée. Sinon, le comportement est déterminé par le paramètre mode dans l'instruction, tel que défini dans le tableau suivant.
Si le paramètre mode n'est pas spécifié dans l'instruction, sa valeur par défaut est overwrite.
|
Mode |
Description |
|
overwrite |
Écrase l'ancienne valeur avec la nouvelle valeur. |
|
preserve |
Conserve l'ancienne valeur et ignore la nouvelle valeur. |
Exemple
-
Exemple 1 : Un champ renommé à partir d'une instruction project présente un nom conflictuel et le même type. Le mode par défaut est overwrite.
Instruction SPL
* | project code=status -- The old and new types of code are both VARCHAR. The new value is used based on the overwrite mode.-
Données d'entrée
status: '200' code: 'Success' -
Résultat de sortie
code: '200'
-
Exemple 2 : Un champ extrait à partir d'une instruction parse-json présente un nom conflictuel et le même type. Le mode par défaut est overwrite.
-
Instruction SPL
* | parse-json content -- The old and new types of status are both VARCHAR. The new value is used based on the overwrite mode. -
Données d'entrée
status: '200' content: '{"status": "Success", "body": "this is test"}' -
Résultat de sortie
content: '{"status": "Success", "body": "this is test"}' status: 'Success' body: 'this is test'
-
-
Exemple 3 : Un champ extrait à partir d'une instruction parse-json présente un nom conflictuel et le même type. Le mode est défini sur preserve.
-
Instruction SPL
* | parse-json -mode='preserve' content -- The old and new types of status are both VARCHAR. The old value is retained based on the preserve mode. -
Données d'entrée
status: '200' content: '{"status": "Success", "body": "this is test"}' -
Résultat de sortie
content: '{"status": "Success", "body": "this is test"}' status: '200' body: 'this is test'
-
Conversion de type de données
Type initial
Lorsque SPL traite les données, tous les champs d'entrée sont initialement de type VARCHAR, à l'exception des champs de temps des journaux. Si le traitement ultérieur nécessite un type de données différent, vous devez effectuer une conversion de type explicite.
Exemple
Pour filtrer les journaux d'accès avec un code d'état 5xx, convertissez le champ status en type BIGINT avant la comparaison.
* -- The initial type of the status field is VARCHAR.
| where cast(status as BIGINT) >= 500 -- Convert the type of the status field to BIGINT, and then perform the comparison.
Conservation du type
Après avoir utilisé l'instruction extend pour convertir le type de données d'un champ, le traitement ultérieur conserve le type converti.
Exemple
* -- A Logstore is used as input data. Except for time fields, all fields are initially of the VARCHAR type.
| where __source__='127.0.0.1' -- Filter on the __source__ field.
| extend status=cast(status as BIGINT) -- Convert the type of the status field to BIGINT.
| project status, content
| where status>=500 -- The type of the status field remains BIGINT, so it can be directly compared with the number 500.
Gestion des valeurs nulles dans les expressions SPL
Génération de valeurs nulles
Lors du traitement des données SPL, des valeurs nulles sont générées dans les scénarios suivants :
Si un champ utilisé dans une expression SPL n'existe pas dans les données d'entrée, sa valeur est traitée comme nulle lors des calculs.
Si une exception se produit lors du calcul d'une expression SPL, le résultat est nul. Par exemple, une conversion de type cast échoue ou un index de tableau est hors limites.
Exemple
-
Si un champ n'existe pas, sa valeur est traitée comme nulle dans les calculs.
-
Instruction SPL
* | extend withoutStatus=(status is null) -
Données d'entrée
# Entry 1 status: '200' code: 'Success' # Entry 2 code: 'Success' -
Résultat de sortie
# Entry 1 status: '200' code: 'Success' withoutStatus: false # Entry 2 code: 'Success' withoutStatus: true
-
-
Si une exception se produit lors du calcul, le résultat est nul.
-
Instruction SPL
* | extend code=cast(code as BIGINT) -- Failed to convert the code field to BIGINT. | extend values=json_parse(values) | extend values=cast(values as ARRAY(BIGINT)) | extend last=arr[10] -- Array index out of bounds. -
Données d'entrée
status: '200' code: 'Success' values: '[1,2,3]' -
Résultat de sortie
status: '200' code: null values: [1, 2, 3] last: null
-
Élimination des valeurs nulles
Pour éliminer les valeurs nulles lors des calculs, utilisez l'expression COALESCE. Elle renvoie la première valeur non nulle d'une liste d'expressions. Vous pouvez également spécifier une valeur par défaut à utiliser si toutes les expressions sont évaluées à nul.
Exemple
Lisez le dernier élément d'un tableau. Si le tableau est vide, la valeur par défaut est 0.
-
Instruction SPL
* | extend values=json_parse(values) | extend values=cast(values as ARRAY(BIGINT)) | extend last=COALESCE(values[3], values[2], values[1], 0) -
Données d'entrée
# Entry 1 values: '[1, 2, 3]' # Entry 2 values: '[]' -
Résultat de sortie
# Entry 1 values: [1, 2, 3] last: 3 # Entry 2 values: [] last: 0
Échappement des caractères
Guillemets simples
Les guillemets simples sont utilisés pour entourer un littéral de chaîne. Si le littéral de chaîne contient un guillemet simple, vous devez utiliser un guillemet simple supplémentaire pour l'échapper.
Exemple
-
Instruction SPL
* | extend user = 'Alice' | extend phone = 'Alice''s Phone' -
Résultat de sortie
user: Alice phone: Alice's Phone
Guillemets doubles
Les guillemets doubles sont utilisés pour entourer un nom de champ. Si le nom de champ contient un guillemet double, vous devez utiliser un guillemet double supplémentaire pour l'échapper.
Exemple
-
Instruction SPL
* | extend user_name = 'Alice' | extend "user name" = 'Alice' | extend "user""name" = 'Alice' -
Résultat de sortie
user_name: Alice user name: Alice user"name: Alice
Autres caractères spéciaux
Exemple 1
Dans SPL, la barre oblique inverse (\) n'est pas un caractère d'échappement et est donc conservée telle quelle.
-
Instruction SPL
* | extend a = 'foo\tbar' | extend b = 'foo\nbar' -
Résultat de sortie
a: foo\tbar b: foo\nbar
Exemple 2
Si une chaîne doit inclure des caractères spéciaux, tels qu'un caractère de tabulation ou un saut de ligne, vous pouvez utiliser la fonction chr pour concaténer des chaînes.
-
Instruction SPL
* | extend a = concat('foo', chr(9), 'bar') | extend b = concat('foo', chr(10), 'bar') -
Résultat de sortie
a: foo bar b: foo bar
Gestion des erreurs
Erreur de syntaxe
Des erreurs de syntaxe se produisent lorsqu'une instruction SPL est mal formée, par exemple un nom d'instruction incorrect, une erreur de référence de mot-clé ou une erreur de spécification de type. Lorsqu'une erreur de syntaxe se produit, SPL ne traite aucune donnée. Corrigez l'instruction en fonction du message d'erreur.
Erreur de données
Une erreur de données se produit lorsqu'une fonction ou une conversion échoue lors de l'exécution SPL. SPL définit le champ résultant sur null. Comme des erreurs de données peuvent se produire sur n'importe quelle ligne, SPL échantillonne aléatoirement et ne renvoie que certains messages d'erreur. Vous pouvez ignorer ces erreurs ou modifier l'instruction SPL en fonction du contenu des données.
Les erreurs de données n'arrêtent pas l'ensemble du processus d'exécution. L'instruction SPL renvoie toujours des résultats, mais le champ où l'erreur s'est produite est défini sur null.
Délai d'exécution dépassé
Une instruction SPL contient diverses instructions, et leur temps d'exécution varie en fonction du scénario de données. Si le temps d'exécution total dépasse la période de délai d'attente par défaut, l'exécution s'arrête et une erreur de délai d'attente est renvoyée avec un résultat vide. La période de délai d'attente par défaut varie pour les requêtes d'analyse, la consommation en temps réel et la collecte Logtail.
Pour résoudre cette erreur, simplifiez votre instruction SPL afin de réduire sa complexité, par exemple en optimisant les expressions régulières complexes ou en réduisant le nombre de pipelines.
Limite de mémoire dépassée
Une instruction SPL contient diverses instructions, et leur consommation de mémoire varie en fonction du scénario de données. L'exécution SPL est limitée à un quota de mémoire spécifique. Si ce quota est dépassé, l'exécution échoue et une erreur de limite de mémoire dépassée est renvoyée avec un résultat vide. Le quota de mémoire par défaut varie pour les requêtes d'analyse, la consommation en temps réel et la collecte Logtail.
Pour résoudre cette erreur, simplifiez votre instruction SPL afin de réduire sa complexité, réduisez le nombre de pipelines ou vérifiez si la taille des données brutes est trop importante.