拆分审核日志条目

本文档介绍 Cloud Logging 如何拆分过大的审核日志 参评资料,并就如何重新组合这些主题提供指导 拆分审核日志。

当单个审核日志条目超过大小限制时, Cloud Logging 会拆分该条目, 跨多个条目的原始审核日志条目。用户可能需要重新组装 拆分审核日志,因为各个拆分日志条目并未包含全部 原始审核日志中的字段。

识别拆分后的审核日志条目

拆分日志条目包含有关它们来自的原始条目的信息 被拆分了如果日志条目包含 split 字段,则 该条目是拆分较大的原始日志条目的结果。split 字段是 LogSplit 对象,该对象包含识别相关拆分日志所需的信息 条目。

每个拆分日志条目都包含以下字段:

  • split.uid:从一个共同的原始日志条目拆分出来的一组日志条目的唯一标识符。对于 从原始日志条目拆分的条目数。

  • split.index:此条目在拆分条目系列中的位置。通过 拆分中的第一个条目的索引为 0split.index 还会附加到 LogEntry.insertId 字段中的值。

  • split.totalSplits:原始日志包含的日志条目数 被拆分成了条目。从原始日志条目拆分出的所有条目的此字段值都相同。

如何拆分日志条目

当过大的审核日志条目被拆分时,这些字段会按如下方式分布在生成的拆分日志条目中:

  • protoPayload 字段外,所有字段都会复制到每个分屏条目中。

  • 以下 protoPayload 子字段可以拆分到多个条目中:

    • protoPayload.metadata
    • protoPayload.request
    • protoPayload.response
  • 所有其他 protoPayload 子字段都包含在所有分屏条目中。

  • 对于 protoPayload.metadataprotoPayload.requestprotoPayload.response 个子字段,可以拆分以下字段类型 跨多个条目:

如果某个字段是可分割字段的成员,但不是可分割字段类型之一,则该字段只会出现在其中一个分块日志中。

例如,protoPayload.request 子字段中的布尔值字段只能 出现在一个拆分日志条目中,但 protoPayload.request 中的字符串字段 子字段的内容可以拆分到多个拆分日志条目。

有关长度条目拆分时间的示例,请参阅 日志条目拆分示例

具有多个值的重复字段

protoPayload.metadataprotoPayload.requestprotoPayload.response 字段包含重复值列表,此列表可能会 拆分并分布到多个拆分日志条目。

例如,值 ["foo", "bar", "baz"] 的列表可能会分成 2 个 列表:["foo", "ba"] 和 ["", "r", "baz"]。第一个列表是带有 第 split.index 个列表(共 0 个),第二个列表位于包含 split.index 的条目中: 1。第二个列表以空字符串开头,用于保持 列表中的元素,并指明这些元素在列表中位于相同位置 必须将不同的列表联接在一起。在此示例中,ba 是第二个 条目 0 中的列表元素,而 r 是条目 1 中的第二个列表元素,因此 在重新组合原始列表时,它们会按 bar 的顺序重新组合。

大型非重复字段

拆分较大的非重复 Structstring 字段时,这些字段 处理方式如下:

  • string 字段在字符级别(而不是字节级别)拆分。 因此,多字节字符不会更改。

  • LogEntry.split.index 用于控制分屏非重复字段内容的排序。

重新组合拆分日志条目

如需重新组合一组拆分日志,请完成以下步骤:

  1. LogEntry.split.index 对拆分的审核日志集进行排序 订单。

  2. 创建第一个拆分日志的副本,其中 LogEntry.split.index == 0。 此副本是重组日志的开头。

  3. 对于其余日志条目,请遍历所有可拆分字段 protoPayload,然后针对每个字段完成以下步骤:

    1. 如果重新组合的日志中已存在该字段,请将 将该字段添加到重新组合的日志中。

    2. 如果重新组合的日志中不存在该字段,请将该字段复制到 重组的日志

      拆分时,重复字段会保留其元素的索引,因此您可以 重新组合重复字段时,请在元素级别应用这些步骤。

  4. 遍历可拆分字段后,清除LogEntry.split的 重新组合的日志。

  5. 从重组日志的 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 对象,其 uidtotalSplits 值为 4。每个 条目的 split.index 值为 0123,表示 拆分日志条目的顺序。

拆分日志条目,索引 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"},
      ]
    }
  }
}