本文說明 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"},
]
}
}
}