ส่ง Structured Logging จาก Cloud Run ไปที่ Cloud Logging
ถ้าเรารันเซอร์วิสของเราบน GCP Cloud Run ซึ่งเป็น Knative platform ของ GCP เรื่องการจัดการ Log เราจะง่ายมากๆเลย ถ้าเราใช้ Cloud Logging ของ GCP ร่วมด้วย แต่ถ้าเราอยากส่งในแบบ structured logging ก็มี format ที่เราต้องรู้เผื่อช่วยให้ Cloud Logging จัดเก็บข้อมูลเราได้ถูกที่ถูกทาง โพสต์นี้เราจะอธิบาย field พิเศษที่เมื่อเราเขียน Log ลงไปแล้ว Cloud Logging agent และ Cloud Run จะจัดรูปร่างหน้าตาให้ก่อนส่งไปให้ Cloud Logging ว่ามีอะไรบ้าง
ก่อนอื่นต้องรู้ก่อนว่าสิ่งที่ Cloud Run จะส่ง log ไปให้ Cloud Logging อัตโนมัติได้แก่
- Request access logging เมื่อเรารัน http service บน Cloud Run แล้วมี request มาที่ service ของเรา Cloud Run จะสร้าง Request access logging ให้เราอัตโนมัติ ดังนั้นเราไม่ต้องเขียน log แบบนี้เองที่ service
ส่วนใน service เรานั้นถ้าเราต้องการให้ Cloud Run จัดส่ง log ไปให้ เราแค่เขียนข้อมูลออกไปได้ทางช่องทางต่อไปนี้
- เขียนออก Standard Output
- เขียนออก Standard Error
- เขียนลงไฟล์ที่ path
/var/log
- ผ่าน syslog (
dev/log
)
ถ้า log ที่เราเขียนออกไปเป็นแค่ข้อมูลธรรมดา เวลาถูกส่งไปก็จะเอาไปไว้ใน field textPayload
แต่ถ้าเป็น JSON ก็จะถูกส่งไปไว้ใน jsonPayload
ตัวอย่าง structured log ที่เราสามารถส่งไปได้เช่น
{
"message": "before call api"
}
แต่เมื่อ logging agent เจอ log ของเราก็จะแปลงให้อยู่ในรูปแบบของ LogEntry ของ Cloud Logging แบบนี้ให้
{
"insertId": "68dcb56efd46632e6a420008",
"jsonPayload": {
"message": "before call api"
},
"resource": {
"type": "cloud_run_revision",
"labels": {
"project_id": "example-project",
"location": "asia-southeast1",
"service_name": "example-api",
"configuration_name": "example-api",
"revision_name": "example-api-00107-xyz"
}
},
"timestamp": "2022-09-24T02:24:02.551132Z",
"severity": "DEFAULT",
"labels": {
"instanceId": "5e590743b327c074694882e51af18af66b9a8ba37aa0b5c6fd0f8bab20ed7a82ef565db0001c9ea28bd4a2e80a93812a6cc070556d59636daa2b914640bfc0f1433d73"
},
"logName": "projects/example-project/logs/run.googleapis.com%2Fstderr",
"receiveTimestamp": "2022-09-24T02:24:02.556546346Z",
}
จะเห็นว่าเอา JSON ที่เราเขียนลงไป ไปอยู่ใน jsonPayload
แล้วก็เติมข้อมูลในส่วนของ insertId
, resource.type
, resource.labels.[project_id, location, service_name, configuration_name, revision_name]
, timestamp
, severity
, labels.instanceId
, logName
, receiveTimestamp
ให้เราเอง
ในส่วนของ resource.type
, resource.labels.[project_id, location, service_name, configuration_name, revision_name]
, logName
, receiveTimestamp
เราแก้ไขไม่ได้ Cloud Run จะเติมให้เอง แต่เราสามารถปรับข้อมูลอื่นๆของ LogEntry โดยส่ง JSON field ที่แมปกับ LogEntry ของ Cloud Logging ตาม document นี้ของ Cloud Logging https://cloud.google.com/logging/docs/structured-logging#special-payload-fields
ตัวอย่างเช่นถ้าเราอยากปรับ severity
เป็น ERROR
เราก็ใช้ field name "severity"
เป็นค่า "ERROR"
ได้เลย
แต่ถ้าเราอยากแปะ trace id เข้าไปกับ log เพื่อ เชื่อมโยง log กับ trace ของ request ด้วยก็ให้เพิ่มที่ field name logging.googleapis.com/trace
ตัวอย่างเช่น
{
"message": "call api error",
"severity": "ERROR",
"logging.googleapis.com/trace": "projects/example-project/traces/802d43d052c8d19924b565e8ab6314a3"
}
ซึ่งก็จะถูก agent แปลงไปเป็น LogEntry แบบนี้
{
"insertId": "68dcb56efd46632e6a420008",
"jsonPayload": {
"message": "call api error"
},
"resource": {
"type": "cloud_run_revision",
"labels": {
"project_id": "example-project",
"location": "asia-southeast1",
"service_name": "example-api",
"configuration_name": "example-api",
"revision_name": "example-api-00107-xyz"
}
},
"timestamp": "2022-09-24T02:24:02.551132Z",
"severity": "ERROR",
"labels": {
"instanceId": "5e590743b327c074694882e51af18af66b9a8ba37aa0b5c6fd0f8bab20ed7a82ef565db0001c9ea28bd4a2e80a93812a6cc070556d59636daa2b914640bfc0f1433d73"
},
"logName": "projects/example-project/logs/run.googleapis.com%2Fstderr",
"trace": "projects/example-project/traces/802d43d052c8d19924b565e8ab6314a3",
"receiveTimestamp": "2022-09-24T02:24:02.556546346Z",
}
สุดท้าย แล้วเราจะได้ค่า trace id ของ request มาได้ยังไง
เราสามารถแกะ trace id มาได้จาก http header ที่ชื่อว่า X-Cloud-Trace-Context
โดย format ของ header จะเป็นแบบนี้
"X-Cloud-Trace-Context: TRACE_ID/SPAN_ID;o=TRACE_TRUE"
ถ้าสนใจแค่ trace id ก็แค่ parse ค่าแรกก่อน slash มาได้เลย
References
Cloud Run Logging: https://cloud.google.com/run/docs/logging
Cloud Logging Strucutured Logging: https://cloud.google.com/logging/docs/structured-logging