במאמר הזה מוסבר איך Cloud Logging מפצל רשומות ביומני ביקורת שהגודל שלהן גדול מדי, ומוצגות הנחיות להרכבה מחדש של יומני הביקורת המפוצלים האלה.
אם רשומה אחת ביומן הביקורת חורגת ממגבלת הגודל, Cloud Logging מפצל את הרשומה ומפיץ את הנתונים שכלולים ברשומה המקורית ביומן הביקורת בין כמה רשומות. יכול להיות שמשתמשים ירצו להרכיב מחדש את יומני הביקורת המפוצלים, כי הרשומות המפוצלות ביומן לא מכילות את כל השדות מיומן הביקורת המקורי.
זיהוי רשומות מפוצלות ביומן הביקורת
רשומות מפוצלות ביומן מכילות מידע על הרשומה המקורית שממנה הן פוצלו. אם רשומה ביומן מכילה את השדה split, הרשומה היא תוצאה של פיצול רשומה גדולה יותר ביומן. השדה split הוא אובייקט LogSplit שמכיל את המידע שנדרש כדי לזהות רשומות קשורות ביומן המפוצל.
כל רשומה מפוצלת ביומן מכילה את השדות הבאים:
split.uid: מזהה ייחודי לקבוצת רשומות ביומן שפוצלו מרשומה מקורית משותפת ביומן. הערך של השדה הזה זהה לכל הרשומות שפוצלו מרשומת היומן המקורית.
split.index: המיקום של הרשומה הזו בסדרה של רשומות מפוצלות. האינדקס של הרשומה הראשונה מהפיצול הוא0. הערךsplit.indexמצורף גם לשדהLogEntry.insertId.
split.totalSplits: מספר רשומות היומן שהרשומה המקורית פוצלה אליהן. הערך של השדה הזה זהה לכל הרשומות שנוצרו מפיצול של רשומת היומן המקורית.
איך רשומה ביומן מפוצלת
כשמפצלים רשומה גדולה מדי ביומן הביקורת, השדות מחולקים בין הרשומות המפוצלות שנוצרות באופן הבא:
כל השדות, מלבד השדה
protoPayload, משוכפלים לכל רשומה מפוצלת.אפשר לפצל את שדות המשנה הבאים
protoPayloadלכמה רשומות:protoPayload.metadataprotoPayload.requestprotoPayload.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של היומן שאוחד מחדש.מסירים את הסיומת
.0מה-LogEntry.insert_idשל היומן שאוחד מחדש.
שאילתות לדוגמה
כדי למצוא את כל רשומות היומן שפוצלו מאותה רשומת יומן מקורית, מריצים את השאילתה הבאה ב-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"},
]
}
}
}