分割稽核記錄項目

本文說明 Cloud Logging 如何分割過大的稽核記錄項目,並提供如何重新組合這些分割稽核記錄的指引。

如果單一稽核記錄項目超過大小限制,Cloud Logging 會拆分該項目,並將原始稽核記錄項目中的資料分散到多個項目中。使用者可能會想要重新組合已分割的稽核記錄,因為個別分割記錄項目不包含原始稽核記錄中的所有欄位。

辨識分割的稽核記錄項目

分割記錄項目包含原始項目的分割資訊。如果記錄項目包含 split 欄位,則該項目是將較大的原始記錄項目拆分的結果。split 欄位是 LogSplit 物件,其中包含用於識別相關分割記錄項目所需的資訊。

每個分割記錄項目都包含下列欄位:

  • split.uid:從一般原始記錄項目分割出來的記錄項目群組專屬 ID。所有從原始記錄項目分割出來的項目,這個欄位的值都會相同。

  • 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"]。第一個清單是 0split.index 項目,第二個清單是 1split.index 項目。第二個清單開頭為空字串,可維持清單中元素的位置,並指出不同清單中相同位置的元素必須合併。在這個範例中,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 後置字串。

查詢範例

如要找出從相同原始記錄項目分割出的所有記錄項目,請在 記錄檔探索工具 中執行以下查詢,並將 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"},
      ]
    }
  }
}