日志记录查询语言

本文档简要介绍了用于查询和过滤 Cloud Logging 数据的 Logging 查询语言。

如需深入了解 Logging 查询语言设计,请参阅 Google API 正式过滤规范

如需了解您想要使用的常见查询示例,请参阅使用日志浏览器的查询示例

概览

您可以使用 Google Cloud 控制台中的日志浏览器中的 Logging 查询语言、Logging API命令行界面。您可以使用 Logging 查询语言来查询数据并编写过滤条件,以创建接收器基于日志的指标

查询是一个布尔表达式,用于指定所选 Google Cloud 资源(例如 Google Cloud 项目或文件夹)中所有日志条目的子集。

您可以使用逻辑运算符 ANDOR 根据 LogEntry 索引字段构建查询。Logging 查询语言使用以下示例中的 resource.type 字段,其语法如下所示:

  • 简单限制:resource.type = "k8s_cluster"

  • 结合限制:resource.type = "k8s_cluster" AND severity = "ERROR"

  • 析取限制:resource.type = "k8s_cluster" OR resource.type = "gce_instance"

    • 或者:resource.type = ("k8s_cluster" OR "gce_instance")
  • 复杂的结合/析取表达式:resource.type = "k8s_cluster" AND (severity = "ERROR" OR "error")

以下是一个查询示例:

resource.type = "gce_instance" AND
severity >= "ERROR" AND
NOT textPayload:robot

此查询与 Compute Engine 中严重程度值至少为 ERRORtextPayload 字段中不包含字符串 robot 的日志条目相匹配。字符串比较不区分大小写。名称 resourceseveritytextPayload 是在 LogEntry 类型中定义的。

语法表示法

以下部分简要介绍了 Logging 查询语言语法,并详细讨论了查询的构造方式和执行匹配的方式。部分示例使用注释来提供说明文本。

请注意以下几点:

  • 查询的长度不能超过 20,000 个字符。

  • Logging 查询语言不区分大小写,但正则表达式除外。

语法摘要

您可以从查询比较的角度来考虑 Logging 查询语言语法。

查询是包含表达式的字符串:

expression = ["NOT"] comparison { ("AND" | "OR") ["NOT"] comparison }

比较运算可以是单个值,也可以是布尔表达式:

"The cat in the hat"
resource.type = "k8s_cluster"

第一行是比较运算为单个值的示例。这些类型的比较运算称为“全局限制”。系统会隐式使用包含运算符将日志条目的每个字段与该值进行比较。对于此示例,如果 LogEntry 中的任何字段或其载荷中的任何字段包含短语“The cat in the hat”,则比较运算成功。

第二行是比较运算为布尔表达式的示例,格式为 [FIELD_NAME] [OP] [VALUE]。比较项由三个部分组成:

  • [FIELD_NAME] 是日志条目中的字段。例如 resource.type

  • [OP] 是比较运算符。例如 =

  • [VALUE] 是数字、字符串、函数或用括号括起来的表达式。例如 "k8s_cluster"。对于 JSON null 值,请使用 NULL_VALUE

布尔运算符

布尔运算符 ANDOR短路运算符NOT 运算符具有最高优先级,OR 次之,AND 最低。例如,以下两个表达式是等效的:

"a" OR NOT "b" AND NOT "c" OR "d"
("a" OR (NOT "b")) AND ((NOT "c") OR "d")

您可以省略比较运算之间的 AND 运算符。您还可以将 NOT 运算符替换为 -(减号)运算符。例如,以下两个查询是相同的:

a="b" AND c="d" AND NOT e="f"
a="b" c="d" -e="f"

本文档均使用 ANDNOT

对于所有过滤条件(日志视图使用的过滤条件除外),您都可以使用 ANDORNOT 运算符。日志视图仅支持 ANDNOT 操作。

如需在同一表达式中组合 ANDOR 规则,您必须使用括号嵌套规则。如果您不使用圆括号,查询可能无法按预期运行。

布尔运算符始终需要采用大写形式。系统会将小写形式 andornot 解析为搜索字词。

比较

比较运算具有以下形式:

[FIELD_NAME] [OP] [VALUE]

比较项由三个部分组成:

  • [FIELD_NAME]:日志条目中字段的字段路径标识符。以下是这些标识符的示例:

    resource.type
    resource.labels.zone
    resource.labels.project_id
    insertId
    jsonPayload.httpRequest.protocol
    labels."compute.googleapis.com/resource_id"
    

    如果字段路径标识符的组成部分包含特殊字符,则该组成部分需要带有双引号。例如,compute.googleapis.com/resource_id 必须带有双引号,因为它包含正斜杠 /

    如需了解详情,请参阅本文档中的字段路径标识符

  • [OP]:比较运算符,包含以下几种:

    =           -- 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
    

