本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
了解计划查询的概念
在创建计划查询之前,请了解这些关键概念,这些概念会影响查询的运行方式和结果的交付地点。
IAM 角色分离
计划查询需要两个独立的 IAM 角色:一个用于执行查询,另一个用于将结果传送到 Amazon S3 存储桶、Amazon EventBridge 事件总线或查询表等目的地。了解这种分离的原因有助于您正确配置权限并使用其提供的安全和运营优势。
双角色架构在数据访问和数据交付之间划分了责任。查询执行角色访问您的日志数据并运行查询,而目标交付角色将结果写入您选择的目的地。这种分离遵循最小权限的原则——每个角色仅拥有其特定功能所需的权限。
- 查询执行角色
-
允许 CloudWatch 日志代表您运行 CloudWatch 日志见解查询。此角色需要访问您的日志组和执行查询的权限,但不需要访问目标资源。所需权限:
-
logs:StartQuery -
logs:StopQuery -
logs:GetQueryResults -
logs:DescribeLogGroups -
logs:Unmask是否需要取消屏蔽数据
对于 KMS-encrypted 日志组:
kms:Decrypt以及用于加密日志组的 KMS 密钥的kms:DescribeKey权限。还需要添加这些权限。信任关系要求:查询执行角色必须包含允许 CloudWatch 日志服务 (
logs.amazonaws.com) 代入该角色的信任策略。如果没有这种信任关系,计划查询将因权限错误而失败。查询执行角色的信任策略示例:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "logs.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }查询执行角色的权限策略示例:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:StartQuery", "logs:StopQuery", "logs:GetQueryResults", "logs:DescribeLogGroups" ], "Resource": "*" } ] } -
- 目的地配送角色
-
允许 CloudWatch 日志将查询结果传送到您选择的目的地。遵循最小权限原则,此角色只需要特定目标服务的权限。所需的权限因目的地类型而异。
信任关系要求:目标交付角色还必须包含允许 CloudWatch 日志服务 (
logs.amazonaws.com) 代入该角色的信任策略。S3 目标交付角色的权限策略示例:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject" ], "Resource": "arn:aws:s3:::your-scheduled-query-results-bucket/*" } ] }查找表目标交付角色的权限策略示例:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:CreateLookupTable", "logs:UpdateLookupTable", "logs:GetQueryResults" ], "Resource": "*" } ] }
这种分离为您的运营带来了实际好处。从安全角度来看,如果您需要更改结果的交付地点,则只需修改目标交付角色而不更改查询执行权限。对于合规性和审计,您可以清楚地跟踪哪个角色访问敏感日志数据以及哪个角色写入外部系统。这样可以更轻松地证明您的日志分析基础架构遵循安全最佳实践。
Cross-region 以及跨账户的使用
计划查询是在特定区域创建的,并在该区域运行。但是,您可以查询日志组并跨区域和跨账户提供结果。您需要将一个或多个 Amazon 账户设置为监控账户,并将它们与多个来源账户关联起来。监控账户是一个中央账户,可以查看源 Amazon 账户生成的可观测性数据并与之交互。源账户是一个个人 Amazon 账户,它为其中的资源生成可观测性数据。源账户与监控账户共享其可观测性数据。因此,您可以使用所有关联账户的日志组设置来自监控账户的预定查询。
- 查询跨区域日志组
-
您的预定查询可以访问任何区域的日志组。使用其完整 ARN 格式指定日志组:
arn:aws:logs:region:account-id:log-group:log-group-name。所有目标区域中日志组的查询执行角色需要logs:StartQuery和logs:GetQueryResults权限。
重要
在查询日志组或跨区域交付结果时,日志数据会跨越区域边界。请考虑以下事项:
-
数据驻留要求 -确保跨区域数据传输符合贵组织的数据治理政策和监管要求
-
数据传输成本 - Cross-region 数据传输会产生额外费用
-
网络延迟 -访问远程区域日志组的查询可能会遇到更高的延迟
为了获得最佳性能和成本效益,请在与主日志组相同的区域中创建计划查询。
替代方法:使用CloudWatch 日志集中化将来自多个账户和地区的日志数据复制到中央监控账户。这使您可以在单个区域中创建计划查询以访问所有集中日志,从而避免跨区域查询并简化 IAM 权限管理。
调度表达式和时区处理
您定义的时间表决定了查询的运行时间和执行频率。选择正确的计划表达式会影响您何时收到结果以及查询的数据量。了解表达式类型有助于您在简单性和精确性之间做出选择。
Cron 表达式可以精确控制时间,允许您指定确切的时间、一周中的几天或一月中的某天。当您需要在特定工作时间运行查询或与运营计划保持一致时,请使用 cron 表达式。在控制台中,您还可以使用简易日历选项安排查询。
- Cron 表达式
-
在特定时间运行查询。格式:
cron(minute hour day-of-month month day-of-week year)。示例:-
cron(0 9 * * ? *)-世界标准时间每天上午 9:00 -
cron(0 18 ? * MON-FRI *)-世界标准时间工作日下午 6:00 -
cron(0 0 1 * ? *)-世界标准时间每个月的第一天午夜 -
cron(0 12 ? * SUN *)-世界标准时间每周日中午 -
cron(30 8 1 1 ? *)-世界标准时间 1 月 1 日上午 8:30
-
所有计划查询均以 UTC 运行,无论您的本地时区如何,也无论您的 Amazon 资源位于何处。当您为工作时间或时间敏感型分析安排查询时,这一点尤其重要。例如,如果您的企业在美国东部时间运营,并且您想在美国东部时间上午 9 点提交每日报告,则需要考虑 UTC 偏移量(夏令时为 14:00 UTC,否则为 13:00 UTC)。在规划日程表达式时要牢记 UTC,确保查询在预定时间运行。
选择查询语言
计划查询支持三种不同的查询语言,您的选择会影响您编写查询的方式以及团队维护查询的难易程度。正确的语言取决于您的分析要求和团队的现有技能。
如果您主要筛选和聚合日志数据, CloudWatch Logs Insights 查询语言可提供最直接的语法。对于需要通过多个步骤重塑或丰富数据的复杂数据转换,PPL 的流水线方法使逻辑更易于理解。当您需要执行类似于数据库操作的联接或复杂聚合时,SQL 会提供熟悉的语法,数据库经验丰富的团队可以快速采用这些语法。
- CloudWatch 日志见解查询语言 (CWLI)
-
Purpose-built 使用直观的语法进行日志分析。最适合:
-
Text-based 日志分析和过滤
-
Time-series 汇总和统计
-
刚接触日志分析的团队
-
- OpenSearch 服务管道处理语言 (PPL)
-
Pipeline-based 具有强大数据转换功能的查询语言。最适合:
-
复杂的数据转换和充实
-
Multi-step 数据处理工作流程
-
熟悉基于管道的处理的团队
-
- OpenSearch 服务结构化查询语言 (SQL)
-
熟悉的数据库式查询的标准 SQL 语法。最适合:
-
复杂的连接和聚合
-
商业智能和报告
-
具有丰富的 SQL 经验的团队
-
目的地选择和用例
将查询结果发送到何处决定了您可以对它们做什么。无论您是在构建长期分析、触发自动响应,还是两者兼而有之,这种选择都会影响您的整个下游工作流程。了解每种目的地类型的优势有助于您为用例设计正确的架构。
Amazon S3 目的地针对存储和批处理进行了优化。当您需要将查询结果保存数月或数年、分析一段时间内的趋势或向分析平台提供数据时,Amazon S3 可提供具有无限保留期的经济实惠的存储。 EventBridge 目的地已针对实时自动化进行了优化。当查询结果应触发即时操作(例如发送警报、启动工作流程或更新系统)时,将结果作为事件EventBridge 提供,您的应用程序可以立即做出响应。默认情况下,所有查询完成事件都会自动作为事件发送到默认事件总线,从而可以与下游处理系统、Lambda 函数或其他事件驱动架构集成。只有成功执行查询后,结果才会发布到目的地。查询表目的地经过优化,可使参考数据保持最新状态。查找表目标会在每次计划执行时使用查询结果自动填充或刷新指定的查找表,因此其他查询可以使用该命令引用最新数据。lookup
- Amazon S3 目标
-
将查询结果存储为 JSON 文件,以便长期保留和批处理。Amazon S3 目的地最适合以下场景:
-
历史分析和数据存档
-
与数据湖和分析平台集成
-
合规和审计要求
-
Cost-effective 存储大型结果集
-
- EventBridge 目的地
-
将查询结果作为事件发送,以进行实时处理和自动化。在事件
queryId中使用来检索查询结果,查询运行后 30 天内仍可用。 EventBridge目的地最适合以下情况:-
触发对查询结果的自动响应
-
与无服务器工作流程和 Lambda 函数集成
-
Real-time 警报和通知系统
-
Event-driven 架构和微服务
-
- 查找表目的地
-
在每次计划执行时自动创建或刷新包含查询结果的查找表。每次刷新都是表格内容的完全替换。查找表目的地最适合以下场景:
-
在日志查询中保持
lookup命令的参考数据是最新的 -
维护源自日志数据的许可名单、拒绝名单或实体清单
-
使用最近的活动摘要(例如活跃用户或资源列表)丰富查询
-
查询结果的格式和结构
计划查询以 JSON 格式提供结果,但每种目标类型接收的负载不同。对于查找表目的地,查询结果成为查找表的内容,每次运行都会替换该内容。有关更多信息,请参阅 为计划查询配置查找表目的地。
Amazon S3 目标接收查询的结果行。每个对象都包含一个 JSON 数组,结果集中每行都有一个条目,每个条目将查询的输出字段名称映射到其值。该对象不包含查询元数据或查询统计信息,即使查询请求它也会省略该@ptr字段,因为该字段只能在控制台中使用。
EventBridge 目标接收查询元数据,包括查询统计信息,但不接收结果行。要检索已完成查询的行,请GetQueryResults使用事件queryId中的值进行调用。
以下示例显示了计划查询完成 EventBridge 时 CloudWatch 日志发布到的事件。
{ "version": "0", "id": "be72061b-eca2-e068-a7e1-83e01d6fe807", "detail-type": "Scheduled Query Completed", "source": "aws.logs", "account": "123456789012", "time": "2025-11-18T11:31:48Z", "region": "us-east-1", "resources": [ "arn:aws:logs:us-east-1:123456789012:scheduled-query:477b4380-b098-474e-9c5e-e10a8cc2e6e7" ], "detail": { "queryId": "2038fd57-ab4f-4018-bb2f-61d363f4a004", "queryString": "fields @timestamp, @message, @logStream\n| filter @message like /ERROR/\n| sort @timestamp desc\n| limit 10000", "logGroupIdentifiers": [ "/aws/lambda/my-function" ], "status": "Complete", "startTime": 1763465460, "statistics": { "recordsMatched": 1842, "recordsScanned": 48325, "estimatedRecordsSkipped": 0, "bytesScanned": 12081250, "estimatedBytesSkipped": 0, "logGroupsScanned": 1, "resultCount": 1842 } } }
此查询不聚合,返回的行数少于 10,000 行,因此 1,842 个匹配的日志事件中的每一个resultCount都成为一个输出行,recordsMatched且相等。limit聚合查询或结果集被截断的查询生成的值limit小resultCount于。recordsMatched有关更多信息,请参阅 了解已扫描的记录、匹配的记录和结果数。
关键要素包括:
-
statistics-描述查询读取的日志数据量以及结果集大小的计数器。有关每个字段的描述,请参阅下表。 -
startTime-开始执行查询的时间(Unix 时间戳) -
queryString-执行的实际查询 -
queryId-查询的查询 ID,使用它可以检索结果 -
logGroupIdentifiers-查询的日志组列表 -
status-查询执行状态(完成、失败等)
下表描述了statistics对象中的每个字段。有关这些字段的 API 定义,请参阅QueryStatistics。
| 字段 | 说明 |
|---|---|
recordsScanned |
查询期间扫描的日志事件总数。 |
recordsMatched |
与查询字符串匹配的日志事件的数量。此值计算日志事件,而不是输出行。对于结果集中的行数,使用resultCount。 |
resultCount |
查询结果集中的行数。该值仅计算在查询中所有操作中幸存下来的行,因此它可能小于recordsMatched。它涵盖了GetQueryResults返回的所有结果页面。有关更多信息,请参阅 了解已扫描的记录、匹配的记录和结果数。 |
estimatedRecordsSkipped |
处理此查询时跳过的日志事件数量的估计值,因为该查询包含索引字段。跳过这些条目可以降低查询成本并缩短查询性能时间。有关更多信息,请参阅 创建字段索引以提高查询性能并减少扫描量。 |
bytesScanned |
查询期间扫描的日志事件中的总字节数。 |
estimatedBytesSkipped |
由于查询包含索引字段,因此在处理此查询时跳过的日志事件中的字节数的估计值。 |
logGroupsScanned |
此查询扫描的日志组的数量。 |
了解已扫描的记录、匹配的记录和结果数
其中三个查询统计数据计算不同的内容,直接比较可能会产生误导。每一个都衡量查询处理的不同阶段:
-
recordsScanned-查询从您的日志组读取的日志事件的数量。这是查询的输入。 -
recordsMatched-与查询字符串匹配的日志事件的数量。此值计算日志事件。 -
resultCount-查询生成的结果集中的行数。此值计算输出行数。
每个阶段都会缩小数据范围。诸如之类的命令stats将许多日志事件合并到一个输出行中,因此resultCount可以小得多recordsMatched。大recordsMatched加小resultCount并不意味着结果集中缺少行。
示例-聚合
以下查询对一小时内一个日志组的每个日志流中的错误消息进行计数。
filter @message like /ERROR/ | stats count(*) as errorCount by @logStream
如果查询读取 1,500,000 个日志事件,其中 24,318 个事件包含ERROR,并且匹配的日志事件来自 12 个日志流,则查询将以以下统计信息完成。
"statistics": { "recordsMatched": 24318, "recordsScanned": 1500000, "estimatedRecordsSkipped": 0, "bytesScanned": 450000000, "estimatedBytesSkipped": 0, "logGroupsScanned": 1, "resultCount": 12 }
stats为每个日志流生成一行,所以resultCount是 12,而recordsMatched是 24,318。的 12 个值errorCount加起来等于 24,318。
示例 — Post-aggregation 过滤器
以下查询仅保留产生超过 1,000 个错误的日志流。
filter @message like /ERROR/ | stats count(*) as errorCount by @logStream | filter errorCount > 1000
最后一个filter命令在分组后运行,因此它会从结果集中删除行,而不是从扫描中删除日志事件。如果 12 个日志流中的 3 个errorCount大于 1,000,则resultCount是 3 而不是 12。recordsScanned并且bytesScanned不要更改,因为无论哪种方式,查询都会读取相同的日志数据。
示例 — 极限
limit命令resultCount无需任何聚合即可减少。以下查询返回 100 条最新错误消息。
filter @message like /ERROR/ | sort @timestamp desc | limit 100
如果查询扫描相同的 1,500,000 个日志事件并匹配相同的 24,318 个,则resultCount为 100,因为结果集的limit上限为 100 行。在控制台中,你会看到这种关系显示了 24,318 条匹配的记录中的 100 条。
每个统计数据都回答了一个不同的问题。
- 这个查询返回了多少行?
-
使用
resultCount。值为 0 表示该查询未生成任何行。请勿recordsMatched用于此目的,因为它计算日志事件而不是行数。 - 这个查询读取了多少日志数据?
-
使用
recordsScanned和bytesScanned。扫描量决定查询的成本和运行时间。要缩短时间范围,减少查询日志组的次数,或者创建字段索引。有关更多信息,请参阅 创建字段索引以提高查询性能并减少扫描量。 - 有多少日志事件与该查询相匹配?
-
使用
recordsMatched。
注意
CloudWatch 当对象没有可用值时,日志会省略该statistics对象的统计数据,而不是将统计数据报告为 0。
如果您的事件使用者在事件resultCount中找不到,则将该值视为未知值而不是 0。编写事件使用者,让他们容忍不存在的统计数据,忽略他们无法识别的统计数据。