Ce document décrit de manière générale le langage de requête Logging que vous utilisez pour interroger et filtrer les données Cloud Logging.
Pour des informations détaillées sur la conception du langage de requête Logging, consultez les spécifications formelles de filtrage des API Google.
Pour obtenir des exemples de requêtes courantes que vous pouvez utiliser, consultez la page Exemples de requêtes avec l'explorateur de journaux.
Présentation
Vous pouvez utiliser le langage de requête Logging dans l'explorateur de journaux de Google Cloud Console, l'API Logging ou l'interface de ligne de commande. Vous pouvez utiliser le langage de requête Logging pour interroger des données et écrire des filtres afin de créer des récepteurs et des métriques basées sur les journaux.
Une requête est une expression booléenne qui délimite un sous-ensemble des entrées de journal d'une ressource Google Cloud sélectionnée (projet ou dossier Google Cloud par exemple).
Vous pouvez créer des requêtes basées sur le champ indexé de LogEntry
à l'aide des opérateurs logiques AND
et OR
.
En utilisant le champ resource.type
dans les exemples suivants, la grammaire du langage de requête Logging se présente comme suit:
Restriction simple :
resource.type = "k8s_cluster"
Restriction conjonctive :
resource.type = "k8s_cluster" AND severity = "ERROR"
Restriction disjonctive :
resource.type = "k8s_cluster" OR resource.type = "gce_instance"
- Vous pouvez également utiliser :
resource.type = ("k8s_cluster" OR "gce_instance")
- Vous pouvez également utiliser :
Expression complexe conjonctive/disjonctive :
resource.type = "k8s_cluster" AND (severity = "ERROR" OR "error")
Voici un exemple de requête:
resource.type = "gce_instance" AND severity >= "ERROR" AND NOT textPayload:robot
Cette requête récupère les entrées de journal de Compute Engine dont les valeurs de gravité sont au moins de ERROR
et dont le champ textPayload
ne contient pas la chaîne robot
. Les comparaisons de chaînes ne sont pas sensibles à la casse. Les noms resource
, severity
et textPayload
sont définis dans le type LogEntry
.
Syntaxe
Les sections suivantes présentent la syntaxe du langage de requête Logging et expliquent en détail comment les requêtes sont structurées et comment la correspondance est appliquée. Certains exemples utilisent des commentaires pour fournir du texte explicatif.
Veuillez noter les points suivants :
La longueur d'une requête ne doit pas dépasser 20 000 caractères.
Le langage de requête Logging n'est pas sensible à la casse, à l'exception des expressions régulières.
Résumé de la syntaxe
La syntaxe du langage de requête Logging peut être considérée en termes de requêtes et de comparaisons.
Une requête est une chaîne contenant une expression :
expression = ["NOT"] comparison { ("AND" | "OR") ["NOT"] comparison }
Une comparaison est une valeur unique ou une expression booléenne:
"The cat in the hat" resource.type = "k8s_cluster"
La première ligne est un exemple de comparaison qui est une valeur unique. Ces types de comparaisons sont des restrictions globales. Chaque champ d'une entrée de journal est comparé à la valeur en utilisant implicitement l'opérateur has (contient). Pour cet exemple, si un champ d'une entrée de journal (LogEntry
) ou sa charge utile contient l'expression "The cat in the hat", alors la comparaison est réussie.
La deuxième ligne est un exemple de comparaison qui est une expression booléenne de la forme [FIELD_NAME] [OP] [VALUE]
. Une comparaison se compose de trois éléments:
[FIELD_NAME]
: est un champ dans une entrée de journal. Exemple :resource.type
[OP]
: est un opérateur de comparaison. Exemple :=
[VALUE]
: est un nombre, une chaîne, une fonction ou une expression entre parenthèses. Exemple :"k8s_cluster"
Pour les valeurs nulles JSON, utilisezNULL_VALUE
.
Opérateurs booléens
Les opérateurs booléens AND
et OR
sont des opérateurs de court-circuit.
L'opérateur NOT
possède la priorité la plus élevée, suivi de OR
et AND
. Par exemple, les deux expressions suivantes sont équivalentes :
"a" OR NOT "b" AND NOT "c" OR "d" ("a" OR (NOT "b")) AND ((NOT "c") OR "d")
Vous pouvez omettre l'opérateur AND
entre les comparaisons. Vous pouvez également remplacer l'opérateur NOT
par l'opérateur -
(moins). Par exemple, les deux requêtes suivantes sont équivalentes :
a="b" AND c="d" AND NOT e="f" a="b" c="d" -e="f"
Cette documentation utilise toujours AND
et NOT
.
Pour tous les filtres, à l'exception de ceux utilisés par les vues de journaux, vous pouvez utiliser les opérateurs AND
, OR
et NOT
. Les vues de journaux n'acceptent que les opérations AND
et NOT
.
Pour combiner des règles AND
et OR
dans la même expression, vous devez imbriquer les règles à l'aide de parenthèses. Si vous n'utilisez pas de parenthèses, votre requête risque de ne pas fonctionner comme prévu.
Les opérateurs booléens doivent toujours être en majuscules. Les valeurs and
, or
et not
en minuscules sont analysées en tant que termes de recherche.
Comparaisons
Les comparaisons ont la forme suivante :
[FIELD_NAME] [OP] [VALUE]
Une comparaison se compose de trois éléments:
[FIELD_NAME]: identifiant du chemin d'accès d'un champ dans une entrée de journal. Voici quelques exemples de ces identifiants:
resource.type resource.labels.zone resource.labels.project_id insertId jsonPayload.httpRequest.protocol labels."compute.googleapis.com/resource_id"
Si un composant d'un identifiant de chemin de champ comporte des caractères spéciaux, il doit être entre guillemets doubles. Par exemple,
compute.googleapis.com/resource_id
doit être entre guillemets doubles, car il contient une barre oblique/
.Pour plus d'informations, consultez la section Identificateurs de chemin d'accès de champ du présent document.
[OP] : est un opérateur de comparaison, parmi les suivants :
= -- equal != -- not equal > < >= <= -- numeric ordering : -- "has" matches any substring in the log entry field =~ -- regular expression search for a pattern !~ -- regular expression search not for a pattern
Pour savoir comment rechercher des entrées de journal à l'aide d'expressions régulières, consultez la section Utiliser des expressions régulières.
- [VALUE] : est un nombre, une chaîne, une fonction ou expression entre parenthèses.
Les chaînes comprennent du texte arbitraire, ainsi que des valeurs booléennes, d'énumération et de chaînes d'octets. La valeur
[VALUE]
est convertie dans le type du champ avant la comparaison. Pour les valeurs JSON nulles, utilisezNULL_VALUE
.
Pour filtrer sur une valeur nulle JSON, utilisez la syntaxe suivante :
jsonPayload.field = NULL_VALUE -- includes "field" with null value NOT jsonPayload.field = NULL_VALUE -- excludes "field" with null value
Si [VALUE]
est une combinaison booléenne de comparaisons entre parenthèses, le nom du champ et l'opérateur de comparaison sont appliqués à chaque élément.
Exemple :
jsonPayload.cat = ("longhair" OR "shorthair") jsonPayload.animal : ("nice" AND "pet")
La première comparaison vérifie que le champ cat
possède la valeur "longhair" (poils longs) ou "shorthair" (poils courts). La seconde vérifie que la valeur du champ animal
contient les deux mots "nice" (gentil) et "pet" (animal domestique), dans n'importe quel ordre.
Identificateurs de chemin d'accès à un champ
Toutes les entrées de journal sont des instances de type LogEntry
. L'identificateur qui est (ou commence à) la partie gauche d'une comparaison doit être un champ défini dans le type LogEntry
. Pour en savoir plus sur les identifiants possibles et leurs valeurs, consultez le type LogEntry
.
Voici la liste actuelle des champs d'entrée de journal. Chaque champ est suivi du niveau de noms suivant pour ce champ, le cas échéant :
httpRequest
: {cacheFillBytes
,cacheHit
,cacheLookup
,cacheValidatedWithOriginServer
,latency
,protocol
,referer
,remoteIp
,requestMethod
,requestSize
,requestUrl
,responseSize
,serverIp
,status
,userAgent
}insertId
jsonPayload
{ variable }labels
{ variable }logName
metadata
{systemLabels
,userLabels
}operation
{id
,producer
,first
,last
}protoPayload
{@type
, variable }receiveTimestamp
resource
{type
,labels
}severity
sourceLocation
: {file
,line
,function
}spanId
textPayload
timestamp
trace
Vous trouverez ci-dessous des exemples d'identificateurs de chemin d'accès à des champs que vous pouvez utiliser dans vos comparaisons :
resource.type: si votre premier identificateur de chemin d'accès est
resource
, l'identificateur suivant doit être un champ de typeMonitoredResource
.httpRequest.latency: si votre premier identificateur de chemin d'accès est
httpRequest
, l'identificateur suivant doit être un champ de typeHttpRequest
.labels.[KEY] Si votre premier identificateur de chemin est
labels
, l'identificateur suivant,[KEY]
, doit être l'une des clés des paires clé/valeur figurant dans le champlabels
.logName : le champ
logName
étant une chaîne, vous ne pouvez pas le faire suivre de noms de sous-champs.
Lorsque vous interrogez des champs map ou struct, vous devez conserver la casse et la mise en forme de leurs clés dans l'expression.
Par exemple, jsonPayload
est un champ de structure. Par conséquent, un nom de champ imbriqué dans jsonPayload
tel que jsonPayload.end_time
est différente de jsonPayload.endTime
. De même, pour un champ de mappage tel que labels
, la clé de libellé labels.env_name
est différente de labels.envName
. En revanche, lorsque vous interrogez le champ de tampon de protocole standard protoPayload, vous n'avez pas besoin de conserver la casse.
Pour en savoir plus sur les types de champs LogEntry
, consultez la documentation de référence sur google.logging.v2.
Caractères spéciaux
Si un champ LogEntry
contient des caractères spéciaux, le champ de journal doit être entre guillemets.
Exemple :
jsonPayload.":name":apple jsonPayload."foo.bar":apple jsonPayload."\"foo\"":apple
Pour obtenir la liste des caractères spéciaux, consultez la section string
de la page Valeurs et conversions.
Pour en savoir plus sur l'utilisation d'identifiants de chemin d'accès de champ faisant référence à des objets ou à des tableaux, consultez la section Types d'objets et de tableaux du présent document.
Types de ressources surveillées
Pour des requêtes plus rapides, spécifiez le type des ressources surveillées. Pour une liste des types de ressources, consultez la page Types de ressources surveillées.
Par exemple, les VM Compute Engine utilisent le type de ressource gce_instance
et les instances Amazon EC2 utilisent aws_ec2_instance
. L'exemple suivant montre comment limiter vos requêtes à ces deux types de VM :
resource.type = ("gce_instance" OR "aws_ec2_instance")
Les valeurs des types de ressources surveillées dans les journaux sont indexées. L'utilisation de correspondances de sous-chaînes ralentit les requêtes.
Champs non renseignés
Si vous utilisez un nom de champ dans une requête et que ce champ n'apparaît pas dans une entrée de journal, le champ est manquant, indéterminé, ou défini par défaut :
Si le champ fait partie de la charge utile de l'entrée de journal (
jsonPayload
ouprotoPayload
) ou s'il figure dans une étiquette de la sectionlabels
de l'entrée de journal, le champ est manquant. L'utilisation d'un champ manquant n'affichera pas d'erreur, mais toutes les comparaisons utilisant des champs manquants échoueront en silence.Exemples :
jsonPayload.nearest_store
,protoPayload.name.nickname
Si le champ est défini dans le type
LogEntry
, il est défini par défaut. Les comparaisons sont effectuées comme si le champ était présent et avait sa valeur par défaut.Exemples :
httpRequest.remoteIp
,trace
,operation.producer
Sinon, le champ n'est pas défini, ce qui correspond à une erreur détectée avant l'utilisation de la requête.
Exemples :
thud
,operation.thud
,textPayload.thud
Pour tester si un champ manquant ou par défaut existe sans tester une valeur particulière de ce champ, utilisez la comparaison :*
. Par exemple, la comparaison suivante réussit si le champ operation.id
est explicitement présent dans une entrée de journal :
operation.id:*
Observez le comportement des requêtes suivantes :
Lorsque vous utilisez l'opérateur booléen
NOT
sur un champ manquant, le résultat estTRUE
:-- Returns TRUE NOT missingField=foo
Lorsque vous utilisez l'opérateur de comparaison d'inégalité
!=
sur un champ manquant, le résultat estFALSE
:-- Returns FALSE missingField!=foo
Types d'objets et de tableaux
Chaque champ d'entrée de journal peut contenir un scalaire, un objet ou un tableau.
Un champ scalaire stocke une seule valeur, telle que
174.4
ou-1
. Unstring
est également considéré comme un scalaire. Les champs pouvant être convertis en (ou à partir de) chaîne, tels queDuration
etTimestamp
sont également de type scalaire.Un type d'objet stocke un ensemble de valeurs nommées, semblable à la valeur JSON suivante :
{"age": 24, "height": 67}
Vous pouvez faire référence à la valeur à l'intérieur d'un objet. Par exemple, si
jsonPayload.x
contient la valeur précédente, alorsjsonPayload.x.age
aura la valeur24
.Un champ de type tableau stocke une liste de valeurs, toutes du même type. Par exemple, un champ contenant des mesures peut avoir un tableau de nombres :
{8.5, 9, 6}
Lorsque des comparaisons sont effectuées et que
[FIELD_NAME]
est un champ de tableau, chaque partie du tableau est comparée à[VALUE]
et les résultats sont joints à l'aide de l'opérateurOR
. Par exemple, sijsonPayload.shoeSize
est un champ de tableau qui stocke{8.5, 9, 6}
, la comparaison :jsonPayload.shoeSize < 7
équivaut à :
8.5 < 7 OR 9 < 7 OR 6 < 7
Dans cet exemple, la comparaison globale est évaluée comme réussie.
Valeurs et conversions
La première étape de l'évaluation d'une comparaison consiste à convertir la valeur de droite en type de champ d'entrée de journal. Les types de champs scalaires sont autorisés dans les comparaisons, ainsi que deux types supplémentaires dont les valeurs sont représentées par des chaînes : Duration
et Timestamp
. Pour obtenir la liste des types scalaires, consultez la liste des types de tampons de protocole scalaires. Le tableau suivant explique quelles valeurs peuvent être converties en types de champs de journal:
Type de champ | Valeur de requête autorisée |
---|---|
bool |
"True" ou "false" dans n'importe quelle casse. Exemples : "True", "true" |
bytes |
Chaîne contenant n'importe quelle séquence d'octets. Exemple : "\377\377". |
Duration |
Chaîne contenant un nombre décimal signé suivi de l'une des unités "ns", "us", "ms", "s", "m" ou "h". Les durées sont exprimées avec une précision de l'ordre de la nanoseconde. Exemple : "3,2 s". |
enum |
Nom d'un type d'énumération littéral, non sensible à la casse. Exemples : "WARNING", qui est une valeur de type LogSeverity. |
double |
Tout nombre, avec ou sans signe, ni partie exponentielle, ou les chaînes de valeurs spéciales "NaN", "-Infinity" et "Infinity" (en majuscules ou non). Exemples : "-3.2e-8", "nan". |
intNN |
Tout entier signé ne dépassant pas la taille du type. Exemple : "-3". |
string |
Toute chaîne contenant du texte encodé en UTF-8 ou en ASCII sur 7 bits. Les guillemets intégrés doivent être échappés avec une barre oblique inverse. Les valeurs de chaîne doivent être entre guillemets doubles pour échapper les caractères spéciaux suivants :
|
Timestamp |
Une chaîne au format RFC 3339 ou au format ISO 8601.
Exemples : "2024-08-02T15:01:23.045Z" (RFC 3339), "2024-08-02" (ISO 8601). Dans les expressions de requête, les horodatages au format RFC 3339 peuvent mentionner un fuseau horaire avec "Z" ou |
uintNN |
Tout entier non signé qui ne dépasse pas la taille du type. Exemple : "1234". |
Si une tentative de conversion échoue, la comparaison échoue.
Lorsqu'une conversion nécessite une chaîne, vous pouvez également utiliser un nombre ou un texte non mis entre guillemets s'ils ne contiennent pas de caractères spéciaux tels que des espaces et des opérateurs. De même, lorsqu'une conversion nécessite un nombre, vous pouvez utiliser une chaîne dont le contenu est un nombre.
Les types intNN
et uintNN
représentent des types entiers de différentes tailles, tels que int32
et uint64
. Lorsque vous écrivez une valeur à convertir en type d'entier de 64 bits, vous devez écrire la valeur sous forme de chaîne, telle que "9223372036854775807".
Types de champs de journal
Voici comment le type d'un champ d'entrée de journal est déterminé :
Les champs de journal définis par le type
LogEntry
et le type composant sont des champs de tampon de protocole. Les champs de tampon de protocole possèdent des types explicites.Les champs de journal qui font partie d'objets
protoPayload
sont également des champs de tampon de protocole et possèdent des types explicites. Le nom du type de tampon de protocole est stocké dans le champ"@type"
deprotoPayload
. Pour en savoir plus, consultez le mappage JSON.Lorsque vous filtrez sur un champ associé au type de message
Any
, le champvalue
est automatiquement parcouru. Par conséquent, n'incluez pas cette valeur dans la requête. Pour en savoir plus, consultez la section Dépannage.Les champs de journal de
jsonPayload
possèdent des types déduits de la valeur du champ lorsque l'entrée de journal est reçue :- Les champs dont les valeurs sont des nombres sans guillemets sont de type
double
. - Les champs dont les valeurs sont
true
oufalse
sont de typebool
. - Les champs dont les valeurs sont des chaînes sont de type
string
.
Les entiers longs (64 bits) sont stockés dans des champs de type chaîne, car ils ne peuvent être représentés de manière fidèle dans des valeurs
double
.- Les champs dont les valeurs sont des nombres sans guillemets sont de type
Les types
Duration
etTimestamp
ne sont reconnus que dans les champs de tampon de protocole. Dans tous les autres contextes, ces valeurs sont stockées dans des champs de type chaîne.
Commentaires
Les commentaires commencent par deux tirets (--
), et tout texte qui suit les tirets est ignoré jusqu'à la fin de la ligne. Les commentaires peuvent être placés au début d'un filtre, entre les termes et à la fin d'un filtre.
Vous pouvez utiliser des commentaires dans les cas suivants:
Pour annoter vos filtres complexes avec des informations sur l'action d'une clause:
-- All of our target users are emitted by Compute Engine instances. resource.type = "gce_instance" -- Looking for logs from "alex". jsonPayload.targetUser = "alex"
Pour activer ou désactiver rapidement une clause en ajoutant ou en supprimant le préfixe de commentaire:
resource.type = "gce_instance" -- jsonPayload.targetUser = "alex" jsonPayload.targetUser = "kiran" -- jsonPayload.targetUser = "sasha"
Opérateurs de comparaison
Le sens des opérateurs d'égalité (=
, !=
) et d'inégalité (<
, <=
, >
, >=
) dépendent du type sous-jacent du nom de champ à gauche.
- Tous les types numériques : l'égalité et l'inégalité s'appliquent de façon normale aux nombres.
bool
: l'égalité signifie la même valeur booléenne. L'inégalité est définie partrue
>false
.enum
: l'égalité signifie la même valeur d'énumération. L'inégalité utilise les valeurs numériques sous-jacentes des littéraux d'énumération.Duration
: l'égalité signifie la même durée. L'inégalité est basée sur la durée du délai. Exemple : en tant que durées,"1s"
>"999ms"
.Timestamp
: l'égalité signifie le même instant temporel. Si a et b sont des valeursTimestamp
, a < b signifie que a est antérieur à b.bytes
: les opérandes sont comparés octet par octet, de gauche à droite.string
: les comparaisons ignorent les lettres majuscules. Plus précisément, les deux opérandes sont d'abord normalisés en utilisant la normalisation Unicode NFKC_CF, puis font appel à des comparaisons lexicographiques. En revanche, les recherches d'expressions régulières ne sont pas normalisées. Pour plus d'informations sur la recherche d'entrées de journal à l'aide d'expressions régulières, consultez la section Utiliser des expressions régulières.
L'opérateur de sous-chaîne (:
) est applicable à string
et bytes
. Il est traité comme une égalité, sans que l'opérande de droite ait besoin d'être égal à la totalité du champ de gauche. Les correspondances de sous-chaînes sur les champs indexés ne tirent pas parti des index de journal.
Restrictions globales
Si la comparaison consiste en une valeur unique, cela s'appelle une restriction globale. Logging utilise l'opérateur has (contient) (:
) pour déterminer si un champ dans une entrée de journal, ou sa charge utile, contient la restriction globale.
Si c'est le cas, la comparaison réussit.
La requête la plus simple rédigée en termes de restriction globale est une valeur unique :
"The Cat in The Hat"
Vous pouvez combiner des restrictions globales en utilisant les opérateurs AND
et OR
pour obtenir une requête plus intéressante. Par exemple, si vous souhaitez afficher toutes les entrées de journal comportant un champ contenant cat
et un champ contenant hat
ou bat
, écrivez la requête comme suit :
("cat" AND ("hat" OR "bat"))
Dans ce cas, il existe trois restrictions globales : cat
, hat
et bat
. Ces restrictions globales sont appliquées séparément et les résultats sont combinés, comme si l'expression avait été écrite sans parenthèses.
Une restriction globale est un moyen d'interroger vos journaux pour une valeur particulière.
Par exemple, si vous recherchez dans votre journal d'activité des entrées contenant la mention GCE_OPERATION_DONE
, vous pouvez utiliser la requête suivante :
logName = "projects/my-project-id/logs/compute.googleapis.com%2Factivity_log" AND "GCE_OPERATION_DONE"
Au lieu d'utiliser des restrictions globales, qui peuvent être lentes, nous vous recommandons d'utiliser la fonction SEARCH
intégrée et de interroger les champs indexés. Pour en savoir plus, consultez la section Rechercher des entrées de journal rapidement de ce document.
Fonctions
Vous pouvez utiliser les fonctions intégrées comme restrictions globales dans les requêtes:
function = identifier ( [ argument { , argument } ] )
où argument
est une valeur, un nom de champ ou une expression entre parenthèses.
Les fonctions sont décrites dans les sections suivantes.
log_id
La fonction log_id
renvoie les entrées de journal correspondant à l'argument [LOG_ID]
spécifié dans le champ logName
:
log_id([LOG_ID])
Par exemple, la requête suivante renvoie toutes les entrées de journal avec un [LOG_ID]
cloudaudit.googleapis.com%2Factivity
:
log_id("cloudaudit.googleapis.com/activity")
cast
La fonction cast
accepte deux paramètres : le champ LogEntry
à caster et le type de données dans lequel le champ est converti :
cast([FIELD], [TYPE][, OPTION])
Les paramètres de l'expression précédente sont définis comme suit:
[FIELD]
: nom d'un champ dans l'entrée de journal, tel quelogName
oujsonPayload.a_field
.[TYPE]
: type de données, par exempleSTRING
,INT64
,FLOAT64
ouBOOL
.TIMESTAMP
ouDURATION
: certains types de données offrent des options supplémentaires, telles que la spécification d'un fuseau horaire de la base de données de fuseaux horaires IANA pour le type de donnéesTIMESTAMP
.
Par exemple, la requête suivante convertit le champ timestamp
en Chaîne et spécifie le fuseau horaire America/New_York
:
cast(timestamp, STRING, TIMEZONE("America/New_York")) =~ "^2023-01-02.*"
regexp_extract
Utilisez la fonction regexp_extract
pour trouver la première sous-chaîne correspondant à une expression régulière:
REGEXP_EXTRACT([FIELD], [REGULAR_EXPRESSION])
Dans l'expression précédente, les champs sont définis comme suit:
[FIELD]
: nom d'un champ dans l'entrée de journal, par exemplelogName
oujsonPayload.a_field
.[REGULAR_EXPRESSION]
: expression régulière RE2 qui doit contenir un groupe de capture ((...)
). Un groupe de capture(?:...)
doit être utilisé si un regroupement supplémentaire est requis pour l'expression régulière. La présence de plusieurs groupes de capture ou l'absence de groupes de capture génère une erreur.
Vous pouvez enchaîner les fonctions cast
et regexp_extract
:
CAST(REGEXP_EXTRACT(CAST(timestamp, STRING), "\\d+:\\d+:\\d+\\.(\\d+)"), INT64) < 500
L'exemple précédent convertit le champ timestamp
en chaîne. L'expression régulière capture la partie milliseconde de la chaîne timestamp
et la convertit en entier pour effectuer une comparaison numérique. Toutes les entrées de journal contenant des codes temporels dont le champ milliseconde est inférieur à 500 sont renvoyées.
source
La fonction source
correspond aux entrées de journal d'une ressource particulière dans la hiérarchie des organisations, des dossiers et des projets Google Cloud.
La fonction source
ne correspond pas aux ressources enfants. Par exemple, l'utilisation de source(folders/folder_123)
correspond aux journaux de la ressource folder_123
, et non aux ressources du projet Google Cloud dans folder_123
.
Pour interroger des journaux à un niveau de ressource particulier, utilisez la syntaxe suivante :
source(RESOURCE_TYPE/RESOURCE_ID)
Ressource | Exemple de requête |
---|---|
Organisation | source(organizations/ ORGANIZATION_ID) |
Dossier | source(folders/ FOLDER_ID) |
Projets Google Cloud | source(projects/ PROJECT_ID) |
exemple
La fonction sample
sélectionne une partie du nombre total d'entrées de journal :
sample([FIELD], [FRACTION])
[FIELD]
correspond au nom d'un champ dans l'entrée de journal, tel que logName
ou jsonPayload.a_field
. La valeur du champ détermine si l'entrée de journal fait partie de l'échantillon. Le type de champ doit être une chaîne ou une valeur numérique.
Définir [FIELD]
sur insertId
est un bon choix, car chaque entrée de journal a une valeur différente pour ce champ.
[FRACTION]
est la fraction des entrées du journal qui ont des valeurs pour [FIELD]
à inclure. C'est un nombre supérieur à 0,0 et inférieur à 1,0. Par exemple, si vous spécifiez 0.01
, l'échantillon contient environ 1 % de toutes les entrées de journal ayant des valeurs pour [FIELD]
. Si [FRACTION]
vaut 1, toutes les entrées de journal dotées de valeurs pour [FIELD]
sont retenues.
Exemple : la requête suivante renvoie 25 % des entrées de journal du journal syslog
:
logName = "projects/my-project/logs/syslog" AND sample(insertId, 0.25)
Précisions : un algorithme déterministe, basé sur le hachage, est utilisé pour déterminer si une entrée de journal est incluse ou exclue de l'échantillon. La précision de l'échantillon résultant dépend de la distribution des valeurs hachées.
Si les valeurs hachées ne sont pas distribuées uniformément, l'échantillon résultant peut être faussé.
Dans le pire des cas, lorsque [FIELD]
contient toujours la même valeur, l'échantillon contient soit la [FRACTION]
de toutes les entrées du journal, soit aucune entrée du journal.
Si [FIELD]
apparaît dans une entrée de journal, alors :
- Un hachage de la valeur est calculé.
- La valeur hachée, qui est un nombre, est divisée par la valeur hachée maximale possible.
- Si la fraction résultante est inférieure ou égale à
[FRACTION]
, l'entrée du journal est incluse dans l'échantillon, sinon, elle est exclue de l'échantillon.
Si [FIELD]
n'apparaît pas dans une entrée de journal, alors :
- Si
[FIELD]
fait partie de la charge utile de l'entrée de journal ou des sectionslabels
, l'entrée de journal n'est pas sélectionnée pour l'exemple, même si[FRACTION]
vaut 1. - Sinon, l'entrée de journal est traitée comme si
[FIELD]
était dans l'entrée de journal et que la valeur de[FIELD]
était la valeur par défaut. La valeur par défaut est déterminée par le typeLogEntry
. Pour en savoir plus sur les champs manquants et définis par défaut, consultez la section Champs non renseignés du présent document.
Pour exclure de l'échantillon les entrées de journal dotées de champs par défaut, utilisez l'opérateur "le champ existe", :*
. La requête suivante génère un échantillon de 1 % des entrées de journal qui possèdent une valeur explicitement définie pour field
:
field:* AND sample(field, 0.01)
ip_in_net
La fonction ip_in_net
détermine si une adresse IP d'une entrée de journal fait partie d'un sous-réseau. Utilisez-la pour savoir, par exemple, si une requête provient d'une source interne ou externe. Exemple :
ip_in_net([FIELD], [SUBNET])
[FIELD]
est un champ de valeur de chaîne d'entrée de journal qui contient une adresse ou une plage d'adresses IP. Le champ peut être répété, auquel cas un seul des champs répétés doit posséder une adresse ou une plage d'adresses contenue dans le sous-réseau.
[SUBNET]
est une constante de type chaîne d'une adresse IP ou d'une plage d'adresses IP. C'est une erreur si [SUBNET]
n'est pas une adresse IP ni une plage d'adresses IP légitime, comme décrit plus loin dans cette section.
Exemple : la requête suivante teste une adresse IP dans la charge utile des entrées de journal à partir du journal my_log
:
logName = "projects/my_project/logs/my_log" AND ip_in_net(jsonPayload.realClientIP, "10.1.2.0/24")
Informations : Si, dans une entrée de journal, [FIELD]
est manquant, défini par défaut, ou s'il ne contient pas d'adresse ou de plage d'adresses IP légitime, la fonction renvoie la valeur "false". Pour en savoir plus sur les champs manquants et définis par défaut, consultez la section Champs non renseignés du présent document.
Exemples d'adresses IP et de plages compatibles :
- IPv4 :
10.1.2.3
- Sous-réseau IPv4 :
10.1.2.0/24
- CIDR IPv6 :
1234:5678:90ab:cdef:1234:5678:90ab:cdef
- Sous-réseau CIDR IPv6 :
1:2::/48
Fonction SEARCH
Vous pouvez rechercher des chaînes dans vos données de journaux à l'aide de la fonction SEARCH
intégrée:
SEARCH([query]) SEARCH([field], [query])
Les deux formes de la fonction SEARCH
contiennent un argument query
, qui doit avoir le format d'un littéral de chaîne. Dans la première forme, la recherche s'effectue dans l'entrée de journal complète. Dans la deuxième forme, vous précisez le champ à rechercher dans l'entrée de journal.
Vous devez spécifier le champ query
. Si ce champ n'est pas spécifié, une erreur est renvoyée.
Lorsque la fonction SEARCH
est traitée, la chaîne query
est traitée par un analyseur de texte qui la divise en jetons. Cloud Logging effectue toujours des comparaisons non sensibles à la casse, même pour les jetons encapsulés avec des accolades. Ce comportement diffère de celui de BigQuery, qui conserve la casse dans les jetons entourés de guillemets.
Pour en savoir plus sur les règles d'analyseur, consultez la documentation BigQuery Règles de l'analyseur de texte.
Lorsque vous créez une recherche, tenez compte des points suivants:
Les jetons ne sont pas sensibles à la casse. Les fonctions suivantes produisent les mêmes résultats:
SEARCH("world") SEARCH("World")
Les fonctions précédentes correspondent à une entrée de journal lorsqu'un seul champ contient le jeton "world". Comme
SEARCH
effectue des correspondances exactes et non des correspondances de sous-chaîne, les fonctions précédentes ne correspondent pas à un champ dont la valeur est "worldwide".Si vous ne spécifiez pas le champ à rechercher, la fonction
SEARCH
correspond à une entrée de journal lorsque cette entrée de journal contient tous les jetons. Toutefois, l'ordre des jetons n'a pas d'importance, et les jetons ne doivent pas nécessairement se trouver dans le même champ de l'entrée de journal.Les fonctions suivantes produisent les mêmes résultats et correspondent à une entrée de journal contenant les jetons "hello" et "world":
SEARCH("hello world") SEARCH("World hello")
Si vous spécifiez le champ à rechercher, la fonction
SEARCH
ne recherche que ce champ. Une correspondance se produit lorsque ce champ contient tous les jetons. Toutefois, l'ordre des jetons n'a pas d'importance.Les fonctions suivantes ne produisent une correspondance que lorsque le champ
textPayload
contient les jetons "hello" et "world":SEARCH(textPayload, "hello world")
Pour imposer une correspondance exacte, mais non sensible à la casse, sur une expression, placez-la entre accents graves. Par exemple, les fonctions suivantes correspondent à la chaîne "hello world":
SEARCH("`hello world`") SEARCH("`Hello World`") SEARCH("`HELLO WORLD`")
Étant donné que les crochets arrière sont utilisés dans les fonctions suivantes, elles produisent des résultats différents:
SEARCH("`hello world`") SEARCH("`world hello`")
Le langage de requête Logging permet de faire des recherches dans les données de journaux de différentes manières. Lorsque vous recherchez une chaîne, il est plus efficace d'utiliser la fonction SEARCH
que d'effectuer une recherche globale ou une recherche de sous-chaîne.
Toutefois, vous ne pouvez pas utiliser la fonction SEARCH
pour rechercher une correspondance avec des champs non textuels.
Pour savoir comment effectuer des opérations de recherche, consultez la section Minimiser les recherches globales et de sous-chaînes.
Rechercher par heure
Dans l'interface, vous pouvez définir des limites spécifiques concernant la date et l'heure des entrées de journal à afficher. Par exemple, si vous ajoutez les conditions suivantes à votre requête, le volet des résultats affiche exactement les entrées de journal dans la période de 30 minutes indiquée, et vous ne pourrez pas faire défiler l'écran en dehors de cette plage de dates:
timestamp >= "2023-11-29T23:00:00Z" timestamp <= "2023-11-29T23:30:00Z"
Lorsque vous rédigez une requête avec un horodatage, vous devez mettre en forme les dates et les heures comme indiqué précédemment.
Vous pouvez également rechercher des entrées de journal à l'aide des raccourcis timestamp
. Par exemple, vous pouvez saisir une date avec un opérateur de comparaison pour obtenir toutes les entrées de journal créées après un jour précis :
timestamp > "2023-11-29"
Utiliser des expressions régulières
Vous pouvez utiliser des expressions régulières pour créer des requêtes et des filtres pour les récepteurs, les métriques et partout où les filtres de journal sont utilisés. Par exemple, vous pouvez utiliser des expressions régulières dans l'explorateur de journaux et avec la Google Cloud CLI.
Une expression régulière est une séquence de caractères définissant une recherche. Le langage de requête Logging utilise la syntaxe RE2. Pour obtenir une explication complète de la syntaxe RE2, consultez le wiki RE2 sur GitHub.
Les requêtes utilisant des expressions régulières présentent les caractéristiques suivantes :
Seuls les champs de type chaîne peuvent être mis en correspondance avec une expression régulière.
Les chaînes ne sont pas normalisées. Par exemple,
kubernetes
n'est pas considéré comme identique àKUBERNETES
. Pour en savoir plus, consultez la section Opérateurs de comparaison.Les requêtes sont sensibles à la casse et ne sont pas ancrées par défaut.
Les opérateurs booléens peuvent être utilisés entre plusieurs expressions régulières à droite de l'opérateur de comparaison d'expressions régulières,
=~
et!~
.
Une requête avec une expression régulière possède la structure suivante :
Correspondance avec un modèle :
jsonPayload.message =~ "regular expression pattern"
Aucune correspondance avec un modèle :
jsonPayload.message !~ "regular expression pattern"
Les opérateurs =~
et !~
transforment la requête en une requête avec des expressions régulières. Le modèle que vous essayez de mettre en correspondance doit être entre guillemets doubles. Pour rechercher des modèles qui contiennent des guillemets doubles, vous pouvez les échapper avec une barre oblique inverse.
Exemples d'interrogation de journaux à l'aide d'expressions régulières
Type de requête | Exemple |
---|---|
Requête standard | sourceLocation.file =~ "foo" |
Requête avec une recherche non sensible à la casse | labels.subnetwork_name =~ "(?i)foo" |
Requête contenant des guillemets | jsonPayload.message =~ "field1=\"bar.*\"" |
Requête utilisant une valeur booléenne or |
labels.pod_name =~ "(foo|bar)" |
Requête utilisant des ancres | logName =~ "/my%2Flog$" |
Requête ne correspondant pas à un modèle | labels.pod_name !~ "foo" |
Requête utilisant un opérateur booléen | labels.env =~ ("^prod.*server" OR "^staging.*server") |
Requête commençant par une valeur | logName =~ "^foo" |
Requête se terminant par une valeur | logName =~ "foo$" |
Trouver des entrées de journal rapidement
Pour trouver efficacement les entrées de journal, procédez comme suit:
- Exécutez une requête à l'aide de champs indexés.
- Réduisez le nombre d'entrées de journal à rechercher.
Utiliser les champs indexés
La journalisation indexe toujours les champs LogEntry
suivants:
- resource.type
- resource.labels.*
- logName
- severity
- timestamp
- insertId
- operation.id
- trace
- httpRequest.status
- labels.*
- split.uid
Vous pouvez également ajouter des champs indexés personnalisés à n'importe quel bucket de journaux.
Les sections suivantes expliquent comment utiliser des champs indexés pour réduire le nombre d'entrées de journal à interroger.
Optimiser vos requêtes
Accélérez vos recherches en réduisant le nombre de journaux, le nombre d'entrées de journal ou la durée des recherches. Idéalement, réduisez les trois.
Exemple : Utilisez le nom de journal correct
Précisez le journal contenant les entrées qui vous intéressent. Assurez-vous de connaître le véritable nom du journal en consultant l'une de ses entrées. Par exemple, le volet des résultats indique que la section Compute Engine contient un journal nommé "activity". En examinant de plus près les entrées du journal des activités d'administration, vous constatez que le journal s'appelle en réalité "cloudaudit.googleapis.com/activity".
De ce fait, la comparaison suivante est erronée. Elle ne renvoie rien car le nom du journal est incorrect :
logName = "projects/my-project-id/logs/activity" -- WRONG!
En revanche, la comparaison suivante est correcte. Elle sélectionne les entrées du journal d'audit pour les activités d'administration. Vous devez indiquer le nom du journal sous forme d'URL, comme suit :
logName = "projects/my-project-id/logs/cloudaudit.googleapis.com%2Factivity"
Exemple : Choisissez les entrées de journal correctes
Si les entrées de journal que vous recherchez proviennent d'une instance de VM particulière, spécifiez-la. Vérifiez que les noms de libellé sont corrects en inspectant l'une des entrées de journal que vous souhaitez rechercher. Dans l'exemple suivant, instance_id
correspond à l'un des libellés indexés :
resource.type = "gce_instance" AND resource.labels.instance_id = "6731710280662790612" logName = "projects/my-project-id/logs/cloudaudit.googleapis.com%2Factivity"
Exemple : Sélectionnez la période correcte
Spécifiez la période sur laquelle effectuer la recherche. Pour déterminer rapidement les horodatages utiles au format RFC 3339, vous pouvez utiliser la commande Gnu/Linux date
:
$ date --rfc-3339=s 2023-06-27 17:39:00-04:00 $ date --rfc-3339=s --date="3 hours ago" 2023-06-27 14:40:00-04:00 $ date --rfc-3339=s --date="5 hours ago" 2023-06-27 12:40:00-04:00
Utilisez les valeurs de ces horodatages dans les requêtes suivantes. Pour créer un horodatage acceptable pour Logging, remplacez l'espace entre la date et l'heure par la lettre T
.
Par exemple, pour effectuer une recherche dans les trois dernières heures :
timestamp >= "2023-06-27T14:40:00-04:00"
Autre exemple, pour rechercher entre trois et cinq heures auparavant :
timestamp >= "2023-06-27T12:40:00-04:00" AND timestamp <= "2023-06-27T14:40:00-04:00"
Minimiser les recherches globales et de sous-chaînes
Évitez de céder à la facilité lorsque vous saisissez des requêtes.
Exemple : N'utilisez pas les recherches globales
Vous voulez rechercher une entrée de journal contenant "Hello, Kitty" dans la charge utile :
N'effectuez pas une recherche globale. Il s'agit ici de recherches de sous-chaînes :
"Hello Kitty" -- THIS CAUSES A SLOW SEARCH!
Limitez la recherche à un seul champ, même si vous devez conserver la recherche de sous-chaîne :
textPayload:"Hello Kitty"
Utilisez si possible un test d'égalité :
textPayload = "Hello Kitty"
Faites référence aux champs individuels d'une charge utile si vos entrées de journal possèdent des charges utiles structurées :
jsonPayload.my_favorite_cat = "Hello Kitty"
Utilisez un champ indexé pour limiter la recherche :
logName = "projects/my-project_id/logs/somelog" AND jsonPayload.my_favorite_cat = "Hello Kitty"
N'hésitez pas à utiliser la fonction
SEARCH
et à spécifier le texte complet à faire correspondre. La fonctionSEARCH
effectue une mise en correspondance non sensible à la casse:SEARCH("
Hello Kitty
")N'utilisez pas la fonction
SEARCH
et ne spécifiez pas de texte partiel. Par exemple, la fonction suivante ne correspond pas à "Hello Kitty".SEARCH("
Hello Kit
")
Exemples de recherches
Les entrées de journal affichées sont celles qui correspondent à une requête. Si le menu Aller à la date contient une valeur, l'affichage défile jusqu'à ce point dans le temps. Voici quelques exemples de requêtes :
resource.type=k8s_cluster
Recherche toutes les entrées de journal Google Kubernetes Engine. Pour obtenir la liste des types de ressources, consultez la liste des ressources surveillées.
Au fur et à mesure que vous saisissez, le volet de requête suggère des suggestions de saisie pour les champs tels que
resource.type
.resource.type=k8s_cluster AND logName:request_log
Recherche les entrées de journal des clusters Google Kubernetes Engine à partir des noms de journaux contenant
request_log
. Veuillez noter que :- L'opérateur
=
signifie égalité parfaite. Le type de ressource doit correspondre exactement à"k8s_cluster"
, à ceci près qu'il n'est pas sensible à la casse. - L'opérateur
:
signifie "contient". Le champlogName
doit contenirrequest_log
, quelle que soit la casse. Le véritable nom du journal est beaucoup plus long. L'utilisation de:
peut ralentir les recherches. - Les deux comparaisons sont jointes par
AND
. Vous pouvez également utiliserOR
, maisAND
est implicite si vous omettez l'opérateur.
- L'opérateur
resource.type = (gce_instance OR aws_ec2_instance) AND severity >= ERROR
Recherche les entrées de journal avec l'un des deux types de ressources suivants : instance de VM Compute Engine ou instance de VM AWS EC2. Les entrées de journal doivent avoir
severity
d'au moinsERROR
, ce qui équivaut à sélectionner ERREUR dans le menu de gravité de l'interface de requête de base.logName = "projects/[PROJECT_ID]/logs/cloudaudit.googleapis.com%2Factivity"
Affiche toutes les entrées du journal d'audit pour les activités d'administration du projet
[PROJECT_ID]
. Les journaux d'audit possèdent tous le même nom au sein d'un projet, mais des types de ressources différents. L'ID de journal,cloudaudit.googleapis.com/activity
, doit être codé en URL dans le nom du journal. L'utilisation de l'égalité dans la comparaison accélère la recherche. Pour en savoir plus, consultez la page Comprendre les journaux d'audit.unicorn
Trouve les entrées de journal contenant
unicorn
dans n'importe quel champ, dans n'importe quelle casse. Un terme de recherche qui ne fait pas partie d'une comparaison de champ est une requête "tous les champs".unicorn phoenix
Affiche les entrées de journal contenant
unicorn
dans un champ etphoenix
dans un autre.textPayload:(unicorn phoenix)
Affiche les entrées de journal dont le champ
textPayload
contient à la foisunicorn
etphoenix
dans n'importe quel ordre.AND
est implicite entre les deux mots.textPayload:"unicorn phoenix"
Affiche les entrées de journal dont le champ
textPayload
contient"unicorn phoenix"
.NOT textPayload: "unicorn phoenix"
Affiche les entrées de journal dont le champ
textPayload
ne contient pas la chaîne"unicorn phoenix"
. Ce type de requête réduit le nombre d'entrées de journal indésirables.timestamp >= "2023-11-29T23:00:00Z" timestamp <= "2023-11-29T23:30:00Z"
Affiche les entrées de journal créées sur une période de 30 minutes.
Dépannage
Problèmes de syntaxe
Si vous rencontrez des problèmes avec les expressions de vos requêtes, vérifiez les points suivants:
Votre requête respecte les règles de syntaxe. Les parenthèses et les guillemets vont par paires.
Les noms des champs d'entrée de journal sont correctement orthographiés.
Les opérateurs booléens sont en majuscules (
AND
,OR
,NOT
).Assurez-vous d'utiliser
NULL_VALUE
pour représenter les valeurs nulles JSON.Les expressions booléennes (restrictions globales ou partie droite des comparaisons) doivent être entre parenthèses pour plus de clarté. Par exemple, les deux requêtes suivantes se ressemblent, mais ne sont pas équivalentes:
insertId = "ABC-1" OR "ABC-2" -- ERROR!? insertId = ("ABC-1" OR "ABC-2")
Le texte sans guillemets ne doit contenir aucun caractère spécial. En cas de doute, ajoutez des guillemets doubles. Par exemple, dans l'exemple suivant, la première comparaison est illégale en raison de l'opérateur de sous-chaîne intégré (
:
). La comparaison doit être écrite entre guillemets:insertId = abc:def -- ILLEGAL! insertId = "abc:def"
La Google Cloud CLI exige que la requête soit entre guillemets doubles. Pour utiliser des guillemets doubles afin d'échapper des caractères spéciaux à l'aide de la commande
gcloud logging
, enveloppez la totalité de la requête avec des guillemets simples à la place :gcloud logging read 'resource.type=gce_instance AND jsonPayload.message="Stopped Unattended Upgrades Shutdown."' gcloud logging read 'timestamp>="2020-06-17T21:00:00Z"'
Lorsque vous filtrez sur un champ associé au type de message
Any
, le champvalue
est automatiquement parcouru. Par conséquent, n'incluez pasvalue
dans la requête.Par exemple, le champ
Status
d'un messageAuditLog
contient un champdetails
de typegoogle.protobuf.Any
. Pour interroger le champdetails
, omettez le champvalue
lorsque vous spécifiez le filtre:À faire
protoPayload.status.details.conditionNotMet.userVisibleMessage =~ "Specified reservation.*"
À ne pas faire
protoPayload.status.details.value.conditionNotMet.userVisibleMessage =~ "Specified reservation.*"