Cloud Functions 日志查询 LQL 实战:基于 cloud-logging-query-generation 技能构建 1st Gen 与 2nd Gen 函数查询
【免费下载链接】skillsAgent Skills for Google products and technologies项目地址: https://gitcode.com/GitHub_Trending/skills29/skills
在 cloud-logging-query-generation 技能中,Cloud Functions 服务日志的 LQL(Logging Query Language)查询参考文档 query_cloud_functions.md 专门解决一个高频排障场景:如何为 Cloud Functions 的日志写出正确的过滤条件。本文以该文档为核心,完整继承其针对 1st Gen 与 2nd Gen 两代函数给出的资源类型、Log ID、执行关联(Execution Correlation)等基础模式,并结合同技能的 SKILL.md 语法规范与 api_reference.md 语法参考进行扩充,帮助你在 Cloud Logging 中精准定位某一函数的调用错误、按函数名与区域定向过滤,并用 Trace ID 关联单次并发执行的全部日志。
一、技能背景:从自然语言到 LQL
SKILL.md 定义了该技能的整体职责:把自然语言需求转换为正确的 Cloud Logging LQL 查询,并按服务拆分了多份参考文件——其中 Cloud Functions 对应的正是 references/query_cloud_functions.md,Cloud Run 对应 references/query_cloud_run.md。
在写任何 Cloud Functions 查询之前,必须遵守该技能声明的核心语法约束(这些约束决定了下文中所有查询的写法):
- 字符串字面量一律使用双引号
",禁止使用单引号'。 - 布尔运算符必须全大写:
AND、OR、NOT。 - 始终使用括号分组,显式控制优先级——例如 2nd Gen 错误查询中三个
log_id()条件必须用括号包成一个 OR 组。 - 优先在查询中限定
resource.type与log_id(仅当查询针对特定服务时;“最近所有错误日志”这类全局查询则不需要)。 - 变量占位符采用尖括号大写形式(如
"<PROJECT_ID>"),且若某字段并非查询必需,应整行省略占位符,而不是保留一个永远匹配不上的占位过滤器。
二、基础 Schema:两代函数的日志结构差异
Cloud Functions 的日志结构在 1st Gen 与 2nd Gen 之间存在显著差异,这是写查询前必须先判断的第一件事——两代函数使用完全不同的resource.type和log_id。
1st Gen Functions
1st Gen 函数有独立的监控资源类型,其核心模式如下:
| 要素 | 取值 | 用途 |
|---|---|---|
| Resource Type | resource.type="cloud_function" | 圈定 1st Gen 函数日志 |
| Log ID | log_id("cloudfunctions.googleapis.com/cloud-functions") | 指定 Cloud Functions 平台日志流 |
| 执行关联 | labels.execution_id="<EXECUTION_ID>" | 过滤出同一次调用的全部日志 |
| 定向过滤 | resource.labels.function_name="<FUNCTION_NAME>"、resource.labels.region="<REGION>" | 定位到具体函数与区域 |
也就是说,1st Gen 下"找出某个函数的某一次执行的错误"有两条路径:按函数名+区域定向,或拿到execution_id后做精确的执行级关联。
2nd Gen Functions(Cloud Run Functions)
2nd Gen 函数原生运行在 Cloud Run 基础设施上,因此它没有独立的资源类型,而是共享标准 Cloud Run schema(与 query_cloud_run.md 中cloud_run_revision的 Service 模式一致),并且存在并发请求日志交错的问题。其核心模式为:
- Resource Type:
resource.type="cloud_run_revision"; - Log ID 分三类用途:
log_id("run.googleapis.com/requests")—— 调用遥测:延迟、HTTP 状态码、请求 URL 等由 Cloud Run 网关产生的路由元数据;log_id("run.googleapis.com/stdout")与log_id("run.googleapis.com/stderr")—— 应用容器自己打印的标准输出/错误输出。
- 执行关联:最可靠的方式是通过 Trace ID:
trace="projects/<PROJECT_ID>/traces/<TRACE_ID>"。仅当你的运行时 SDK 确实会显式注入该字段时,才退而求其次使用labels.execution_id作为备选。 - 定向过滤:注意 label 名称与 1st Gen 不同——使用
resource.labels.service_name="<FUNCTION_NAME>"与resource.labels.location="<REGION>"(而不是function_name/region)。
这一"以 Trace 而非 execution_id 关联并发执行"的策略,与 Cloud Run 参考文档 中的结论一致:Cloud Run 天然处理并发请求,用简单的 execution ID label 做关联通常被视为反模式,应当改用
trace字符串匹配来串联单次请求的requests日志与其产生的stdout/stderr日志。
三、可直接使用的示例查询
原文档给出了两条无需替换变量的现成查询,分别覆盖两代函数的"执行错误"排查场景。
查询 1st Gen Cloud Functions 的执行错误
需替换变量:无
resource.type="cloud_function" AND log_id("cloudfunctions.googleapis.com/cloud-functions") AND severity >= ERROR解读:三段条件分别限定资源类型、日志流、严重度(severity >= ERROR使用数值比较运算符,会同时命中ERROR与CRITICAL等更高级别)。这是在全项目范围内扫描所有 1st Gen 函数执行错误的基线查询。
查询 2nd Gen Cloud Functions 的执行错误
需替换变量:无
resource.type="cloud_run_revision" AND (log_id("run.googleapis.com/stdout") OR log_id("run.googleapis.com/stderr") OR log_id("run.googleapis.com/requests")) AND severity >= ERROR解读:与 1st Gen 查询的关键差别在于——2nd Gen 的错误可能出现在应用输出(stdout/stderr)也可能出现在网关遥测(requests)中,因此必须用括号把三个log_id()条件组合成一个 OR 组再与其余条件做 AND,这正是 SKILL.md 中"始终用括号显式分组"规则的典型落地。
定向到具体函数(基于基础模式组合)
原文档给出的定向条件可以进一步组合为可复制的查询模板。例如定位某区域下指定 1st Gen 函数的全部日志:
resource.type="cloud_function" AND resource.labels.function_name="<FUNCTION_NAME>" AND resource.labels.region="<REGION>"2nd Gen 对应写法(注意 label 名差异):
resource.type="cloud_run_revision" AND resource.labels.service_name="<FUNCTION_NAME>" AND resource.labels.location="<REGION>"按照 SKILL.md 的占位符规则,如果用户没有指定区域,应当直接省略resource.labels.region这一行,而不是填入"<REGION>"占位符——因为占位符会作为显式过滤器生效,导致日志被漏掉。
四、基于 LQL 语法参考的查询扩展技巧
api_reference.md 提供了 LQL 的完整语法细节,配合 Cloud Functions 的 schema 可以构造更精细的查询:
全局关键字搜索:当你在参考文档中找不到所需字段的确切结构时,SKILL.md 要求改用全局
SEARCH()而不是猜字段名。例如在 2nd Gen 函数的应用输出里找包含某条错误信息的日志:resource.type="cloud_run_revision" AND log_id("run.googleapis.com/stderr") AND SEARCH("timeout")按 SKILL.md 要求,使用
SEARCH()兜底时应在查询顶部加一行--注释,说明因参考文件中缺少确切 schema 而采用了全局关键字搜索。限定字段的定向搜索:
SEARCH()可指定搜索范围,例如只在文本负载中搜索:SEARCH(textPayload, "hello world"),且参数必须是单个字符串字面量、不能传入布尔表达式。正则匹配:RE2 语法、大小写敏感、默认不加锚点。例如匹配特定函数的错误:
resource.labels.function_name =~ "^my-func.*";若需要大小写不敏感,可写=~ "(?i)keyword"。时间范围:
timestamp >= "2023-11-29T23:00:00Z"(严格 RFC 3339)或日期快捷形式timestamp > "2023-11-29",可追加到上述任意查询后缩小排查窗口。空值与字段存在性:显式 JSON null 用
NULL_VALUE判断;字段缺失时,否定比较为真而等值比较为假(NOT missingField="x"为 TRUE,missingField!="x"为 FALSE);用:*通配判断字段是否存在,例如labels.execution_id:*可用于先探测某批日志是否携带该关联标签。
五、实操:在 Cloud Logging 中运行这些查询
- 打开 Cloud Logging 的 Logs Explorer,切换到Logs advanced query(高级查询)模式——LQL 仅在此模式下可用,Express 模式只提供有限的过滤控件。
- 粘贴上文查询(占位符按实际值替换,或按规则整行删除),并设置合适的时间范围。
- 排查某次具体调用的完整链路时:先运行
requests日志流查询定位到目标请求日志,记下其trace字段值,再用trace="projects/<PROJECT_ID>/traces/<TRACE_ID>"作为过滤条件,即可把该次执行在stdout/stderr中产生的全部输出聚合出来——这是对 2nd Gen 并发交错日志最有效的关联手段。 - 若需要复用,可将查询保存为 Logs Explorer 的查询配置,或直接在日志查询界面分享。
六、延伸阅读
- SKILL.md —— 技能总体规则、占位符约定与"未知 schema 时降级为 SEARCH"策略;
- api_reference.md —— LQL 运算符、SEARCH、正则、时间戳与内置函数(
log_id、source、sample、cast、ip_in_net等)的完整语法参考; - query_cloud_run.md —— Cloud Run Services/Jobs 的
cloud_run_revision/cloud_run_jobschema,与 2nd Gen 函数日志直接对应; - query_audit_logs.md —— 若需排查"谁创建/删除了某个函数"等审计事件,应使用其中的
protoPayload模式而非本文的运行时日志模式。
适用前提与限制:本文所有resource.type、log_id、label 名称均以 query_cloud_functions.md 在当前仓库中的内容为准;2nd Gen 的labels.execution_id备选方案仅在运行时 SDK 显式注入该字段时可用,具体行为取决于你所使用的函数运行时与 SDK 版本。
【免费下载链接】skillsAgent Skills for Google products and technologies项目地址: https://gitcode.com/GitHub_Trending/skills29/skills
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考