本文說明 Cloud Logging 如何分割過大的稽核記錄項目,並提供如何重新組合這些分割稽核記錄的指引。
如果單一稽核記錄項目超過大小限制,Cloud Logging 會拆分該項目,並將原始稽核記錄項目中的資料分散到多個項目中。使用者可能會想要重新組合已分割的稽核記錄,因為個別分割記錄項目不包含原始稽核記錄中的所有欄位。
辨識分割的稽核記錄項目
分割記錄項目包含原始項目的分割資訊。如果記錄項目包含 split 欄位,則該項目是將較大的原始記錄項目拆分的結果。split 欄位是 LogSplit 物件,其中包含用於識別相關分割記錄項目所需的資訊。
每個分割記錄項目都包含下列欄位:
- split.uid:從一般原始記錄項目分割出來的記錄項目群組專屬 ID。所有從原始記錄項目分割出來的項目,這個欄位的值都會相同。
- 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"]。第一個清單是 0 的 split.index 項目,第二個清單是 1 的 split.index 項目。第二個清單開頭為空字串,可維持清單中元素的位置,並指出不同清單中相同位置的元素必須合併。在這個範例中,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後置字串。
查詢範例
如要找出從相同原始記錄項目分割出的所有記錄項目,請在 記錄檔探索工具 中執行以下查詢,並將 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"},
      ]
    }
  }
}