Observability
อนุมานสถานะภายในของระบบจากผลลัพธ์ภายนอกที่มันปล่อยออกมา
คืออะไร
หัวข้อที่มีชื่อว่า “คืออะไร”Observability เป็นแนวปฏิบัติในแวดวงวิศวกรรมซอฟต์แวร์และ DevOps ที่ว่าด้วยแนวทางเชิงระบบในการทำความเข้าใจว่า สถานะภายในของระบบสามารถอนุมานได้ดีเพียงใดจากผลลัพธ์ภายนอกที่มันปล่อยออกมา คำนี้ยืมมาจาก control theory ซึ่ง “observability” ของระบบวัดว่าเราสามารถระบุสถานะภายในของระบบได้ดีเพียงใดจากค่า output ที่สังเกตได้ ในบริบทซอฟต์แวร์ โดยเฉพาะระบบแบบกระจาย (distributed systems) มันหมายถึงความสามารถในการรวบรวมข้อมูลเกี่ยวกับการทำงานของโปรแกรม สถานะภายในของแต่ละ module และการสื่อสารระหว่างคอมโพเนนต์ ผ่านการเก็บ เชื่อมโยง และวิเคราะห์ข้อมูล telemetry จาก logs, metrics และ traces
เป้าหมายหนึ่งของ observability คือการลดปริมาณ “ความรู้ล่วงหน้า” (prior knowledge) ที่จำเป็นต่อการ debug ปัญหาให้เหลือน้อยที่สุด — ทีมที่มีแค่ monitoring แบบเดิมต้องพึ่งชุด dashboard/alert ที่กำหนดไว้ล่วงหน้าและความเชี่ยวชาญเฉพาะทาง ในขณะที่ทีมที่มี observability ที่ดีสามารถตั้งคำถามใหม่กับระบบได้แบบ ad-hoc โดยไม่ต้อง deploy code ใหม่เพื่อเก็บข้อมูลเพิ่ม นี่คือความแตกต่างสำคัญระหว่าง monitoring (เฝ้าดูสิ่งที่รู้ล่วงหน้าว่าจะพัง) กับ observability (สำรวจสิ่งที่ไม่เคยคาดคิดมาก่อน) — observability จึงเป็นรากฐานของ Site Reliability Engineering (SRE) เพราะมันคือขั้นตอนแรกในการวิเคราะห์และแก้ปัญหา service outage
สามเสาหลักของ Observability — Logs · Metrics · Traces
หัวข้อที่มีชื่อว่า “สามเสาหลักของ Observability — Logs · Metrics · Traces”- Logs: บันทึกเหตุการณ์รายชิ้นที่ประทับเวลา (time-stamped) ให้รายละเอียดว่าระบบทำอะไรในแต่ละช่วง รวมถึง error, warning และข้อความ informational จำเป็นต่อการ debug และเข้าใจลำดับเหตุการณ์ที่นำไปสู่สถานะหนึ่ง อาจเป็นแบบ structured (เช่น JSON) หรือ unstructured (ข้อความธรรมดา)
- Metrics: ค่าตัวเลขที่แทนสถานะหรือประสิทธิภาพของระบบตามเวลา เก็บเป็น time series ที่มี timestamp, ชื่อ, ค่า และ label ประกอบ มักถูก aggregate เพื่อให้ภาพรวมระดับสูงของสุขภาพระบบ เช่น CPU, memory, request rate, error rate, response time — สำคัญต่อการหาแนวโน้ม ตรวจจับ anomaly และจุดชนวน alert
- Traces: ติดตามการเดินทางของ request หนึ่งรายการขณะมันวิ่งผ่าน component และ service ต่าง ๆ ในระบบแบบกระจาย ให้แผนที่เส้นทางพร้อมข้อมูลเวลาในแต่ละช่วง (span) ช่วยชี้จุดคอขวด ความล่าช้า และ dependency ระหว่างบริการ มีค่ายิ่งใน microservices ที่ request หนึ่งอาจไหลผ่านสิบกว่าบริการ
ทั้งสามเสานี้เสริมกัน: metrics ใช้เตือนทีมว่ามีปัญหาเกิดขึ้น traces แสดงเส้นทางการทำงานที่ทำให้เกิดปัญหานั้น และ logs ให้บริบทรายละเอียดที่จำเป็นสำหรับแก้ไข — การมีครบทั้งสามเสาและ “เชื่อมโยง” (correlate) เข้าด้วยกันได้ (เช่นผ่าน trace ID เดียวกัน) คือสิ่งที่ทำให้ observability เกิดขึ้นจริง ไม่ใช่แค่การมี log จำนวนมากเฉย ๆ
ทำอย่างไร
หัวข้อที่มีชื่อว่า “ทำอย่างไร”แนวปฏิบัติหลักในการสร้าง observability ให้ระบบมี 3 ขั้นตอนต่อเนื่องกัน
- Instrumentation — ใส่ code เพื่อเก็บ telemetry ณ จุดที่มีความหมายทางธุรกิจหรือทางเทคนิค เช่น เริ่ม/จบ operation, จับ exception, นับจำนวน request ควรทำทั้งระดับ infrastructure (CPU, memory, GC) และระดับ application/domain (เช่น “จำนวนคำสั่งซื้อที่ล้มเหลว”)
- Correlation — เชื่อม logs, metrics และ traces เข้าด้วยกันด้วย identifier ร่วม เช่น
trace_id/correlation_idเพื่อให้เมื่อ alert แจ้งเตือนจาก metric หนึ่งตัว วิศวกรสามารถกระโดดไปดู trace และ log ที่เกี่ยวข้องได้ทันทีโดยไม่ต้องเดา - Visualization & Alerting — ใช้ dashboard แสดงผลรวม ตั้ง alert บน threshold หรือ anomaly และทำ SLO/error-budget เพื่อให้ทีมรู้ว่าเมื่อไรควรเข้าไปดูระบบ
มาตรฐานเปิดที่ครองพื้นที่นี้ในปัจจุบันคือ OpenTelemetry (OTel) ซึ่งรวม SDK/API สำหรับสร้าง logs, metrics, traces แบบ vendor-neutral — instrument code ครั้งเดียว แล้วส่งออกไปยัง backend ใดก็ได้ (Prometheus, Jaeger, Grafana, Application Insights ฯลฯ) ผ่าน exporter ที่ตั้งค่าได้ ทำให้ทีมไม่ถูกผูกติดกับผู้ให้บริการรายใดรายหนึ่ง (avoid vendor lock-in)
Pete Hodgson ในบทความ Domain-Oriented Observability (เผยแพร่บนเว็บไซต์ของ Martin Fowler) ชี้ปัญหาที่พบบ่อย: การ instrument code ตรง ๆ ด้วยการเรียก logger/metrics client กระจัดกระจายอยู่ทั่ว domain logic ทำให้ code อ่านยากและปนกันระหว่างตรรกะทางธุรกิจกับ plumbing ทางเทคนิค ทางแก้คือ pattern ที่เรียกว่า Domain Probe — สร้าง high-level API ที่มีชื่อ method สื่อความหมายทางธุรกิจ (เช่น OrderProbe.DiscountApplied(...)) ห่อหุ้ม logger/metrics/tracer ไว้ภายใน ทำให้ domain class ไม่ต้องรู้จัก infrastructure ของการ observe เลย code domain จึงยังคงอ่านง่ายและทดสอบง่าย ในขณะที่ทีม observability ปรับ implementation เบื้องหลัง probe ได้อย่างอิสระ
ตัวอย่าง
หัวข้อที่มีชื่อว่า “ตัวอย่าง”ตัวอย่างการ instrument ด้วย System.Diagnostics.ActivitySource (ซึ่งเป็น implementation ของ Tracer ใน OpenTelemetry สำหรับ .NET) ร่วมกับ ILogger และ Domain Probe pattern เพื่อไม่ให้ code domain ปนกับ plumbing:
// DomainProbe.cs — ห่อหุ้มรายละเอียดการ instrument ไว้เบื้องหลัง API ที่สื่อความหมายทางธุรกิจpublic sealed class OrderProbe{ private static readonly ActivitySource ActivitySource = new("Store.Orders"); private readonly ILogger<OrderProbe> _logger; private readonly Counter<long> _discountAppliedCounter;
public OrderProbe(ILogger<OrderProbe> logger, Meter meter) { _logger = logger; _discountAppliedCounter = meter.CreateCounter<long>("orders.discount_applied"); }
// ชื่อ method สื่อความหมายทางธุรกิจ ไม่ใช่ "LogInfo" หรือ "TrackEvent" ทั่วไป public void DiscountApplied(string orderId, string couponCode, decimal amount) { using var activity = ActivitySource.StartActivity("Order.DiscountApplied"); activity?.SetTag("order.id", orderId); activity?.SetTag("coupon.code", couponCode);
_discountAppliedCounter.Add(1, new KeyValuePair<string, object?>("coupon", couponCode));
_logger.LogInformation( "Applied discount {Amount} to order {OrderId} using coupon {Coupon}", amount, orderId, couponCode); }}
// OrderService.cs — domain logic เรียก probe แทนการยุ่งกับ logger/tracer โดยตรงpublic class OrderService{ private readonly OrderProbe _probe;
public OrderService(OrderProbe probe) => _probe = probe;
public void ApplyCoupon(Order order, string couponCode) { var discount = order.CalculateDiscount(couponCode); order.Total -= discount;
// domain logic อ่านง่าย ไม่มี noise ของ instrumentation ปนอยู่ _probe.DiscountApplied(order.Id, couponCode, discount); }}การตั้งค่าฝั่ง host เพื่อ export traces/metrics ผ่าน OpenTelemetry ไปยัง OTLP collector (เช่น Jaeger หรือ Grafana Tempo):
builder.Services.AddOpenTelemetry() .ConfigureResource(r => r.AddService("Store.Orders")) .WithTracing(tracing => tracing .AddSource("Store.Orders") // custom ActivitySource ของเรา .AddAspNetCoreInstrumentation() // trace อัตโนมัติของ incoming HTTP request .AddHttpClientInstrumentation() // trace อัตโนมัติของ outgoing call .AddOtlpExporter()) .WithMetrics(metrics => metrics .AddMeter("Store.Orders") .AddAspNetCoreInstrumentation() .AddOtlpExporter());แผนภาพต่อไปนี้แสดงว่า request หนึ่งรายการก่อให้เกิด telemetry ทั้งสามชนิดอย่างไร และถูกเชื่อมโยงกันด้วย correlation ID เดียวกันก่อนไหลไปยัง backend สำหรับ visualize:
flowchart LR
Request[Incoming Request] --> App[Application Code]
App --> Logs[Structured Logs]
App --> Metrics[Metrics Counters]
App --> Traces[Trace Spans]
Logs --> Correlate[Correlation via trace id]
Metrics --> Correlate
Traces --> Correlate
Correlate --> Backend[Observability Backend]
Backend --> Dashboard[Dashboards and Alerts]
ประโยชน์และข้อควรระวัง
หัวข้อที่มีชื่อว่า “ประโยชน์และข้อควรระวัง”ประโยชน์
- ลดเวลาในการหาสาเหตุปัญหา (MTTR) เพราะวิศวกรตั้งคำถามใหม่กับระบบได้ทันทีโดยไม่ต้อง deploy code เก็บข้อมูลเพิ่ม
- เห็นภาพรวม end-to-end ของระบบแบบกระจาย ซึ่งเป็นสิ่งที่การดู log ทีละเครื่องทำไม่ได้
- เมื่อทำแบบ domain-oriented (Domain Probe) จะได้ metric ที่สะท้อนเป้าหมายทางธุรกิจจริง เช่น cart abandonment rate ไม่ใช่แค่ CPU/memory ที่เป็น technical metric ทั่วไป
- เป็นรากฐานให้ SRE ตั้ง SLO/error budget และทำ incident response ได้อย่างมีข้อมูลรองรับ
ข้อควรระวัง
- Over-instrumentation ทำให้เกิด noise ล้นระบบ (log/metric cardinality สูงเกินไป) ซึ่งเพิ่มต้นทุนเก็บข้อมูลและทำให้หาสัญญาณจริงยากขึ้น ควร instrument อย่างมีเป้าหมาย ไม่ใช่ใส่ทุกจุด
- ถ้าไม่มี correlation ID เชื่อม logs/metrics/traces เข้าด้วยกัน การมีข้อมูลทั้งสามชนิดแยกกันก็ยังไม่ใช่ observability ที่แท้จริง
- การ instrument แบบเรียก logger/tracer ตรง ๆ ใน code domain ทำให้ code อ่านยากและทดสอบยาก — ควรพิจารณาแยกผ่าน pattern อย่าง Domain Probe
- Telemetry data มักมีข้อมูลอ่อนไหว (PII) ปนอยู่โดยไม่ตั้งใจ ต้องระวังเรื่อง data governance และ redaction ก่อนส่งออกไปยัง backend ภายนอก
- เครื่องมือ observability มีต้นทุนทั้งด้าน license/SaaS และ storage สำหรับ high-cardinality metrics/traces ควรวางแผน retention policy ตั้งแต่ต้น
ที่เกี่ยวข้อง
หัวข้อที่มีชื่อว่า “ที่เกี่ยวข้อง”แหล่งอ้างอิง
หัวข้อที่มีชื่อว่า “แหล่งอ้างอิง”- ที่มา · deviq.com/practices/observability
- Observability (software) — Wikipedia
- Domain-Oriented Observability — Pete Hodgson (martinfowler.com)
- Add distributed tracing instrumentation — .NET | Microsoft Learn
- The 3 pillars of observability: Logs, metrics and traces | TechTarget
- Getting started with traces — ASP.NET Core | OpenTelemetry