如需了解如何使用正则表达式搜索日志条目,请参阅使用正则表达式

  • [VALUE]:数字、字符串、函数或带英文括号的表达式。字符串用于表示任意文本,以及布尔值、枚举值和字节字符串值。在比较之前,[VALUE] 会转换为字段的类型。 对于 JSON null 值,请使用 NULL_VALUE

要过滤 JSON null 值,请使用以下语法:

jsonPayload.field = NULL_VALUE      -- includes "field" with null value
NOT jsonPayload.field = NULL_VALUE  -- excludes "field" with null value

如果 [VALUE] 是带英文括号的布尔型比较运算组合,则字段名称和比较运算符将应用于每个元素。例如:

jsonPayload.cat = ("longhair" OR "shorthair")
jsonPayload.animal : ("nice" AND "pet")

第一个比较运算检查字段 cat 是否包含值“longhair”或“shorthair”。第二个比较运算检查字段 animal 的值是否同时包含字词“nice”和“pet”(字词不限顺序)。

字段路径标识符

所有日志条目都是类型为 LogEntry 的实例。位于比较运算左侧的标识符必须是在 LogEntry 类型中定义的字段。如需详细了解可能的标识符及其值,请参阅 LogEntry 类型。

下面是当前的日志条目字段列表。每个字段后跟该字段的下一级别的名称(如果适用):

  • httpRequest: { cacheFillBytes, cacheHit, cacheLookup, cacheValidatedWithOriginServer, latency, protocol, referer, remoteIp, requestMethod, requestSize, requestUrl, responseSize, serverIp, status, userAgent }
  • insertId
  • jsonPayload { 变量 }
  • labels { 变量 }
  • logName
  • metadata { systemLabels, userLabels }
  • operation{ id, producer, first, last }
  • protoPayload { @type, 变量 }
  • receiveTimestamp
  • resource { type, labels }
  • severity
  • sourceLocation: { file, line, function }
  • spanId
  • textPayload
  • timestamp
  • trace

下面是您可以在比较运算中使用的字段路径标识符的示例:

  • resource.type:如果您的第一个路径标识符是 resource,则下一个标识符必须是 MonitoredResource 类型中的字段。

  • httpRequest.latency:如果您的第一个路径标识符是 httpRequest,则下一个标识符必须是 HttpRequest 类型中的字段。

  • labels.[KEY] 如果您的第一个路径标识符是 labels,则下一个标识符 [KEY] 必须是 labels 字段中出现的键值对中的一个键。

  • logName:由于 logName 字段是一个字符串,因此该字段后面不能跟有任何子字段名称。

查询映射结构体字段时,您必须在表达式中保留其键的字母大小写和格式。

例如,jsonPayload 是一个结构体字段,因此嵌套在 jsonPayload 中的字段名称,例如 jsonPayload.end_time,与 jsonPayload.endTime 不同。同样,对于 labels 这样的映射字段,标签键 labels.env_namelabels.envName 不同。与此相反,在查询常规协议缓冲区字段 protoPayload 时,无需保留大小写。

如需了解 LogEntry 字段类型,请参阅 google.logging.v2 参考文档。

特殊字符

如果 LogEntry 字段包含特殊字符,则日志字段必须用英文引号引起来。例如:

jsonPayload.":name":apple

jsonPayload."foo.bar":apple

jsonPayload."\"foo\"":apple

如需查看特殊字符的列表,请参阅值和转换中的 string 部分。

如需详细了解如何使用引用对象或数组的字段路径标识符,请参阅本文档中的对象和数组类型

受监控的资源类型

为加快查询速度,请指定受监控的资源类型。如需资源类型的列表,请参阅受监控的资源类型

例如,Compute Engine 虚拟机使用资源类型 gce_instance,而 Amazon EC2 实例使用 aws_ec2_instance。以下示例展示了如何将查询限制为这两种虚拟机类型:

resource.type = ("gce_instance" OR "aws_ec2_instance")

日志中受监控的资源类型值已编入索引,对这些值使用子字符串匹配会导致查询速度变慢。

缺失字段

如果您在查询中使用了字段名称,且该字段没有出现在日志条目中,则该字段为缺失未定义默认字段:

  • 如果该字段属于日志条目的负载(jsonPayloadprotoPayload),或者它位于日志条目的 labels 部分内的标签中,则该字段为缺失字段。使用缺失字段不会显示错误,但使用缺失字段的所有比较运算都会失败,且不发出任何提示。

    示例:jsonPayload.nearest_storeprotoPayload.name.nickname

  • 如果该字段是在 LogEntry 类型中定义的,则该字段为默认字段。比较运算会按照该字段存在并且具有默认值的情况执行。

    示例:httpRequest.remoteIptraceoperation.producer

  • 否则,该字段为未定义字段,在使用查询之前会检测到此错误。

    示例:thudoperation.thudtextPayload.thud

