Continuous Profiler และ Error Tracking
ไอเดียหลักในหนึ่งประโยค
หัวข้อที่มีชื่อว่า “ไอเดียหลักในหนึ่งประโยค”tracing บอกคุณว่าตรงไหนที่ช้าหรือ fail — service ไหน, span ไหน — ส่วน Continuous Profiler กับ Error Tracking บอกคุณว่าทำไม ลงลึกถึงฟังก์ชันที่กิน CPU หรือ root cause ที่ถูก dedup มาจากกอง stack trace ที่ซ้ำกัน
Continuous Profiler: code-level visibility ที่ always-on
หัวข้อที่มีชื่อว่า “Continuous Profiler: code-level visibility ที่ always-on”Continuous Profiler รันตลอดเวลาบน production ด้วย overhead ต่ำ เก็บ CPU time, wall-time และ allocation ระดับโค้ด — ฟังก์ชันและ call stack แต่ละตัว ไม่ใช่แค่ aggregate ระดับ service เพราะ always-on แทนที่จะเป็นอะไรที่คุณเปิดทีหลังตอน investigate incident ข้อมูลจึงพร้อมอยู่แล้วตั้งแต่ก่อนคุณต้องการด้วยซ้ำ
profiler ผูก sample ของตัวเองกลับไปหา service, endpoint และแม้แต่ trace ที่เกิดขึ้นด้วย ความเชื่อมโยงนี้เองที่ทำให้ profiler มีประโยชน์ตอน debug request ที่ช้า — แทนที่จะเดาว่าส่วนไหนของ checkout-web ที่แพง คุณกระโดดจาก trace ที่ช้าตรงเข้าไปหา flame graph ว่าฟังก์ชันไหนกำลังรันอยู่และนานแค่ไหนระหว่าง request นั้น
# ddtrace's profiler starts alongside the tracer — no separate instrumentation neededfrom ddtrace.profiling import Profiler
prof = Profiler()prof.start()พอทั้ง tracer และ profiler รันพร้อมกัน span ที่ช้าใน trace หนึ่งจะพาคุณตรงไปที่ flame graph ระดับฟังก์ชันของช่วงเวลานั้นพอดี — tracing จำกัดให้เหลือ span ไหน profiler จำกัดให้เหลือ บรรทัดโค้ดไหน
Error Tracking: เปลี่ยน stack trace ที่ซ้ำกันให้เป็น issue เดียว
หัวข้อที่มีชื่อว่า “Error Tracking: เปลี่ยน stack trace ที่ซ้ำกันให้เป็น issue เดียว”Error Tracking เอา error event ที่มาจาก trace และ log แล้ว group กับ dedup error ที่คล้ายกันให้เป็น issue เดียวอัตโนมัติ แทนที่จะปล่อยให้คุณต้องมาสังเกตเองว่า NullPointerException ตัวเดิมเกิดขึ้นไปแล้ว 482 ครั้งตลอดหนึ่งสัปดาห์ของ trace แต่ละ issue มี lifecycle ที่คุณจัดการได้ชัดเจน — ปกติคือ new, triaged และ resolved — error ที่เกิดซ้ำ ๆ จึงกลายเป็นสิ่งเดียวที่ทีมของคุณ track จนปิดได้ แทนที่จะเป็น event หลายร้อยตัวที่ดูเหมือนไม่เกี่ยวกันเลย
{ "issue": { "status": "new", "occurrences": 482, "first_seen": "2026-07-01T10:03:00Z", "last_seen": "2026-07-08T09:12:00Z", "example_trace_ids": ["6141ee2f9a4d4b2e8f3c1a90", "9af23cd1b8e7f4a6c2d5e901"] }}สังเกต field example_trace_ids — Error Tracking เก็บ link กลับไปหา example trace จริงของ issue นั้นไว้ด้วย คุณจึงกระโดดจาก “issue นี้เกิดไปแล้ว 482 ครั้ง” ตรงเข้าไปหา occurrence จริงหนึ่งตัวเพื่อดู context ของ request รอบ ๆ ได้
จาก “ตรงไหน” ไปสู่ “ทำไม”
หัวข้อที่มีชื่อว่า “จาก “ตรงไหน” ไปสู่ “ทำไม””สองเครื่องมือนี้รวมกันแล้วปิดช่องว่างที่ tracing เพียงอย่างเดียวทิ้งไว้
- Tracing — service ไหนและ span ไหนที่ช้าหรือ fail
- Continuous Profiler — ฟังก์ชันไหนระดับโค้ดที่กิน CPU/wall-time/allocation ระหว่าง span ที่ช้านั้น
- Error Tracking — span ที่ fail นั้นอยู่ใน issue ที่ dedup แล้วอันไหน และ issue นั้นอยู่ที่จุดไหนใน lifecycle new/triaged/resolved
ไม่มีเครื่องมือไหนแทนที่ tracing ทั้งคู่เริ่มจาก trace หรือ span แล้วลงลึกไปอีกระดับกว่าที่ “service ไหน” จะพาไปถึงได้
flowchart LR Trace[Slow or failing trace] --> Where[Tracing: which service, which span] Where --> Profiler[Continuous Profiler: which function, CPU/wall-time/allocations] Where --> ErrorTracking[Error Tracking: deduplicated issue, new/triaged/resolved] Profiler --> WhySlow[Why it is slow] ErrorTracking --> WhyFailing[Why it is failing]