日志记录查询语言

本页介绍用于查询日志数据和创建日志接收器的日志记录查询语言。

您可以在 Google Cloud Console 的 Cloud Logging 查询构建器窗格、Logging API命令行界面进行查询。

查询语法

本部分介绍了如何构建查询以及如何执行匹配。

查询是指可以从任意数量的日志中指定一组日志条目的表达式。查询是一个布尔表达式,用于指定项目中的部分日志条目。

您可以使用逻辑运算符 ANDOR 根据以下四个维度构建查询:

  • 资源:如需了解详情,请参阅 resource.type
  • 日志名称:如需了解详情,请参阅 logName
  • 严重级别:如需了解详情,请参阅 severity
  • 时间范围:如需了解详情,请参阅 timestamp

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

语法表示法

系统使用以下表示法描述查询语法:

  • a = e 表示 a 是表达式 e 的名称。
  • a b 表示“a 在前面,后跟 b”。
  • a | b 表示“a 或 b”。
  • ( e ) 用于分组。
  • [ e ] 表示 e 是可选项。
  • { e } 表示 e 可以重复 0 次或更多次。
  • "abc" 表示 abc 必须如显示的那样写入。

语法摘要

本部分简要介绍了查询语法。

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

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

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

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

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

第二行是比较运算为布尔表达式的示例,格式为 [FIELD_NAME] [OP] [VALUE]。下面介绍了比较运算的元素:

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

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

  • [VALUE]:数字、字符串、函数或带英文括号的表达式。例如 "gae_app"

以下部分详细介绍了查询和匹配。

布尔运算符

布尔运算符 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

比较运算

比较运算具有以下形式:

[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] 会转换为字段的类型。

如果 [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 字段是一个字符串,因此该字段后面不能跟有任何子字段名称。

特殊字符

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

uintNN

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

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

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

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

日志字段的类型

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

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

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

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

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

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

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

比较运算符

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

  • 所有数字类型:等式和不等式具有其常规数字含义。
  • 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"

虽然全局限制使用简单,但速度可能较慢;如需了解详情,请查看本页中的快速查找日志条目

函数

您可以在查询中使用内置函数作为全局限制:
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")

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

按时间搜索

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

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

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

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

  timestamp > "2016-11-29"

使用正则表达式

您可以使用正则表达式来构建查询,以及为接收器、指标和任何使用日志过滤条件的情况创建过滤条件。您可以在查询构建器中使用正则表达式,也可以将正则表达式与 gcloud command-line tool 搭配使用。

正则表达式是可用于定义搜索的字符序列。查询语言使用 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")