如需测试是否存在缺失字段或默认字段,而不测试字段中是否有特定值,请使用 :* 比较运算。例如,如果日志条目中明确存在字段 operation.id,则以下比较运算会成功:

operation.id:*

请注意以下查询的行为:

  • 当您针对缺失字段使用布尔运算符 NOT 时,结果为 TRUE

    -- Returns TRUE
    NOT missingField=foo
    
  • 当您针对缺失字段使用不等于比较运算符 != 时,结果为 FALSE

    -- Returns FALSE
    missingField!=foo
    

对象和数组类型

每个日志条目字段都可以包含标量、对象或数组

  • 标量字段存储单个值,如 174.4-1string 也被视为标量。可与字符串相互转换的字段(如 DurationTimestamp)也是标量类型。

  • 对象类型存储一组指定值,如以下 JSON 值:

    {"age": 24, "height": 67}
    

    您可以引用对象内的值。例如,如果 jsonPayload.x 包含了前面的值,则 jsonPayload.x.age 将包含值 24

  • 数组字段存储值列表(所有值的类型相同)。例如,包含测量结果的字段可能具有数字数组:

    {8.5, 9, 6}
    

    在执行比较运算且 [FIELD_NAME] 为数组字段时,每个数组成员都会与 [VALUE] 比较,并且结果会通过 OR 运算符组合在一起。例如,如果 jsonPayload.shoeSize 是存储 {8.5, 9, 6} 的数组字段,则比较运算:

    jsonPayload.shoeSize < 7
    

    等效于:

    8.5 < 7 OR 9 < 7 OR 6 < 7
    

    在此示例中,整体比较计算结果成功。

值和转换

评估比较运算的第一步是将右侧值转换为日志条目字段的类型。比较运算中允许使用标量字段类型,以及另外两种其值表示为字符串的类型:DurationTimestamp。如需查看标量类型的列表,请参阅标量协议缓冲区类型列表。下表说明了可以将哪些值转换为日志字段类型:

字段类型 允许的查询值
bool

“True”或“false”,字母不区分大小写。示例:“True”、“true”

bytes

字符串,包含任意字节序列。示例:“\377\377”。

Duration

字符串,包含带符号小数,后跟“ns”、“us”、“ms”、“s”、“m”或“h”单位之一。持续时间精确到纳秒。示例:“3.2s”。

enum

枚举类型字面量的名称,不区分大小写。示例:“WARNING”,它是类型为 LogSeverity 的值。

double

任何数字(带符号或无符号和指数部分),或特殊值字符串“NaN”、“-Infinity”和“Infinity”(无论大小写)。示例:“-3.2e-8”、“nan”。

intNN

任何带符号整数,不超过带符号整数类型的大小。 示例:“-3”。

string

任何包含 UTF-8 编码或 7 位 ASCII 文本的字符串。嵌入式英文引号必须使用反斜杠进行转义。

字符串值必须带有双引号,才能对以下特殊字符进行转义:

  • +(加号)、-(减号)或 .(英文句点)开头的字符串。

  • 带有 ~(波浪符号)、=(等号)、()(英文括号)、:(英文冒号)、>(大于号)、<(小于号)、,(英文逗号)、.(英文句点)或 *(星号)的字符串。

  • 任何转义序列,例如 \t

Timestamp

采用 RFC 3339ISO 8601 格式的字符串。例如:"2024-08-02T15&colon;01&colon;23.045Z" (RFC 3339)、"2024-08-02" (ISO 8601)。在查询表达式中,采用 RFC 3339 格式的时间戳可以使用“Z”或 ±hh:mm 指定时区。时间戳可以精确到纳秒。

uintNN

任何无符号整数,不超过无符号整数类型的大小。 示例:“1234”。

如果尝试转换失败,则比较失败。

当转换需要字符串时,如果它们不包含空格和运算符等特殊字符,您也可以使用数字或不带英文引号的文本。同样,如果转换需要数字,您可以使用其内容为数字的字符串。

类型 intNNuintNN 表示各种大小的整数类型,例如 int32uint64。在写入要转换为 64 位整数类型的值时,您应以字符串形式写入该值,例如“9223372036854775807”。

日志字段的类型

