ทำไมต้อง Observability & แบบจำลองความคิด
หกคอร์สที่ผ่านมา (#5–#10 และโดยเฉพาะ #8) คุณสร้าง platform Order ของจริงขึ้นมาทั้งระบบ — 4 bounded context ที่คุยกันข้าม RabbitMQ ผ่าน transactional outbox: Ordering (core), Kitchen กับ Delivery (supporting, และ Delivery ถูกแยกออกไปเป็น service เดี่ยว), Payment (generic ที่คุยกับ gateway ภายนอกผ่าน ACL) code ทำงานถูกต้อง ออเดอร์ไหลจาก confirm ไป kitchen ticket ไป delivery assignment ครบทุกขั้น
แต่ลองนึกภาพตอนตีสามที่คุณเป็นคน on-call แล้วมีคนบอกว่า “ออเดอร์ #4821 ค้าง” คุณเปิด log ของ Kitchen เจอ ticket ที่ไม่เคยถูกปิด เปิด log ของ Payment เจอบรรทัดเดียวที่บอกว่า charge สำเร็จ — แต่สองอย่างนี้เป็นความลึกลับสองก้อนที่ไม่โยงกัน คุณไม่มีทางรู้เลยว่ามันเป็นออเดอร์เดียวกันไหม, ออเดอร์นั้นเดินทางผ่าน RabbitMQ ไปถึงไหนแล้ว, หรือมันหยุดตรงไหน นี่คือประเด็นของทั้งคอร์ส: คุณสร้าง Order platform 4 context ที่คุยกันข้าม RabbitMQ มา 6 คอร์ส — แต่ตอนนี้คุณ “มองไม่เห็น” ว่าออเดอร์เดินทางผ่านมันยังไง นี่คือระบบกระจายที่มืดสนิท คอร์ส #19 คือชั้น OPERATE ที่จะเปิดไฟให้มัน
คอร์สนี้ instrument platform Order ตัวเดิมที่ #8 สร้างไว้ (Ordering/Kitchen/Delivery/Payment บน WolverineFx outbox + RabbitMQ) — repo kaen-food-ordering (กำลังจัดทำ) #19 ไม่เพิ่ม bounded context หรือ business logic ใหม่ แต่ห่อ ชั้นสังเกตการณ์ คร่อมมัน บทนี้เป็นบทวางกรอบความคิด — ยัง ไม่มี code รันได้ code instrument ของจริงเริ่มที่บท2 (ตั้ง stack แล้วได้ trace แรก) บทนี้ตั้ง precedent ของ honesty spine กับ 🔗 callout อ้างอิงต้นทางไว้ให้ทุกบทหลังจากนี้เดินตาม
Observability ไม่ใช่ monitoring — และความต่างนี้คือหัวใจ
หัวข้อที่มีชื่อว่า “Observability ไม่ใช่ monitoring — และความต่างนี้คือหัวใจ”ObservabilityObservabilityความสามารถเข้าใจสถานะภายในของระบบจากสัญญาณที่มันปล่อยออกมา (telemetry) โดยไม่ต้องรู้โครงสร้างภายในล่วงหน้า และตอบ 'unknown unknowns' ได้Process คือความสามารถเข้าใจสถานะภายในของระบบจากสัญญาณที่มันปล่อยออกมา (TelemetryTelemetryข้อมูลสัญญาณ (traces/metrics/logs) ที่ app ปล่อยออกมาเพื่อให้สังเกตพฤติกรรมของระบบได้Process) โดย ไม่ต้อง รู้โครงสร้างภายในล่วงหน้า จุดที่คนสับสนกันมากที่สุดคือคิดว่ามันเท่ากับ monitoring — มันไม่ใช่
Monitoring ตอบคำถามที่คุณ รู้ล่วงหน้าว่าจะถาม — “known unknowns” คุณสร้าง dashboard ไว้ก่อนล่วงหน้าเพราะรู้อยู่แล้วว่าอยากดู CPU, จำนวน request ต่อวินาที, error rate เมื่อ graph แดง คุณก็รู้ พวกนี้คือคำถามที่คุณคาดไว้แล้ว
Observability ตอบคำถามที่คุณ ไม่รู้ว่าต้องถาม — “unknown unknowns” ตำราของ OpenTelemetry นิยามไว้ตรงๆ ว่าระบบจะ observable ได้เมื่อคุณ (S2):
“ask questions about that system without knowing its inner workings.”
ตอนตีสามกับออเดอร์ #4821 คุณไม่มี dashboard ที่ชื่อ “ทำไมออเดอร์นี้ค้าง” ไว้ก่อน — เพราะไม่มีใครคาดเหตุนี้ได้ observability คือความสามารถ ตั้งคำถามใหม่ กับข้อมูลที่ระบบปล่อยไว้แล้ว โดยไม่ต้องไป deploy code ใหม่ก่อน นี่คือเส้นความซื่อสัตย์เส้นแรกของคอร์ส: อย่าขาย dashboard ว่ามันคือ observability — dashboard คือ monitoring ที่ดี แต่มันตอบได้แค่คำถามที่คุณเดาไว้ล่วงหน้าเท่านั้น
สามสัญญาณ — และความจริงที่ว่า OpenTelemetry ไม่ใช่ backend
หัวข้อที่มีชื่อว่า “สามสัญญาณ — และความจริงที่ว่า OpenTelemetry ไม่ใช่ backend”telemetry ที่เรากำลังพูดถึงมีสามชนิด และ OpenTelemetryOpenTelemetryมาตรฐานเปิดที่เป็นกลางต่อ vendor สำหรับสร้างและส่ง telemetry; ตัวมันเองไม่ใช่ backend — storage/UI ปล่อยให้เครื่องมืออื่นArchitecture (OTel) เรียกมันว่า สามสัญญาณ (signals):
- Traces — เส้นทางของ หนึ่ง request ผ่านทั้งระบบ (ออเดอร์ #4821 เดินผ่าน context ไหนบ้าง เรียงตามเวลา)
- Metrics — ตัวเลขสรุปรวม (ออเดอร์ต่อวินาที, p95 ของ checkout latency, ความลึกของคิว)
- Logs — บันทึกเหตุการณ์เป็นข้อความ ณ จุดเวลาหนึ่ง (มีโครงสร้างหรือไม่ก็ได้)
จุดที่คนเข้าใจผิดบ่อยที่สุดคือคิดว่า OpenTelemetry เป็น “เครื่องมือ observability” ที่เก็บและแสดงข้อมูลให้ มันไม่ใช่ เอกสารทางการของ OTel พูดชัดว่ามันไม่ใช่ backend — มันหยุดที่การ สร้างและส่ง telemetry เท่านั้น (S1):
“The backend (storage) and the frontend (visualization) of telemetry data are intentionally left to other tools.”
นี่คือเส้นความซื่อสัตย์เส้นที่สอง และเป็น mental model ที่ต้องปักตั้งแต่บทแรกเพราะทุกบทลงมือจะหมุนรอบมัน:
“สิ่งที่คุณ instrument คือ OpenTelemetry — มาตรฐานเปิดที่เป็นกลางต่อ vendor. ClickStack เป็นแค่ ‘ปลายทาง’ (sink) ที่เราเลือกใช้ให้จับต้องได้ ไม่ใช่ตัวคอร์ส.”
พูดให้จำง่าย: OTel คือ สายไฟ (portable) — ClickStackClickStackstack observability โอเพนซอร์สของ ClickHouse: HyperDX (UI) + ClickHouse (columnar store) + OTel Collector distro; เป็น 'ปลายทาง' ที่สลับได้Architecture คือ ปลั๊ก (สลับได้) code C# ที่คุณเขียนจะปล่อย OTLP ออกมา ส่วนปลายทางเป็นแค่ env var หนึ่งตัว — วันไหนอยากสลับ ClickStack ไปเป็น Jaeger, Grafana, Datadog หรือ Honeycomb code instrument ใน app ของคุณ ไม่ต้องแก้แม้แต่บรรทัดเดียว เราเลือก ClickStack (ClickHouse + HyperDX) เพราะมันเป็น OSS all-in-one รันบน Docker ได้ ทำให้ตัวอย่างจับต้องได้ — แต่คอร์สนี้สอน OpenTelemetry ไม่ได้สอน ClickStack
จาก ‘สามเสา’ สู่ Observability 2.0 — ดีเบตที่ยังไม่จบ (และเราจะไม่ตัดสินให้)
หัวข้อที่มีชื่อว่า “จาก ‘สามเสา’ สู่ Observability 2.0 — ดีเบตที่ยังไม่จบ (และเราจะไม่ตัดสินให้)”คุณจะเจอคำว่า Three PillarsThree Pillarsกรอบเดิม (Obs 1.0) ที่มอง metrics/logs/traces เป็นสามคลังแยกกัน — ถูกวิจารณ์ว่าทำให้ต้องเก็บข้อมูลซ้ำหลายที่Process (สามเสา) ทุกที่ในวงการ observability — กรอบที่มอง metrics, logs, traces เป็น สามคลังแยกกัน สามผลิตภัณฑ์ สามที่เก็บ นี่คือคำศัพท์มาตรฐานของอุตสาหกรรม (บางคนเรียกยุคนี้ว่า Obs 1.0) และคุณควรรู้จักมันเพราะทุกคนพูดถึงมัน
แต่มีเสียงวิจารณ์ที่ดังและตรงประเด็น — นำโดย Charity Majors (Honeycomb) ที่ต้องฟังอย่างซื่อสัตย์:
- Majors เถียงว่ากรอบสามเสาฝังรากลึกส่วนหนึ่งเพราะเหตุผลเชิงธุรกิจ ไม่ใช่เชิงเทคนิค — “vendors had metrics products, logging products, and tracing products to sell” (S45/S46)
- และมันทำให้คุณต้องจ่ายเงินเพื่อ “store telemetry five different ways, in five different places, for every single request” — ข้อมูลชุดเดียวถูกเก็บซ้ำห้าที่ (S47)
ทางออกที่ฝ่ายนี้เสนอคือ Observability 2.0Observability 2.0แนวคิด 'แหล่งความจริงเดียว' เก็บเป็น wide structured event แล้วอนุมาน metrics/logs/traces ตอนอ่าน (frame ที่ vendor คิด อยู่ในดีเบตที่ยังไม่จบ)Process: แหล่งความจริงเดียว — เก็บทุกอย่างเป็น Wide EventWide Eventเหตุการณ์ structured ที่มี attribute จำนวนมาก (คือสแปนนั่นเอง) เป็นหน่วยข้อมูลหลักของ Obs 2.0Architecture (structured event ที่มี attribute กว้างมากๆ คือ span นั่นเอง) แล้ว อนุมาน metrics/logs/traces ออกมาตอน อ่าน ไม่ใช่เก็บแยกไว้ก่อน (S46)
แล้ว ClickStack อยู่ตรงไหน? พูดตามตรงโดยไม่โม้: ClickStack เก็บทุกสัญญาณเป็นแถว columnar กว้างๆ ใน ClickHouse แล้วให้คุณ pivot จาก log ไป trace ไป metric เหนือ store เดียวกันได้ — เชิงสถาปัตยกรรมมันจึงอยู่ในค่าย wide-event/single-store แต่ ระวังการโม้: “Obs 2.0” เป็น frame ที่ vendor (Honeycomb) เป็นคนตั้งชื่อ อยู่ในดีเบตที่ยัง ไม่จบ; ClickStack ก็ไม่ได้ถูกสร้างมาตาม spec ของ Majors เป๊ะๆ; และตัว OTel เองก็ยังจัดระเบียบรอบ สามสัญญาณ บนสาย ดังนั้นเส้นของคอร์สนี้คือ:
OTel ให้ สามสัญญาณ วิ่งอยู่บนสาย; ClickStack ให้คุณ เก็บ + query มันเป็น dataset เดียวที่กว้างและ สัมพันธ์กัน (correlated) ดีเบตนี้เป็นของจริง และการ correlate คือผลตอบแทนที่จับต้องได้ — แต่เราจะ ไม่บอกคุณว่าฝ่ายไหนชนะ
เส้นเลือดความซื่อสัตย์สี่เส้นของคอร์สนี้
หัวข้อที่มีชื่อว่า “เส้นเลือดความซื่อสัตย์สี่เส้นของคอร์สนี้”ก่อนลง code สักบรรทัด ปักความจริงสี่ข้อนี้ไว้ — ทุกบทลงมือจะย้ำข้อที่เกี่ยวข้องซ้ำ เหมือนที่บทนี้ตั้ง precedent ไว้:
- (A) OTel เป็นกลางต่อ vendor; ClickStack เป็นแค่ sink หนึ่งที่สลับได้ — สายไฟ vs ปลั๊ก code ไม่ผูกกับปลายทาง
- (B) Observability ≠ monitoring — monitoring ตอบ known-unknowns (dashboard ที่สร้างไว้ก่อน), observability ตอบ unknown-unknowns
- (C) instrumentation มีต้นทุนจริง; filter/dashboard ลด MTTR แต่ ไม่กำจัด เหตุ — cardinality ที่ระเบิดคิดเงินแบบทวีคูณ, storage โตตามปริมาณ, และ sampling เป็น “เครื่องมือหยาบ” ที่ซ่อนข้อมูล wide-event store ลด ต้นทุนนี้ได้ แต่ ไม่ลบ มันทิ้ง
- (D) คุณ debug สิ่งที่คุณไม่ได้ instrument ไม่ได้ — app ต้องปล่อยสัญญาณออกมาก่อน คุณถึงจะตั้งคำถามกับมันได้ auto-instrumentation (HTTP/DB span ที่ได้ฟรีจาก framework) เป็นแค่ พื้น ไม่ใช่ เพดาน — span/attribute ที่มีความหมายเชิง domain (
order.id, ผลลัพธ์การจ่ายเงิน) ต้องเขียนเอง
คอร์สนี้จับ สามสัญญาณฝั่ง backend เท่านั้น: traces, metrics, logs ของ platform .NET จริงๆ แล้ว ClickStack มีสัญญาณที่สี่คือ session replay — แต่มันเป็นสัญญาณ ฝั่ง browser (เก็บผ่าน SDK ในเว็บหน้าบ้าน) platform Order ของเราเป็น backend service ล้วน จึง ไม่แตะ session replay เลย (S50) พูดไว้ตรงนี้ชัดๆ เพื่อไม่ให้ใครอนุมานว่าคอร์สครอบคลุมมัน
คอร์สนี้ ‘สังเกต’ platform ที่ #8 สร้าง — ไม่ได้สร้างใหม่ (anti-overlap)
หัวข้อที่มีชื่อว่า “คอร์สนี้ ‘สังเกต’ platform ที่ #8 สร้าง — ไม่ได้สร้างใหม่ (anti-overlap)”ขีดเส้นให้ชัดว่าคอร์สนี้ ไม่ใช่ บทไหนที่คุณเคยเรียน: #19 สังเกต platform ที่ #8 สร้างไว้ — มันไม่เคยสอน Wolverine/RabbitMQ/outbox mechanics ซ้ำ (นั่นคือของ #8 เราแค่ instrument มัน) และไม่เคยสอน resilience/retry/idempotency ซ้ำ (นั่นคือของ #17 ซึ่งเป็น resilience ไม่ใช่ observability) เราจะ reuse idempotent guard ของ #17 เป็น บริบท ของ trace เท่านั้น ไม่ derive มันใหม่ และเมื่อพูดถึง RED/SLO/error budget ในบทหลัง เราจะ frame มันเป็น operations observability ไม่ใช่ resilience
แผนภาพ: จากระบบมืดสนิท สู่ระบบที่ติดไฟด้วย telemetry
หัวข้อที่มีชื่อว่า “แผนภาพ: จากระบบมืดสนิท สู่ระบบที่ติดไฟด้วย telemetry”flowchart LR
subgraph DARK["ตอนนี้: ระบบกระจายที่มืดสนิท"]
O1["Ordering<br/>log บอก 'confirmed' แล้วเงียบ"]
K1["Kitchen<br/>ticket ค้าง — ทำไม?"]
D1["Delivery (service เดี่ยว)<br/>ออเดอร์มาถึงไหม?"]
P1["Payment<br/>log บรรทัดเดียว ไม่โยงกับใคร"]
O1 -. "RabbitMQ<br/>มองไม่เห็นการเดินทาง" .-> K1
O1 -. "?" .-> D1
O1 -. "?" .-> P1
end
subgraph LIT["หลัง instrument: telemetry ที่สัมพันธ์กัน (correlated)"]
O2["Ordering<br/>span: place-order"]
K2["Kitchen<br/>span: open-ticket"]
D2["Delivery<br/>span: assign"]
P2["Payment<br/>span: charge (HttpClient)"]
O2 -->|"traceparent ข้าม RabbitMQ<br/>trace เดียวกัน"| K2
O2 -->|"trace เดียวกัน"| D2
O2 -->|"trace เดียวกัน"| P2
end
DARK ==>|"instrument ด้วย OpenTelemetry"| LIT
classDef dark fill:#1e293b,stroke:#0f172a,color:#94a3b8;
classDef lit fill:#0e7490,stroke:#155e75,color:#f0fdff;
class O1,K1,D1,P1 dark;
class O2,K2,D2,P2 lit;
คำบรรยายภาพ: ก่อน instrument (ซ้าย) แต่ละ context ปล่อย log ของตัวเองแยกกัน — ออเดอร์เดียวกลายเป็นความลึกลับสี่ก้อนที่ไม่โยงกัน และการเดินทางข้าม RabbitMQ มองไม่เห็นเลย หลัง instrument ด้วย OpenTelemetry (ขวา) ทุก context ปล่อย span ที่ share trace เดียวกัน โดย trace context ถูกส่งต่อผ่าน RabbitMQ — ออเดอร์หนึ่งใบจึงกลายเป็น เส้นทางเดียว ที่ไล่ดูได้ตั้งแต่ต้นจนจบ
สรุปก่อนไปต่อ
หัวข้อที่มีชื่อว่า “สรุปก่อนไปต่อ”หกคอร์สก่อนหน้าให้คุณ สร้าง platform Order ที่ทำงานถูกต้อง — แต่ตอนรันจริงมันมืดสนิท บทนี้วางแบบจำลองความคิดทั้งหมดไว้ก่อนลง code: observability ตอบ unknown-unknowns ต่างจาก monitoring ที่ตอบแค่คำถามที่เดาไว้; OpenTelemetry คือ สายไฟ ที่เป็นกลางต่อ vendor และ ไม่ใช่ backend ส่วน ClickStack คือ ปลั๊ก ที่สลับได้; ดีเบต three-pillars vs Observability 2.0 เป็นของจริงและเราจะไม่ตัดสินให้ฝ่ายใดชนะ; และเส้นความซื่อสัตย์สี่เส้น (A–D) — โดยเฉพาะข้อ (D) ที่ว่า คุณ debug สิ่งที่ไม่ได้ instrument ไม่ได้ — จะกำกับทุกบทที่เหลือ คอร์สนี้จับสามสัญญาณฝั่ง backend เท่านั้น session replay อยู่นอกขอบเขต
บทหน้าเลิกพูดทฤษฎี — เราจะรัน ClickStack บน Docker, wire app Ordering เข้า OTel, แล้วได้ trace แรก end-to-end เข้า HyperDX รวมถึง DB span จาก EF Core มาเปิดไฟให้ระบบมืดก้อนนี้กัน
บทนี้อิงต้นทางที่ลงวันที่กำกับ อ่านต่อได้โดยตรง:
- OpenTelemetry — What is OpenTelemetry? (เอกสารทางการ, เข้าถึง 2026-07-22) — OTel เป็นกลางต่อ vendor และ ไม่ใช่ backend: “The backend (storage) and the frontend (visualization) of telemetry data are intentionally left to other tools”
- OpenTelemetry — Observability Primer (เอกสารทางการ, เข้าถึง 2026-07-22) — observability = ตั้งคำถามกับระบบได้ “without knowing its inner workings” (unknown-unknowns) และ app ต้องปล่อยสัญญาณก่อน
- Charity Majors — “The pillar is a lie” (2025-10-30) — คำวิจารณ์กรอบสามเสา: pillar = การตลาด, signal = เทคนิค; เก็บครั้งเดียว
- Honeycomb — “Time to version observability? Signs point to yes” (2024-12-02) — Obs 1.0 vs 2.0, wide events, อนุมาน metrics/logs/traces ตอนอ่าน; “vendors had metrics products, logging products, and tracing products to sell”
- Honeycomb — “The cost crisis in observability tooling” (2024-12-18) — ต้นทุนของการเก็บซ้ำห้าที่: “store telemetry five different ways, in five different places, for every single request”; sampling เป็นเครื่องมือหยาบ
- ClickStack — Session replay (เข้าถึง 2026-07-22) — สัญญาณที่สี่ ฝั่ง browser (SDK
@hyperdx/browser) — อยู่นอกขอบเขต ของคอร์ส backend นี้
เช็กความเข้าใจ — บทที่ 1
ข้อ 1 / 3ความต่างที่เป็นหัวใจระหว่าง monitoring กับ observability คืออะไร?