本文档介绍 Cloud Logging 如何拆分过大的审核日志 参评资料,并就如何重新组合这些主题提供指导 拆分审核日志。
当单个审核日志条目超过大小限制时, Cloud Logging 会拆分该条目, 跨多个条目的原始审核日志条目。用户可能需要重新组装 拆分审核日志,因为各个拆分日志条目并未包含全部 原始审核日志中的字段。
识别拆分后的审核日志条目
拆分日志条目包含有关它们来自的原始条目的信息
被拆分了如果日志条目包含
split
字段,则
该条目是拆分较大的原始日志条目的结果。split
字段是 LogSplit
对象,该对象包含识别相关拆分日志所需的信息
条目。
每个拆分日志条目都包含以下字段:
split.uid
:从一个共同的原始日志条目拆分出来的一组日志条目的唯一标识符。对于 从原始日志条目拆分的条目数。split.index
:此条目在拆分条目系列中的位置。通过 拆分中的第一个条目的索引为0
。split.index
还会附加到LogEntry.insertId
字段中的值。split.totalSplits
:原始日志包含的日志条目数 被拆分成了条目。从原始日志条目拆分出的所有条目的此字段值都相同。
如何拆分日志条目
当过大的审核日志条目被拆分时,这些字段会按如下方式分布在生成的拆分日志条目中:
除
protoPayload
字段外,所有字段都会复制到每个分屏条目中。以下
protoPayload
子字段可以拆分到多个条目中:protoPayload.metadata
protoPayload.request
protoPayload.response
所有其他
protoPayload
子字段都包含在所有分屏条目中。对于
protoPayload.metadata
、protoPayload.request
和protoPayload.response
个子字段,可以拆分以下字段类型 跨多个条目:
如果某个字段是可分割字段的成员,但不是可分割字段类型之一,则该字段只会出现在其中一个分块日志中。
例如,protoPayload.request
子字段中的布尔值字段只能
出现在一个拆分日志条目中,但 protoPayload.request
中的字符串字段
子字段的内容可以拆分到多个拆分日志条目。
有关长度条目拆分时间的示例,请参阅 日志条目拆分示例。
具有多个值的重复字段
当 protoPayload.metadata
、protoPayload.request
或
protoPayload.response
字段包含重复值列表,此列表可能会
拆分并分布到多个拆分日志条目。
例如,值 ["foo", "bar", "baz"] 的列表可能会分成 2 个
列表:["foo", "ba"] 和 ["", "r", "baz"]。第一个列表是带有
第 split.index
个列表(共 0
个),第二个列表位于包含 split.index
的条目中:
1
。第二个列表以空字符串开头,用于保持
列表中的元素,并指明这些元素在列表中位于相同位置
必须将不同的列表联接在一起。在此示例中,ba
是第二个
条目 0
中的列表元素,而 r
是条目 1
中的第二个列表元素,因此
在重新组合原始列表时,它们会按 bar
的顺序重新组合。
大型非重复字段
拆分较大的非重复 Struct
和 string
字段时,这些字段
处理方式如下:
string
字段在字符级别(而不是字节级别)拆分。 因此,多字节字符不会更改。LogEntry.split.index
用于控制分屏非重复字段内容的排序。
重新组合拆分日志条目
如需重新组合一组拆分日志,请完成以下步骤:
按
LogEntry.split.index
对拆分的审核日志集进行排序 订单。创建第一个拆分日志的副本,其中
LogEntry.split.index == 0
。 此副本是重组日志的开头。对于其余日志条目,请遍历所有可拆分字段
protoPayload
,然后针对每个字段完成以下步骤:如果重新组合的日志中已存在该字段,请将 将该字段添加到重新组合的日志中。
如果重新组合的日志中不存在该字段,请将该字段复制到 重组的日志
拆分时,重复字段会保留其元素的索引,因此您可以 重新组合重复字段时,请在元素级别应用这些步骤。
遍历可拆分字段后,清除
LogEntry.split
的 重新组合的日志。从重组日志的
LogEntry.insert_id
中移除.0
后缀。
查询示例
如需查找从同一原始日志条目中拆分出来的所有日志条目,请运行以下命令: 以下查询中的 Logs Explorer,替换了 将 UID 变量替换为所需的值:
split.uid="UID"
例如:
split.uid="abc123"
如需查找属于任何分屏的所有日志条目,请运行以下查询:
split:*
过滤掉拆分的审核日志
您可以使用以下过滤条件从查询中排除所有拆分审核日志:
split.totalSplits = 0
您还可以使用以下过滤条件,仅包含拆分审核日志的第一个条目,并排除其余条目:
split.index = 0
日志条目拆分示例
以下示例展示了一条审核日志条目,该条目在拆分为四个新的条目之前 日志条目。新条目展示了 拆分操作。
拆分前审核日志条目过大
{
"insertId": "567",
"logName": "projects/1234/logs/cloudaudit.googleapis.com%2Fdata_access",
"resource": {
"type": "audited_resource"
},
"protoPayload": {
"serviceName": "example.googleapis.com",
"methodName": "google.cloud.example.ExampleMethod",
"resourceName": "projects/1234/resources/123",
"status": {
"code": 0
},
"authenticationInfo": {
"principalEmail": "user@example_company.com"
},
"authorizationInfo": [
{
"resource": "example.googleapis.com/projects/1234/resources/123",
"permission": "examples.get",
"granted": "true"
}
],
"request" {
"boolField": true,
"numberField": 123,
"stringField": "Very long string that needs 2 log entries.",
"structField": {
"nestedNumberField": 1337,
"nestedStringField": "Another long string that needs 2 log entries.",
},
"listField" [
{"value": "short 1"},
{"value": "Yet another long string."},
{"value": "short 2"},
{"value": "short 3"},
]
}
}
}
拆分后审核日志条目过大
原始日志条目会拆分为以下条目。请注意,每个条目
包含 split
对象,其 uid
和 totalSplits
值为 4
。每个
条目的 split.index
值为 0
、1
、2
或 3
,表示
拆分日志条目的顺序。
拆分日志条目,索引 0
以下是第一个拆分日志条目,其 split.index
值为 0
。
{
"insertId": "567.0",
"logName": "projects/1234/logs/cloudaudit.googleapis.com%2Fdata_access",
"resource": {
"type": "audited_resource"
},
"split": {
"uid": "789+2022-02-22T12:22:22.22+05:00",
"index": 0,
"totalSplits": 4,
},
"protoPayload": {
// The following fields are included in all split entries
"serviceName": "example.googleapis.com",
"methodName": "google.cloud.example.ExampleMethod",
"resourceName": "projects/1234/resources/123",
"status": {
"code": 0
},
"authenticationInfo": { // small size; included in all split entries
"principalEmail": "user@example_company.com"
},
// The following field is included in this split entry only.
"authorizationInfo": [
{
"resource": "spanner.googleapis.com/projects/1234/datasets/123",
"permission": "databases.read",
"granted": "true"
}
],
// The following field is split across all the split entries
"request" {
// boolField and numberField can only be in one split.
"boolField": true,
"numberField": 123,
// Split with the next LogEntry.
"stringField": "Very long string that ",
}
}
}
拆分日志条目,索引 1
以下是下一个拆分日志条目,split.index
值为 1
。
{
"insertId": "567.1",
"logName": "projects/1234/logs/cloudaudit.googleapis.com%2Fdata_access",
"resource": {
"type": "audited_resource"
},
"split": {
"uid": "567+2022-02-22T12:22:22.22+05:00",
"index": 1,
"totalSplits": 4,
},
"protoPayload": {
"serviceName": "example.googleapis.com",
"methodName": "google.cloud.example.ExampleMethod",
"resourceName": "projects/1234/resources/123",
"status": {
"code": 0
},
"authenticationInfo": {
"principalEmail": "user@example_company.com"
},
"request" {
// boolField and numberField aren't present
// Continued from the previous entry.
"stringField": "needs 2 log entries.",
"structField": {
"nestedNumberField": 1337,
// Split with the next LogEntry.
"nestedStringField": "Another long string ",
}
}
}
}
拆分日志条目,索引 2
下面是下一个分块日志条目,其 split.index
值为 2
。
{
"insertId": "567.2",
"logName": "projects/1234/logs/cloudaudit.googleapis.com%2Fdata_access",
"resource": {
"type": "audited_resource"
},
"split": {
"uid": "567+2022-02-22T12:22:22.22+05:00",
"index": 2,
"totalSplits": 4,
},
"protoPayload": {
"serviceName": "example.googleapis.com",
"methodName": "google.cloud.example.ExampleMethod",
"resourceName": "projects/1234/resources/123",
"status": {
"code": 0
},
"authenticationInfo": {
"principalEmail": "user@example_company.com"
},
request {
"structField": {
// Continued from the previous entry.
"nestedStringField": "that needs 2 log entries.",
}
"listField" [
{"value": "short 1"},
{"value": "Yet another "}, // Split with the next LogEntry.
// Missing two values, split with the next LogEntry.
]
}
}
}
拆分日志条目,索引 3
以下是最后一个拆分日志条目,其 split.index
值为 3
。
{
"insertId": "567.3",
"logName": "projects/1234/logs/cloudaudit.googleapis.com%2Fdata_access",
"resource": {
"type": "audited_resource"
},
"split": {
"uid": "567+2022-02-22T12:22:22.22+05:00",
"index": 3,
"totalSplits": 4,
},
"protoPayload": {
"serviceName": "example.googleapis.com",
"methodName": "google.cloud.example.ExampleMethod",
"resourceName": "projects/1234/resources/123",
"status": {
"code": 0
},
"authenticationInfo": {
"principalEmail": "user@example_company.com"
},
"request" {
"listField" [
{}, // Padding to ensure correct positioning of elements in split repeated fields.
{"value": "long string."}, // Continuation of the second repeated field.
{"value": "short 2"},
{"value": "short 3"},
]
}
}
}