下面介绍了如何确定日志条目字段的类型:

  • 类型 LogEntry 及组件类型中定义的日志字段为协议缓冲区字段。协议缓冲区字段具有显式类型。

  • 属于 protoPayload 对象的日志字段也是协议缓冲区字段,具有显式类型。协议缓冲区类型的名称存储在 protoPayload"@type" 字段中。如需了解详情,请参阅 JSON 映射

    当您按与 Any 消息类型关联的字段进行过滤时,系统会自动遍历 value 字段。因此,请勿将其包含在查询中。如需了解详情,请参阅问题排查

  • jsonPayload 内的日志字段的类型是收到日志条目时根据字段的值推断出的类型:

    • 如果字段的值为不带英文引号的数字,则该字段的类型为 double
    • 如果字段的值为 truefalse,则该字段的类型为 bool
    • 如果字段的值为字符串,则该字段的类型为 string

    长(64 位)整数存储在字符串字段中,因为它们不能精确表示为 double 值。

  • DurationTimestamp 类型只能在协议缓冲区字段中识别。在其他位置,这些值存储在字符串字段中。

评论

注释以两个短划线 (--) 开头,系统会忽略短划线后面直到行尾的所有文本。注释可以放在过滤条件的开头、字词之间和结尾。

您可以在以下情况下使用注释:

  • 如需使用子句的用途信息为复杂过滤条件添加注解,请执行以下操作:

     -- All of our target users are emitted by Compute Engine instances.
     resource.type = "gce_instance"
     -- Looking for logs from "alex".
     jsonPayload.targetUser = "alex"

  • 如需通过添加或移除注释前缀快速启用或停用子句,请执行以下操作:

     resource.type = "gce_instance"
     -- jsonPayload.targetUser = "alex"
     jsonPayload.targetUser = "kiran"
     -- jsonPayload.targetUser = "sasha"

比较运算符

等式(=!=)和不等式(<<=>>=)运算符的含义取决于左侧字段名称的基础类型。

  • 所有数字类型:等式和不等式具有其常规数字含义。
  • bool:等式表示布尔值相同。不等式通过 true > false 来定义。
  • enum:等式表示枚举值相同。不等式使用枚举字面量的基础数值。
  • Duration:等式表示持续时间的长度相同。不等式基于持续时间的长度。例如:持续时间 "1s" > "999ms"
  • Timestamp:等式表示同一时刻。如果 a 和 b 为 Timestamp 值,则 a < b 表示在时间上 a 早于 b
  • bytes:操作数按字节从左到右逐一比较。
  • string:比较运算会忽略字母大小写。具体来说,两个操作数必须先使用 NFKC_CF Unicode 标准化进行标准化,然后按字典顺序比较。但是,正则表达式搜索不进行标准化。如需详细了解如何使用正则表达式搜索日志条目,请参阅使用正则表达式

子字符串运算符 (:) 适用于 stringbytes,除了右侧操作数只需等于左侧字段的某个部分之外,其处理方式与等式相同。编入索引的字段的子字符串匹配未充分利用日志索引。

全局限制

如果比较运算包含单个值,则称为“全局限制”。Logging 使用包含运算符 (:) 确定日志条目的任何字段或条目的负载是否包含全局限制。如果包含,则比较会成功。

根据全局限制编写的最简单的查询为单个值:

"The Cat in The Hat"

您可以使用 ANDOR 运算符组合全局限制以获得更符合需要的查询。例如,如果要显示一个字段包含 cat,一个字段包含 hatbat 的所有日志条目,请按以下所示编写查询:

("cat" AND ("hat" OR "bat"))

在本例中,有三个全局限制:cathatbat。这些全局限制会单独应用,而结果会进行组合,就像未使用英文括号编写表达式一样。

全局限制是一种在日志中查询特定值的方式。例如,如果您在活动日志中查找提及到 GCE_OPERATION_DONE 的条目,则可以使用以下查询:

logName = "projects/my-project-id/logs/compute.googleapis.com%2Factivity_log" AND
"GCE_OPERATION_DONE"

我们建议您使用内置的 SEARCH 函数和查询编入索引的字段,而不是使用可能运行缓慢的全局限制。如需了解详情,请参阅本文档中的快速查找日志条目

Functions

您可以在查询中使用内置函数作为全局限制:

function = identifier ( [ argument { , argument } ] )

其中,argument 为值、字段名称或带英文括号的表达式。以下各部分介绍了这些函数。

log_id

log_id 函数会返回与 logName 字段中的指定 [LOG_ID] 参数匹配的日志条目:

log_id([LOG_ID])

例如,以下查询会返回带有 cloudaudit.googleapis.com%2Factivity [LOG_ID] 的所有日志条目:

log_id("cloudaudit.googleapis.com/activity")

投放

cast 函数接受两个参数:要转换的 LogEntry 字段,以及该字段要转换为的数据类型:

cast([FIELD], [TYPE][, OPTION])

上一个表达式的参数定义如下:

  • [FIELD]:日志条目中字段的名称,例如 logNamejsonPayload.a_field

  • [TYPE]:数据类型,例如 STRINGINT64FLOAT64BOOL

    • TIMESTAMPDURATION:某些数据类型提供其他选项,例如为 TIMESTAMP 数据类型指定 IANA 时区数据库时区。

