งาน Week นี้ merge วุ่นวาย และระลึกชาติ เพราะไปช่วยเรื่องอื่นมานานนนน และมีเรื่องวุ่นๆเรื่อง Branching กัน ไม่อยากแตก ไม่อยาก Tag แต่ต้องการให้ keep //ดูย้อนแย้งระดับนึง 555
สำหรับสัปดาห์นี้จะเป็นตอนต่อจากของ Week ก่อนหน้า The Cloud Camp Week#12 (Observability#1) Opentelemetry - Log / Metric โดยเพิ่มเติมในส่วนของ Trace ครับ
Traces
Where is it happening? - เกิดที่ไหน จุดไหน และมี Flow อย่างไร
Tracing เป็นตัวเชื่อมความสัมพันธ์ระหว่าง Activity หรือ Span รวมไปถึงตัว Log และ Metric ว่าเกี่ยวข้องกันยังในในแต่ละระบบ หรือ microservice ในช่วงเวลาหนึ่ง โดยมี Keyword ที่ต้องรู้ก่อน ดังนี้
- span = unit of work งานที่เกิดขึ้น ซึ่งมีระยะเวลาชัดเจน (Call Method / API)
- sub span = operation ย่อยๆใน span - sequence of span = ลำดับของ span
- propagation - การจัดกลุ่มของ span ให้เป็นชุดเดียวกัน ทั้ง Internal (ในระบบเดียวกัน) และ External (System / Microservice อื่นๆ) โดยจะมี Key พวก trace_id หรือ CorrealationId เอาไว้อ้างอิงว่ามี span ชุดเดียวกัน
NOTE: จริงๆ อาจจะมองแบบ Transaction ของ DB ก็ได้ แต่ทว่า DB เองมีส่วนของการ Rollback ไว้ให้ด้วย
- Traces Pipeline
- TracerProvider ตัวสร้าง Tracer
- Tracer - ตัวที่สร้าง Span
- SpanProcessor - บอกรูปแบบการ Export Span
- SimpleSpanProcessor - ทำตามลำดับตรงๆเลย แต่เพิ่ม Overhead ขึ้นมา เวลา Request / Response นานขึ้น เหมาะกับงานที่เน้นลำดับ หรือ เอามา Debug
- BatchSpanProcessor - ทำแบบ Async ไปเลย แยก Thread กันส่งไปเลย - SpanExporter ส่งข้อมูลออกมา
- Resource
Traces เราจะรู้ระยะเวลาระหว่าง Microservice (Span) พวก Duration ถ้าตรวจสอบแล้วเจอเคสผิดปกติ เช่น จาก A > B เกินจาก Thresold ที่กำหนด เราสามารถตัดสินใจได้ เช่น
- แจ้งทีมงาน เพื่อมาปรับปรุง หาสาเหตุ
- คุยกับ Business ของ root cause ที่จำเป็น และถ้า App มีทำ Feature Flags อยู่ เปิดตัว Circuit Breaker เพื่อ By Pass ให้ตอบสนองให้เร็วขึ้น
- Insight Span
- Span Attribute - บอกข้อมูล Metadata ที่ฝากไว้ โดยพวก Lib Opemtelemetry มันจะเตรียม Key สำคัญ เพื่อให้เราเอาข้อมูลให้ยัดแล้ว อย่างพวก HTTP_METHOD / HTTP_FLAVOR / HTTP_URL หรือ NET_PEER_IP เป็นต้น
- Span Kind - บอกรูปแบบการเชื่อมต่อ เอามาจับกลุ่ม โดยมี 5 แบบ ดังนี้
- Internal - คุยภายใน Service เดียวกัน
- Client - Server สำหรับคุยระหว่าง Service
- Producer - Consumer สำหรับคุยกับระบบ Queue เช่น RabbitMQ / Apache Kafka เป็นต้น - Span Status - บอกผลการ Request / Response ปกติจะเป็นค่า UNSET ให้เรามากำหนด Logic ในการกำหนดค่าเอง เช่น ยิง API สำเร็จไหม
- UNSET
- OK - พวก http code 2xx
- ERROR - พวก http code 4xx / 5xx - Span Event - ใน Span เรามี Data อะไรบ้าง โดยจะเอาไปต่อยอดในส่วนของ Event Sourcing ถ้าระบบมันพัง เราจะข้อมูลใน Span Event มาปรับเป็น Tx แทนได้ อารมณ์ Log ใน DB
- Context บอกเส้นทางที่ต่อเนื่องกันของ Span ภายใน Service เดียวกัน ใน OpenTelemetry มีทั้งแบบ ฺ(Base on Python ยังไม่ได้ดูภาษาอื่นๆ)
- Manual ต้องสร้าง Token และ Attach เอง
- Auto ใส่ With ครอบ
- propagation
B3Format - เป็นรูปแบบกลางที่ช่วยทำตัว propagation ของ OpenTelemetry โดยแปะไปในทุก Request และเป็น Seed เพื่อเอาไป Generate Token ในเวลาที่ข้าม Microservice / System
พวก Telemetry มี Standard กลางนะ อย่าง Trace มีตัว Trace Context (w3.org) / Trace Context Level 2 (w3.org)
dotnet มีนะ หาตัวอย่างไม่เจอ เจอแต่ Issue แทน https://github.com/open-telemetry/opentelemetry-dotnet/issues/884 555
Update เจอแล้วของ OpenTelemetry เอง opentelemetry-dotnet/examples/AspNetCore at main · open-telemetry/opentelemetry-dotnet (github.com)
Resources
ส่วนที่บอกข้อมูลตั้งต้นให้กับ Metric / Trace / Log / Baggage เอาไปใช้งานได้เลย อาทิ เช่น
- กลุ่ม Infra: OS / Platform หรือ ถ้าใน K8S เป็นพวก Podname / Deployment / NameSpace เป็นต้น
- กลุ่ม App: ชื่อ APP (Service) / Version / Enviroment เป็นต้น
- และอื่นๆ
ข้อมูลตั้งต้นใน Object Resource จะเก็บในรูปแบบ Key/Value
- Pre-Define Key เตรียมไว้ให้ พวก Env / App เช่น ResourceAttributes.SERVICE_NAME / ResourceAttributes.SERVICE_VERSION แล้วระบบอื่นๆ ที่ Implement ตามแนวทาง W3C จะดึงไปใช้ได้เลย
- หรือ ถ้าไม่มี Key นั้นๆให้ ก็สามารถกำหนดเอง
ResourceDetector - เอาช่วยดึง App / Infra Resource ขึ้นมา โดยมี Implement ตามไปในแต่ละภาษา
NOTE: Object Resource สร้างแล้วจะแก้ไขไม่ได้ ถ้ามีเพิ่มต้องใช้ Operation Merge ใส่เพิ่มเข้าไป
OTLP Collector
เป็นตัวที่ช่วยจัดเก็บ Data จาก App โดยมี Implementation ไว้หลายแบบ เช่น On-Premise / Cloud / K8S Operator / Functions as a Service เป็นต้น โดยจะช่วยทำงานส่วน
- Auto-Instrucmentation - ให้สร้าง Telemetry (Metric / Trace / Log / Baggage) ให้เลย โดยมีแบบ Agent หรือเพิ่ม Lib ไว้ใน App ให้มันสร้าง Trace-Span หรือ Metric เองเลย
Note:
- ใน K8S ต้องไปเพิ่ม Anotation ให้มันสร้าง Trace-Span หรือ Metric เองเลย ดูเพิ่มได้จาก Injecting Auto-instrumentation | OpenTelemetry
- จากนั้นเดี๋ยวมันจะไป Deployment modes มีหลายแบบตามนี้ >> open-telemetry/opentelemetry-operator: Kubernetes Operator for OpenTelemetry Collector (github.com) - Collector - ทำหน้าที่เป็นตัวกลาง (Agent) รับ Telemetry และจัดส่งให้ถูก Database ของ Log / Metric / Trace แบบนี้จะลด Coupling ของระบบได้ App รู้จัก Agent ตัวเดียว
Ref: Instrumentation | OpenTelemetry / https://github.com/open-telemetry/opentelemetry-operator#opentelemetry-auto-instrumentation-injection
ภาพรวมทั้งหมด
จากเรื่อง Observability > Opentelemetry - Log / Metric / Trace น่าเขียนภาพรวมได้ ประมาณนี้ ถ้าไม่ครบ หรือต่อหล่นไปทักได้
เว็บ Opentelemetry มี 2 Path for Dev / Ops บางทีหาแล้วจะงงๆ ตอนแรกเวลา Search เข้ามาก็งงๆอยู่ เรื่องเดียวกัน มี 2 อัน ตอนแรกเข้าใจว่าแบบสั้น /ยาว จริงๆมัน Dev / Ops
พวก Telemetry กำหนด Pattern / Format ดีๆ อะไรควรเก็บไม่ควรเก็บ ถ้าเก็บมากไปจะมี Cost Storage หรือ Pre-Process เพิ่ม
วันเสาร์มีมาลอง Lab กันคับ ลองไปมายังคิดอยู่ เดียวหลัง Blog นี้จบจะไปไล่ดูต่อ แปะ Resource ไว้ก่อน ช่วงบ่ายหนีมา dotnet ก่อนมีทำไว้นะ pingkunga/dotnet23observability (github.com) >> 2Opentelemetry ถ้าจัดอะไรครบจะ push ขึ้นไป
แต่ถ้าเอาขึ้นมาได้แล้ว เหลือการอ่านทำความเข้าใจ และตีความ ที่ยังงๆๆ แต่ตอนนี้เอาให้ขึ้นได้ก่อน 55
- Grafana Agent Flow: Simplifying Monitoring and Telemetry Collection for Kubernetes Clusters | by TJ. Podobnik, @dorkamotorka | Level Up Coding (gitconnected.com)
- Setting up an End-to-End Monitoring System with Grafana Stack (LGTM) | by TJ. Podobnik, @dorkamotorka | Level Up Coding (gitconnected.com)
- Sending Traces with the Grafana Agent for Grafana Tempo | by Gleydson Cavalcanti Observability | Medium >> ดูอันนี้เยอะ
- Sending and Filtering Python Logs with OpenTelemetry | SigNoz >> Log
แปะไว้หน่อย ถ้าเจอ Error Transient error StatusCode.UNAVAILABLE encountered while exporting metrics ไปดู Lib ที่ใช้กับ Protocal ที่กำหนดนะ กำหนด http ใช้แบบ Lib ของ Grpc 555
อ๋อนอกจาก Otel Collector ที่ผมไปลองใน dotnet ใน LAB ใช้ LGTM Stack + Grafana Agent ซึ่งตัว Grafana Agent หน้าที่เหมือนกับ Otel Collector กำหนดปลายทางได้ทั้งแบบ YAML / River ตัว River ดู Doc ได้จากนี้เลย Components reference | Grafana Agent documentation
ภาพรวม LGTM Stack + Grafana Agent น่าจะประมาณนี้ หลังจะปะติดปะต่อเสร็จ
พอรันขึ้นแล้วอ่า เลข Trace_Id Link กันมันแบบนี้เอง เหลือ Metric ยังกดไม่เจอ และการตีความตัวเลข นำเสนอ และตัดสินใจ
สรุปที่ลองไป
- Python ใน LAB วันเสาร์
- dotnet (pingkunga/dotnet23observability (github.com) >> 2Opentelemetry)
- ลองแก้เชื่อมจาก Infra ใน Repo มาเป็น LGTM Stack + Grafana Agent (เปิด GRPC ก็ใช้ได้)
- dotnet ทำได้แล้ว มี Log / Trace แยก Span (ใน .NET เรียก Span ว่า Activity)
- แล้ว มีตัว Spring Boot พอลอง Google Search Config แล้วไปเจอ เอามาแปะไว้ดีกว่า
- Spring Boot logging with Loki, Promtail, and Grafana (Loki stack) - DEV Community
- Open Telemetry | Prometheus | Exemplars | Loki | Tempo | Grafana (k8staz.com)
Reference
- Traces | OpenTelemetry
- Resources | OpenTelemetry
- OpenTelemetry Operator for Kubernetes | OpenTelemetry
- Components reference | Grafana Agent documentation
- Observability Primer | OpenTelemetry
- opentelemetry-specification/specification/trace/api.md at main · open-telemetry/opentelemetry-specification (github.com)
Discover more from naiwaen@DebuggingSoft
Subscribe to get the latest posts sent to your email.