异步搜索 API
借助 Google Security Operations 中的搜索平台,您可以对长时间运行的查询使用异步 API,这些查询会返回最多 100 万个结果的大型结果集。借助这些 API,您可以跨数据源(包括统一数据模型 [UDM] 事件、检测、数据表和实体上下文图表 [ECG])发起搜索,而不会阻塞应用。使用长时间运行的操作 (LRO) API 运行搜索查询时,您会收到一个操作 ID。您可以使用此 ID 监控操作状态并逐页获取结果。
前提条件
如需使用长时间运行的操作 API,调用主账号需要特定的 Identity and Access Management (IAM) 权限。
如需执行以下操作,您必须拥有相应的 IAM 权限:
- 发起搜索:
chronicle.searchSessions.search - 列出结果:
SearchSession资源上的chronicle.searchedResults.list。
确保调用主账号拥有授予这些权限的角色,例如 Chronicle API Viewer、Chronicle API Editor 或 Chronicle API Admin 角色。
使用 LRO API 运行搜索
请按照以下步骤使用 LRO API 运行搜索:
发起搜索
向 Google SecOps 实例上的 search 自定义方法发送 POST 请求。
- 端点:
POST /{$api_version}/projects/{project}/locations/{location}/instances/{instance}:search - 方法:
Search - 请求正文:
SearchRequest
以下示例展示了一个 SearchRequest 对象:
{
"parent": "projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID",
"query": "metadata.event_type = \"USER_LOGIN\"",
"time_range": {},
"start_time": "2026-03-16T14:40:13Z",
"endTime": "2026-03-16T15:40:13Z",
"dialect": "YL2"
}
该请求需要以下关键参数:
query:搜索查询字符串。time_range:搜索的时间间隔。dialect:将语言方言指定为YL2。SQL方言不支持使用ListSearchedResults(searchedResults.list) 异步检索 LRO 结果。RAW_LOG方言处于预览版阶段,如果未为您的实例启用,可能会返回501 UNIMPLEMENTED错误。
result_limit:可选。要具体化的行数上限。默认值为10000,最大值为1000000。simulated_data_visibility(或 JSON 中的simulatedDataVisibility):可选。控制搜索结果是否包含模拟事件。设置为SIMULATED_DATA_INCLUDED,以便在搜索结果中包含模拟事件。如果未指定,此参数默认为SIMULATED_DATA_EXCLUDED,即排除模拟事件。
此调用会返回一个 google.longrunning.Operation 对象。
以下示例展示了成功操作响应:
{
"name": "projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/operations/OPERATION_ID",
"metadata": {
"@type": "[type.googleapis.com/google.cloud.chronicle.v1main.SearchOperationMetadata](https://type.googleapis.com/google.cloud.chronicle.v1main.SearchOperationMetadata)",
"state": "RUNNING",
"start_time": "2026-03-13T10:00:00Z"
}
}
state: RUNNING 字段表示搜索正在进行中。
监控操作
使用 google.longrunning.Operations 服务中的标准 GetOperation 方法轮询 LRO 的状态。使用上一个响应中的 name 值。
- 端点:
GET /{$api_version}/projects/{project}/locations/{location}/instances/{instance}/operations/{operationID}
继续轮询,直到 GetOperation 响应中的 done 字段返回 true。
- 如果操作成功,
metadata.state字段会返回SUCCEEDED,并且响应字段会包含创建的SearchSession资源。 - 如果操作失败,
done字段会返回true,并且 error 字段会包含相关的失败详情。
以下示例展示了成功的 GetOperation 响应:
{
"name": "projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/operations/OPERATION_ID",
"metadata": {
"@type": "[type.googleapis.com/google.cloud.chronicle.v1main.SearchOperation](https://type.googleapis.com/google.cloud.chronicle.v1main.SearchOperation) Metadata",
"state": "SUCCEEDED",
"startTime": "2026-03-16T15:42:11.037506921Z"
},
"endTime": "2026-03-16T15:42:17.504730842Z",
"expireTime": "2026-03-17T15:42:17.504731874Z",
"progress": 100,
"done": true,
"response": {
"@type": "[type.googleapis.com/google.cloud.chronicle.v1main.SearchSession](https://type.googleapis.com/google.cloud.chronicle.v1main.SearchSession)",
"name": "projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/searchSessions/SEARCH_SESSION_ID",
"query": "metadata.event_type = \"USER_LOGIN\"",
"timeRange": {},
"startTime": "2026-03-16T14:40:13Z",
"endTime": "2026-03-16T15:40:13Z",
"dialect": "YL2",
"metadata": {
"operationId": "OPERATION_ID",
"startTime": "2026-03-16T15:42:11.037506921Z",
"endTime": "2026-03-16T15:42:17.504730842Z",
"expireTime": "2026-03-17T15:42:17.504731874Z",
"resultRowCount": 10000,
"moreDataAvailable": true
}
}
}
SearchSession 资源名称格式为 projects/{project}/locations/{location}/instances/{instance}/searchSessions/{search_session}。
成功的响应包含以下关键字段:
done:设置为true时,操作完成。state:设置为SUCCEEDED时,表示搜索已成功完成。response.name:SearchSession的资源名称。在下一步中,将此值用作父级媒体资源。response.metadata.resultRowCount:表示找到的总行数。response.metadata.moreDataAvailable:表示可用结果的数量超过了定义的返回限制。
列出 LRO 操作
如需列出 LRO 操作,请使用 google.longrunning.Operations 服务中的 ListOperations 方法。使用上一个响应中的 name 值。
- 端点:
GET /{$api_version}/projects/{project}/locations/{location}/instances/{instance}
如需列出过去 24 小时内的搜索 LRO 操作,请指定 name:"operations/s-lro-" 过滤条件,包括尾部连字符。
以下示例展示了成功的 ListOperations 请求:
google.longrunning.ListOperationsRequest {
name: "projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID"
filter: "name:\"operations/s-lro-\""
page_size: 100
}
以下示例展示了成功的 ListOperations 响应:
{
operations {
name: "projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/operations/OPERATION_ID_1"
metadata {
type_url: "[type.googleapis.com/google.cloud.chronicle.v1main.SearchOperation](https://type.googleapis.com/google.cloud.chronicle.v1main.SearchOperation) Metadata"
value: "\b\002\022\f\b\367\304\363\316\006\020\317\352\232\240\003\032\f\b\237\307\363\316\006\020\326\334\351\311\001\"\f\b\237\352\370\316\006\020\352\342\351\311\001(d"
}
done: true
response {
type_url: "[type.googleapis.com/google.cloud.chronicle.v1main.SearchSession](https://type.googleapis.com/google.cloud.chronicle.v1main.SearchSession)"
value: "\n\213\001projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/searchSessions/OPERATION_ID_11022\bip != \"\"\032\020\n\006\b\251\255\334\316\006\022\006\b\351\345\336\316\006\0012\\\n*OPERATION_ID_1\022\f\b\367\304\363\316\006\020\317\352\232\240\003\032\f\b\237\307\363\316\006\020\326\334\351\311\001\"\f\b\237\352\370\316\006\020\352\342\351\311\001(\300\204=0\001"
}
}
operations {
name: "projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/operations/OPERATION_ID_2"
metadata {
type_url: "[type.googleapis.com/google.cloud.chronicle.v1main.SearchOperationMetadata](https://type.googleapis.com/google.cloud.chronicle.v1main.SearchOperationMetadata)"
value: "\b\002\022\f\b\200\305\363\316\006\020\324\262\367\225\001\032\v\b\241\307\363\316\006\020\321\261\333?\"\v\b\241\352\370\316\006\020\317\264\333?(d"
}
done: true
response {
type_url: "[type.googleapis.com/google.cloud.chronicle.v1main.SearchSession](https://type.googleapis.com/google.cloud.chronicle.v1main.SearchSession)"
value: "\n\213\001projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/searchSessions/OPERATION_ID_2\022\bip != \"\"\0321020\n\006\b\251\255\334\316\006\022\006\b\351\345\336\316\006\0012Z\n*OPERATION_ID_2\022\f\b\200\305\363\316\006\0201324\262\367\225\001\032\v\b\241\307\363\316\006\020\321\261\333?\"\v\b\241\352\370\316\006\020\317\264\333?(\300\204=0\001"
}
}
}
提取结果
在操作状态返回 SUCCEEDED 后,使用 ListSearchedResults() 方法检索搜索结果。
- 端点:
GET /{$api_version}/{parent=projects/*/locations/*/instances/*/searchSessions/*}/searchedResults - 方法:
ListSearchedResults - 请求参数:
ListSearchedResultsRequest
以下示例展示了一个 ListSearchedResultsRequest,它会检索三个结果并跳过前五个结果:
// GET
/v1alpha/projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/searchSessions/SEARCH_SESSION_ID/searchedResults?page_size=3&skip=5
该请求支持以下查询参数:
page_size:每页返回的结果数上限。默认值为 100,最大值为 10000。page_token:上一个ListSearchedResultsResponse中用于检索下一页的令牌。order_by(或 JSON 中的orderBy):可选。用于对结果进行排序的字段。如果省略order_by,UDM 事件结果默认按udm.metadata.event_timestamp降序排序,最先返回最近的事件。如果您在order_by中指定了不带方向后缀的字段路径(例如udm.principal.hostname),则默认情况下,结果会按升序排序。请勿附加asc,因为asc后缀不受支持,并且会返回400 INVALID_ARGUMENT错误。如需按降序对结果进行排序,请将desc后缀附加到字段路径,例如udm.metadata.event_timestamp desc。不支持多列排序。UDM events (eventRecord):在udm字段中使用完全限定路径,例如udm.metadata.event_timestamp desc或udm.principal.hostname。此外,还支持hostname、user、process name和event type等列名称。默认排列顺序为
udm.metadata.event_timestamp降序,即首先返回最近的事件。Entities / ECG (entityContextRecord):使用entity字段中的路径,例如graph.entity.ip或graph.entity.ip desc。data tables (dataTableRecord):使用%<table_alias>.<column_name>格式。 例如%dt.user desc。默认值为第一个数据表列。
Detections (DetectionRecord):使用关键字detection,后跟路径,例如detection.id。联接:对于事件和实体,请使用定义它们的占位符变量。对于所有其他来源,格式保持不变。
例如:
- ECG(UDM-ECG 联接):实体:
$e1.graph.entity.hostname - UDM(与 UDM 的所有联接):
$e1.principal.ip - 数据表(UDM-数据表联接):
%<table_alias>.<column_name>
此外,还支持预定义的别名,例如
hostname、user、process name和event type。对于这些,请使用$e1.hostname.at格式。- ECG(UDM-ECG 联接):实体:
skip:可选。要跳过的结果数量。请勿将此参数与page_token搭配使用。- 默认排序 (
udm.metadata.event_timestamp) 在具有相同时间戳的事件中不具有唯一性。此外,搜索结果的排列顺序是在首次调用ListSearchedResults(searchedResults.list) 时设置的。 - 使用
skip进行分页时,尤其是在并行请求中,请在order_by参数中指定唯一的排序字段(例如udm.metadata.id)。或者,在发送并行skip请求之前提取第一页,以便设置排列顺序。
- 默认排序 (
以下示例展示了成功的 ListSearchedResultsResponse 响应:
{
"searchedResults": [
{
"name":
"projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/searchSessions/SEARCH_SESSION_ID/searchedResults/
RESULT_ID",
"resultRow": {
"eventRecord": {
"event": {
"name":
"projects/PROJECT_NUMBER/locations/LOCATION/instances/INSTANCE_ID/events/EVENT_ID",
"udm": {
"metadata": {
"eventTimestamp": "2026-03-16T14:45:18Z",
"eventType": "USER_LOGIN",
"vendorName": "Microsoft",
"productName": "Azure AD"
}
},
//... other UDM fields
}
//... other UDM fields
"eventLogToken":
"EVENT_LOG_TOKEN"
}
},
{ }
},
{
"name": "projects/PROJECT_NUMBER/locations/
LOCATION/instances/INSTANCE_ID</span>
/searchSessions/SEARCH_SESSION_ID/searchedResults/RESULT_ID", "resultRow": {
"eventRecord": {
//... Similar UDM event structure...
}
}
},
{
""name": "projects/PROJECT_NUMBER/locations/
LOCATION/instances/INSTANCE_ID</span>
/searchSessions/SEARCH_SESSION_ID/searchedResults/RESULT_ID", "resultRow": {
"eventRecord": {
//... Similar UDM event structure...
}
}
}
],
"totalSize": 10000,
"columnNames": [],
"columnSchema": {},
"nextPageToken": "CAKYASAB"
}
如需提取后续结果页,请在下一个 ListSearchedResults 请求的 page_token 查询参数中使用返回的 nextPageToken 值。resultRow 字段包含实际数据。
继续使用每个响应中的 next_page_token 值调用 ListSearchedResults。当 next_page_token 返回空值时,表示已检索到所有结果。
后续步骤
如需详细了解方法、请求和响应字段以及类型,请参阅以下 API 参考文档:
需要更多帮助?获得社区成员和 Google SecOps 专业人士的解答。