例如,以下查询会将 timestamp 字段转换为字符串,并指定 America/New_York 时区:

cast(timestamp, STRING, TIMEZONE("America/New_York")) =~ "^2023-01-02.*"

regexp_extract

使用 regexp_extract 函数查找与正则表达式匹配的第一个子字符串:

REGEXP_EXTRACT([FIELD], [REGULAR_EXPRESSION])

在前面的表达式中,字段定义如下:

  • [FIELD]:日志条目中字段的名称,例如 logNamejsonPayload.a_field
  • [REGULAR_EXPRESSION]:必须包含一个捕获组 ((...)) 的 RE2 正则表达式。如果正则表达式需要进行额外的分组,则必须使用非捕获组 (?:...)。多个捕获组或没有捕获组都会导致错误。

您可以链接 castregexp_extract 函数:

CAST(REGEXP_EXTRACT(CAST(timestamp, STRING), "\\d+:\\d+:\\d+\\.(\\d+)"), INT64) < 500

前面的示例将 timestamp 字段转换为字符串。正则表达式会捕获 timestamp 字符串的毫秒部分,并将其转换为整数以执行数字比较。系统会返回包含毫秒字段小于 500 的日期时间戳的所有日志条目。

来源

source 函数会匹配组织、文件夹和 Google Cloud 项目层次结构中特定资源的日志条目。

source 函数不会匹配子资源。例如,使用 source(folders/folder_123) 会匹配 folder_123 资源中的日志,但不会匹配 folder_123 中的 Google Cloud 项目资源的日志。

如需查询特定资源级层的日志,请使用以下语法:

source(RESOURCE_TYPE/RESOURCE_ID)
资源 查询示例
组织 source(organizations/ORGANIZATION_ID)
文件夹 source(folders/FOLDER_ID)
Google Cloud 项目 source(projects/PROJECT_ID)

sample

sample 函数选择日志条目总数的一部分:

sample([FIELD], [FRACTION])

[FIELD] 是日志条目中的字段的名称,如 logNamejsonPayload.a_field。该字段的值确定日志条目是否在样本中。字段类型必须为字符串或数值。建议将 [FIELD] 设置为 insertId,因为对于该字段,每一个日志条目都具有不同的值。

[FRACTION] 是要包含的具有 [FIELD] 值的日志条目数的一部分。它是一个大于 0.0 且小于等于 1.0 的数字。例如,如果您指定 0.01,则样本所包含的日志条目大约占具有 [FIELD] 值的所有日志条目的 1%。如果 [FRACTION] 为 1,则选择具有 [FIELD] 值的所有日志条目。

示例:以下查询返回日志 syslog 中 25% 的日志条目:

logName = "projects/my-project/logs/syslog" AND sample(insertId, 0.25)

详细信息:基于哈希技术的确定性算法用于确定日志条目包含在样本中还是从样本中排除。所生成的样本的准确率取决于哈希值的分布。如果哈希值分布不均匀,则生成的样本可能会出现偏差。在最坏的情况下,如果 [FIELD] 始终包含相同的值,则生成的样本将包含所有日志条目的 [FRACTION] 或不包含任何日志条目。

如果 [FIELD] 出现在日志条目中,则:

  • 计算哈希值。
  • 该哈希值(数字)除以最大可能的哈希值。
  • 如果得出的比例小于或等于 [FRACTION],则日志条目包含在样本中;否则日志条目从样本中排除。

如果 [FIELD] 未出现在日志条目中,则:

  • 如果 [FIELD] 属于日志条目的负载部分或 labels 部分,即使 [FRACTION] 为 1,系统也不会为该样本选择日志条目。
  • 否则,日志条目会按照 [FIELD] 在日志条目中且 [FIELD] 的值为默认值进行处理。默认值由 LogEntry 类型确定。如需详细了解缺失字段和默认字段,请参阅本文档中的缺失字段

如需从样本中排除包含默认字段的日志条目,请使用判断字段是否存在的运算符 :*。以下查询生成 1% 的日志条目样本,这些日志条目已明确提供 field 的值:

field:* AND sample(field, 0.01)

ip_in_net

ip_in_net 函数确定日志条目中的 IP 地址是否包含在子网中。您可以使用此函数来判断请求是来自内部还是外部来源。例如:

ip_in_net([FIELD], [SUBNET])

[FIELD] 是日志条目中包含 IP 地址或 IP 地址范围的字符串值字段。该字段可以重复,在这种情况下,只有一个重复字段必须包括子网中包含的地址或地址范围。

[SUBNET] 是 IP 地址或 IP 地址范围的字符串常量。如果 [SUBNET] 不是合法的 IP 地址或 IP 地址范围,则会出错,如本部分稍后所述。

示例:以下查询测试来自日志 my_log 的日志条目负载中的 IP 地址:

logName = "projects/my_project/logs/my_log" AND
ip_in_net(jsonPayload.realClientIP, "10.1.2.0/24")

详细信息:如果在日志条目中,[FIELD] 为缺失字段或默认字段,或者不包含合法 IP 地址或 IP 地址范围,则该函数会返回 false。如需详细了解缺失字段和默认字段,请参阅本文档中的缺失字段

以下是受支持的 IP 地址和范围的示例:

  • IPv4:10.1.2.3
  • IPv4 子网:10.1.2.0/24
  • CIDR IPv6:1234:5678:90ab:cdef:1234:5678:90ab:cdef
  • CIDR IPv6 子网:1:2::/48

SEARCH 函数

您可以使用内置的 SEARCH 函数在日志数据中查找字符串:

SEARCH([query])
SEARCH([field], [query])

SEARCH 函数的两种形式都包含 query 参数,该参数的格式必须为字符串字面量。在第一个表单中,系统会搜索整个日志条目。在第二种形式中,您可以指定要搜索的日志条目中的字段。

您必须指定 query 字段。如果未指定此字段,则系统会返回错误。

处理 SEARCH 函数时,文本分析器会处理 query 字符串,将其拆分为词元。Cloud Logging 始终执行不区分大小写的比较,即使是用反引号括起来的令牌也是如此。此行为不同于 BigQuery 的行为,后者会保留用反引号括起来的令牌中的大小写。如需了解分析器规则,请参阅 BigQuery 文档 Text analyzer rules(文本分析器规则)。

构建搜索时,请考虑以下事项:

  • 令牌不区分大小写。以下函数会产生相同的结果:

    SEARCH("world")
    SEARCH("World")
    

    当单个字段包含令牌“world”时,上述函数会与日志条目匹配。由于 SEARCH 执行的是完全匹配,而不是子字符串匹配,因此前面的函数不会与值为“worldwide”的字段匹配。

  • 如果您未指定要搜索的字段,则当日志条目包含所有令牌时,SEARCH 函数会与该日志条目匹配。不过,令牌的顺序无关紧要,也不要求令牌位于日志条目的同一字段中。

    以下函数会产生相同的结果,并且与包含“hello”和“world”令牌的日志条目匹配:

    SEARCH("hello world")
    SEARCH("World hello")
    
  • 如果您指定要搜索的字段,则 SEARCH 函数只会搜索该字段。如果该字段包含所有令牌,则会发生匹配;不过,令牌的顺序无关紧要。

    只有当 textPayload 字段包含“hello”和“world”令牌时,以下函数才会产生匹配:

    SEARCH(textPayload, "hello world")
    
  • 如需对某个词组进行不区分大小写的完全匹配,请将该词组用反引号括起来。例如,以下函数与字符串“hello world”匹配:

    SEARCH("`hello world`")
    SEARCH("`Hello World`")
    SEARCH("`HELLO WORLD`")
    

    由于以下函数中使用了反引号,因此它们会产生不同的结果:

    SEARCH("`hello world`")
    SEARCH("`world hello`")
    

Logging 查询语言支持通过多种方式搜索日志数据。搜索字符串时,使用 SEARCH 函数比执行全局搜索或子字符串搜索更高效。不过,您无法使用 SEARCH 函数匹配非文本字段。如需有关执行搜索操作的指导,请参阅尽可能减少全局搜索和子字符串搜索

按时间搜索

在界面中,您可以对要显示的日志条目的日期和时间设置特定限制。例如,如果您向查询添加以下条件,结果窗格会精确显示在指定的 30 分钟时间段内的日志条目,并且您无法滚动查看该日期范围外的日志条目:

timestamp >= "2023-11-29T23:00:00Z"
timestamp <= "2023-11-29T23:30:00Z"

在编写带有时间戳的查询时,您必须使用格式如上所示的日期和时间。

您还可以使用 timestamp 快捷方式搜索日志条目。例如,您可以输入一个具有比较运算符的日期,以获取特定日期之后的所有日志条目:

timestamp > "2023-11-29"

使用正则表达式

您可以使用正则表达式来构建查询,以及为接收器、指标和任何使用日志过滤条件的情况创建过滤条件。例如,您可以在 Logs Explorer 中使用正则表达式,也可以在 Google Cloud CLI 中使用正则表达式。

正则表达式是可用于定义搜索的字符序列。Logging 查询语言使用 RE2 语法。如需查看 RE2 语法的完整说明,请参阅 GitHub 上的 RE2 wiki

正则表达式查询具有以下特征:

  • 只有字符串类型的字段才能与正则表达式匹配。

  • 不会执行字符串标准化,例如,kubernetes 不会被视为与 KUBERNETES 相同。如需了解详情,请参阅比较运算符部分。

  • 查询区分大小写,默认情况下不使用锚点。

  • 可以在正则表达式比较运算符(即 =~!~)右侧的多个正则表达式之间使用布尔运算符。

正则表达式查询的结构如下:

与某种模式匹配

jsonPayload.message =~ "regular expression pattern"

与某种模式不匹配

jsonPayload.message !~ "regular expression pattern"

=~!~ 用于将查询更改为正则表达式查询,而您尝试匹配的模式必须用英文双引号引起来。如需查询包含英文双引号的模式,请使用反斜杠对英文双引号进行转义。

使用正则表达式查询日志的示例

查询类型 示例
标准查询 sourceLocation.file =~ "foo"
包含不区分大小写的搜索内容的查询 labels.subnetwork_name =~ "(?i)foo"
包含英文双引号的查询 jsonPayload.message =~ "field1=\"bar.*\""
使用布尔运算符 or 的查询 labels.pod_name =~ "(foo|bar)"
使用锚点的查询 logName =~ "/my%2Flog$"
与某种模式不匹配的查询 labels.pod_name !~ "foo"
使用布尔运算符的查询 labels.env =~ ("^prod.*server" OR "^staging.*server")
以值开头的查询 logName =~ "^foo"
以值结尾的查询 logName =~ "foo$"

快速查找日志条目

如需高效地查找日志条目,请执行以下操作:

  • 使用编入索引的字段进行查询。
  • 尽可能减少必须搜索的日志条目数。

使用编入索引的字段

Logging 始终会为以下 LogEntry 字段编入索引:

您还可以向任何日志存储桶添加自定义编入索引的字段

接下来的部分将介绍如何使用编入索引的字段来最大限度地减少要搜索的日志条目数。

优化查询

通过减少日志、减少日志条目或缩小搜索时间范围,可以加快搜索速度。三个方面都缩减,效果会更佳。

示例:使用正确的日志名称

指定包含您感兴趣的日志条目的日志。检查其中一个日志条目,确保您知道实际的日志名称。例如,结果窗格会显示 Compute Engine 部分包含一个名为“activity”的日志。仔细检查管理员活动日志条目后,您会发现该日志实际名为“cloudaudit.googleapis.com/activity”。

以下比较不正确。此比较与任何日志条目都不匹配,因为它使用的日志名称不正确:

logName = "projects/my-project-id/logs/activity"   -- WRONG!

以下比较正确。此比较会从管理员活动日志中选择日志条目。您必须对日志名称进行网址编码,如下所示:

logName = "projects/my-project-id/logs/cloudaudit.googleapis.com%2Factivity"

示例:选择正确的日志条目

如果您知道需要的日志条目来自特定虚拟机实例,则指定该实例。通过检查您想要搜索的其中一个日志条目来检查正确的标签名称。在以下示例中,instance_id 是编入索引的标签之一:

resource.type = "gce_instance" AND
resource.labels.instance_id = "6731710280662790612"
logName = "projects/my-project-id/logs/cloudaudit.googleapis.com%2Factivity"

示例:选择正确的时间段

指定要搜索的时间段。快速确定 RFC 3339 格式的有效时间戳的一种方法是使用 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

在以下查询中使用这些时间戳的值。如需创建 Logging 接受的时间戳,请将日期和时间之间的空格替换为字母 T

例如,要在最近三个小时内搜索,请输入:

timestamp >= "2023-06-27T14:40:00-04:00"

再举一例,要在前五个小时到前三个小时之间搜索,请输入:

timestamp >= "2023-06-27T12:40:00-04:00" AND
timestamp <= "2023-06-27T14:40:00-04:00"

尽可能减少全局搜索和子字符串搜索

输入查询时,请避免尝试走捷径。

示例:不要使用全局搜索

如果您要在载荷中搜索包含“Hello, Kitty”的日志条目,请注意以下事项:

  • 不要使用全局搜索。一个原因是它们都是子字符串搜索:

       "Hello Kitty"   -- THIS CAUSES A SLOW SEARCH!
       

  • 务必将搜索限制为单个字段,即使您必须保留子字符串搜索也是如此:

       textPayload:"Hello Kitty"
       

  • 如果可以,请务必使用等式测试:

       textPayload = "Hello Kitty"
       

  • 如果日志条目包含结构化负载,请务必引用负载中的各个字段。

       jsonPayload.my_favorite_cat = "Hello Kitty"
       

  • 务必使用编入索引的字段来限制搜索:

       logName = "projects/my-project_id/logs/somelog" AND
       jsonPayload.my_favorite_cat = "Hello Kitty"
       

  • 使用 SEARCH 函数并指定要匹配的完整文本。 SEARCH 函数执行不区分大小写的匹配:

      SEARCH("Hello Kitty")
      

    请勿使用 SEARCH 函数并指定部分文本。例如,以下函数与“Hello Kitty”不匹配。

      SEARCH("Hello Kit")
      

搜索示例

显示的日志条目是与查询匹配的日志条目。如果跳转到时间菜单包含值,则显示内容会滚动到该时间点。下面是一些查询示例:

resource.type=k8s_cluster

查找所有 Google Kubernetes Engine 日志条目。如需资源类型的列表,请参阅受监控的资源列表

在输入时,查询窗格会针对 resource.type 等字段提供补全建议。

resource.type=k8s_cluster AND logName:request_log

从包含 request_log 的日志名称中查找 Google Kubernetes Engine 集群的日志条目。请注意以下几点:

  • = 运算符表示完全相等。资源类型必须正好是 "k8s_cluster",字母不区分大小写。
  • : 运算符表示“包含”。logName 字段必须包含 request_log,字母不区分大小写。实际的日志名称要长得多。使用 : 可能会导致搜索速度变慢。
  • 这两项比较由 AND 连接。您也可以使用 OR,但如果您省略此运算符,则假定为 AND
resource.type = (gce_instance OR aws_ec2_instance) AND severity >= ERROR

查找具有以下两种资源类型之一的日志条目:Compute Engine 虚拟机实例或 AWS EC2 虚拟机实例。日志条目的 severity 必须至少为 ERROR,这相当于在查询界面的严重级别菜单中选择错误

logName = "projects/[PROJECT_ID]/logs/cloudaudit.googleapis.com%2Factivity"

查找项目 [PROJECT_ID] 中的所有管理员活动审核日志条目。审核日志在项目中都使用相同的日志名称,但具有不同的资源类型。日志 ID cloudaudit.googleapis.com/activity 必须在日志名称中进行网址编码。在比较中使用等式可加快搜索速度。如需了解详情,请参阅了解审核日志

unicorn

在任意字段中查找包含 unicorn(字母不区分大小写)的日志条目。不属于字段比较的搜索字词是一个“所有字段”查询。

unicorn phoenix

在某些字段中查找包含 unicorn 的日志条目,而在某些字段中查找包含 phoenix 的日志条目。

textPayload:(unicorn phoenix)

查找 textPayload 字段同时包含 unicornphoenix(字词不限顺序)的日志条目 - 这两个字词之间隐含 AND

textPayload:"unicorn phoenix"

查找 textPayload 字段包含字符串 "unicorn phoenix" 的日志条目。

NOT textPayload: "unicorn phoenix"

查找 textPayload 字段不包含字符串 "unicorn phoenix" 的日志条目。这种类型的查询可以减少不必要的日志条目。

timestamp >= "2023-11-29T23:00:00Z" timestamp <= "2023-11-29T23:30:00Z"

查找 30 分钟时间段内的日志条目。

问题排查

语法问题

如果查询的表达式有问题,请检查以下各项:

  • 您的查询应遵循语法规则,并使用匹配的括号和引号。

  • 您的日志条目字段名称拼写正确。

  • 布尔运算采用大写字母(ANDORNOT)。

  • 确保使用 NULL_VALUE 表示 JSON null 值。

  • 为明确起见,作为全局限制的布尔表达式或作为比较运算右侧的布尔表达式应加英文括号。例如,以下两个查询看起来相同,但实际并不相同:

    insertId = "ABC-1" OR "ABC-2"  -- ERROR!?
    insertId = ("ABC-1" OR "ABC-2")
    
  • 不带英文引号的文本不得包含任何特殊字符。如果不确定,请添加英文双引号。例如,在以下代码中,由于嵌入了子字符串运算符 (:),第一个比较运算不符合规则。比较运算必须用英文引号括起来:

    insertId = abc:def  -- ILLEGAL!
    insertId = "abc:def"
    
  • Google Cloud CLI 要求为查询添加英文双引号。如需使用英文双引号通过 gcloud logging 命令进行转义特殊字符写入,请改用英文单引号将整个查询引起来:

    gcloud logging read 'resource.type=gce_instance AND jsonPayload.message="Stopped Unattended Upgrades Shutdown."'
    gcloud logging read 'timestamp>="2020-06-17T21:00:00Z"'
    

  • 当您按与 Any 消息类型关联的字段进行过滤时,系统会自动遍历 value 字段。因此,请勿在查询中添加 value

    例如,AuditLog 消息中的 Status 字段包含类型为 google.protobuf.Anydetails 字段。如需查询 details 字段,请在指定过滤条件时省略 value 字段:

    • 正确做法

      protoPayload.status.details.conditionNotMet.userVisibleMessage =~ "Specified reservation.*"
      
    • 错误做法

      protoPayload.status.details.value.conditionNotMet.userVisibleMessage =~ "Specified reservation.*"