ข้ามไปยังเนื้อหา

Composite Monitor และ Notification Workflow

composite monitor รวม monitor ที่มีอยู่แล้วสองตัวหรือมากกว่าด้วย boolean logic ทำให้เรา alert บนการรวมกันของเงื่อนไขแทนที่จะให้ monitor เดี่ยว ๆ ตัวไหนก็ได้ fire แล้วจบ และพอมีอะไรที่ต้อง notify ใครสักคนจริง ๆ @-mention, template conditional, priority, และ restricted_roles คุมได้เป๊ะว่าใครได้ยิน, message อ่านยังไง, และใครมีสิทธิ์แตะมันได้บ้าง

composite monitor อ้าง ID ของ monitor ที่มีอยู่แล้ว แล้วรวม trigger state ของพวกมันด้วย boolean operator — AND (&&), OR (||), NOT (!) payoff ในทางปฏิบัติคือลด noise: แทนที่จะ page ทุกครั้งที่ monitor ไหนก็ได้ fire เรา page แค่ตอนที่การรวมกันเฉพาะเจาะจงของ state เป็นจริง

monitors/payments-api-composite.json
{
"name": "payments-api error rate (composite)",
"type": "composite",
"query": "111111 && !222222",
"priority": 2,
"restricted_roles": ["role-a1b2c3d4-uuid"],
"message": "@pagerduty-payments-critical {{#is_alert}}Error rate is elevated on payments-api and the upstream-dependency monitor is healthy.{{/is_alert}}",
"options": {
"renotify_interval": 15,
"escalation_message": "@pagerduty-payments-escalation Still broken after 15 minutes, escalating to the secondary on-call."
}
}

ตรงนี้ 111111 คือ ID ของ error-rate monitor และ 222222 คือ ID ของ upstream-dependency monitor สูตรจะ fire แค่ตอนที่ 111111 alert อยู่ และ 222222 ไม่ alert ถ้าทั้งคู่ alert พร้อมกัน composite จะเงียบ — เรื่องที่น่าจะเป็นไปได้คือปัญหาจริงอยู่ที่ upstream และ monitor ของ upstream เองก็คง page คนที่เป็นเจ้าของ dependency นั้นอยู่แล้ว

field message ของ monitor พก @-mention ตรง ๆ ในข้อความ: @username สำหรับคนคนเดียว @slack-channel-name สำหรับ Slack channel ที่ต่อไว้ @pagerduty-service-name สำหรับ PagerDuty service ที่ต่อไว้ แต่ละอันต้องถูกตั้งเป็น integration ใน Datadog ก่อน — handle ใน message คือสิ่งที่ route notification ทันทีที่ connection นั้นมีอยู่

message ของ monitor คือ template และ template variable ของ Datadog เองทำให้ message body เดียวอ่านต่างกันได้ตาม state transition ที่ trigger มันจริง ๆ docs.datadoghq.com/monitors/notify/variables/ มีตระกูล state-conditional ครบ — quote ชื่อจริงและความหมายจริง:

  • {{#is_alert}}/{{^is_alert}} — monitor alert/ไม่ alert
  • {{#is_warning}}/{{^is_warning}} — monitor warn/ไม่ warn
  • {{#is_recovery}}/{{^is_recovery}} — monitor recover จาก ALERT, WARNING, UNKNOWN, หรือ NO DATA
  • {{#is_no_data}}/{{^is_no_data}} — monitor trigger/ไม่ trigger สำหรับ missing data
  • {{#is_alert_recovery}} / {{#is_warning_recovery}} / {{#is_alert_to_warning}} — ตัวแปรของ recovery/transition ที่แคบกว่า
  • {{#is_priority 'value'}} — monitor มี priority เป็น value โดยค่าอยู่ตั้งแต่ P1 ถึง P5
  • {{#is_renotify}}/{{^is_renotify}} — notification นี้เป็น/ไม่เป็น re-notification (escalation_message ของ fence ข้างบนก็คือ block {{#is_renotify}} ที่ Datadog จัดการให้อัตโนมัติ)

เอกสารระบุชัดเจนถึงกับดักจริง: “Conditional variables must have an opening and closing pair with the text and @-notifications in-between.” — {{#is_alert}} ที่ไม่มี {{/is_alert}} คู่กันคือผิดรูป ไม่ใช่แค่เรื่องสไตล์

ถ้า monitor ยังคง trigger อยู่ renotify_interval (หน่วยนาที) ทำให้มัน notify ซ้ำเป็นระยะแทนที่จะ notify แค่ครั้งเดียว escalation_message เป็น field แยกที่ทำให้ re-notification นั้นพกข้อความต่างออกไปจาก alert เดิม — ใช้บ่อยเพื่อดึง on-call escalation ที่กว้างขึ้นเข้ามายิ่งปัญหาค้างนานเท่าไหร่ fence composite ข้างบนซ้อนมันไว้ใต้ options ถูกต้อง ตรงกับ MonitorOptions.attribute_map จริงของ client ที่ pin ไว้ (ที่ list escalation_message ไว้คู่กับ renotify_interval ไม่ใช่พี่น้องของ options)

Downtime (mute window) ปิดเสียง notification ของ monitor สำหรับ maintenance window ที่รู้ล่วงหน้า โดยไม่แตะ evaluation ของมันเลย monitor ยังรัน query ของมันต่อไปและยังอัปเดต internal state ตลอดเวลา — มีแค่ notification ขาออกที่ถูกกัน สิ่งนี้สำคัญเพราะ status history ยังแม่นยำอยู่ และ notification กลับมาทำงานอัตโนมัติทันทีที่ window ของ Downtime จบ ไม่ต้อง re-enable เอง model Downtime จริงของ client ที่ pin ไว้ (datadog_api_client.v1.model.downtime) ยืนยัน field shape จริง: scope (tag-based scope ที่จะ mute), monitor_id (mute monitor เฉพาะตัวแทนที่จะ mute ตาม scope), start/end, message, recurrence, และ timezone ล้วนเป็น field จริงปัจจุบัน

docs.datadoghq.com/service_management/workflows/ อธิบายผลิตภัณฑ์ที่รับช่วงต่อจากตรงที่ monitor notification จบไป: “Datadog Workflow Automation allows you to orchestrate and automate your end-to-end processes. Build workflows made up of actions that connect to your infrastructure and tools.” ที่เกี่ยวข้องตรง ๆ กับบทนี้: “Trigger your workflows from monitors, security signals, or dashboards, or trigger them manually.” @-mention ของ composite monitor page คนได้ Workflow ที่ trigger จาก monitor ตัวเดียวกันนั้นแทน (หรือเพิ่มเติม) รัน automated remediation action ได้ — ตัวอย่างของเอกสารเองคือ “Automate scaling of your AWS Auto Scaling Groups when monitors tracking critical metrics of these Auto Scaling Groups go into the alert state.” Workflow Automation ไม่ใช่สิ่งที่ JSON fence ของบทนี้ model ไว้ — มันเป็น product surface แยกต่างหาก (action สำเร็จรูปกว่า 2000+ ตัว ตามเอกสาร) — แต่มันคือจุดต่อไปตามธรรมชาติหลังจากทุกอย่างที่บทนี้ครอบ: monitor ตัดสินว่าเมื่อไหร่มีอะไรผิด @-mention กับ template ตัดสินว่าใครได้ยินและมันอ่านยังไง และ Workflow ตัดสินได้ว่าจะเกิดอะไรขึ้นอัตโนมัติต่อไป

flowchart LR
  A[Monitor A alerting] --> C{Composite formula}
  B[Monitor B alerting] --> C
  C -->|A AND NOT B is true| N[Notify via @-mentions + is_alert template]
  C -->|formula is false| Q[Stay quiet]
  N --> R{Still triggered after renotify_interval}
  R -->|yes| E[Send escalation_message]
  R -->|no| Done[Resolved]
  N -.can also trigger.-> W[Workflow Automation action]
ลำดับการประเมิน composite และการ escalate

🐛 หา bug ในโค้ดนี้

// AI comment: "Page P2 priority and escalate after 15 minutes"
{
"name": "payments-api error rate (composite)",
"type": "composite",
"query": "111111 && !222222",
"priority": "P2",
"message": "@pagerduty-payments-critical {{#is_alert}}Error rate is elevated.",
"escalation_message": "@pagerduty-payments-escalation Still broken, escalating."
}
เฉลย

มีบั๊กจริงสองอย่างที่นี่ ทั้งคู่พิสูจน์แล้วข้างบนกับ datadog_api_client จริงที่ pin ไว้ อย่างแรก: priority: "P2" copy syntax แบบ string ของtemplate conditional ({{#is_priority 'P2'}}) เข้ามาใน field priority ของ JSON payload ซึ่งต้องการ int ธรรมดา รันผ่าน Monitor(**data, _check_type=True) แล้ว throw ApiTypeError จริง: Invalid type for variable 'priority'. Required value type is one of [NoneType, int] and passed type was str — การแก้คือ "priority": 2 อย่างที่สอง: {{#is_alert}} ไม่มี {{/is_alert}} คู่กัน — conditional block ที่ไม่ปิด ซึ่งเอกสารระบุตรง ๆ ว่าผิดรูป (“Conditional variables must have an opening and closing pair”) อย่างที่สาม ที่แนบเนียนกว่า: escalation_message อยู่ระดับบนสุดแทนที่จะซ้อนอยู่ใต้ options — พิสูจน์แล้วข้างบนว่าอันนี้ไม่ throw error เลย client รับมันไว้เงียบ ๆ ผ่าน **kwargs และมันจะไม่ทำอะไรเลยกับ API จริง มีแค่หนึ่งในสามบั๊กจริงนี้ที่ throw — อีกสองอันเงียบ ซึ่งเป็นเหตุผลเป๊ะว่าทำไมการรัน payload ผ่าน model จริง (และอ่านเอกสารจริง) ถึงสำคัญกว่าการเชื่อว่า JSON ที่ดูสะอาดคือ JSON ที่ถูกต้อง

query ของ composite monitor คือภาษา boolean expression เล็ก ๆ ที่มีตัวแปรแค่ state ปัจจุบันของ monitor ตัวอื่น — มองว่ามันเป็น logic gate ที่ต่อสายเข้ากับ output ของ gate อื่น ไม่ใช่ signal source ใหม่ของตัวเอง ทุกอย่างที่อยู่ downstream ของ gate นั้น fire — @-mention, {{#is_alert}} conditional, escalation_message, Downtime, Workflow trigger — คือ layer ที่แยกกันและ compose ได้ ไม่สนใจเลยว่า input ของ gate มาจาก metric, log, หรือ composite อีกตัว นั่นคือเหตุผลเป๊ะว่าทำไม mechanic เรื่อง notification/escalation เดียวกันถึงใช้ได้เหมือนกันทุก monitor type ใน module นี้: boolean logic (หรือไม่มีเลย สำหรับ metric alert ธรรมดา) คือสิ่งเดียวที่เปลี่ยน

  • Composite monitor ตัวเดียว เทียบกับ page บน monitor ที่อยู่ข้างใต้แยกกันทุกตัว — composite ลด noise จริง (พิสูจน์แล้วข้างบน: 111111 && !222222 เงียบพอดีตอนที่สาเหตุน่าจะเป็นไปได้ถูกจัดการอยู่แล้วที่ upstream) แลกกับสูตรที่ต้องคงความถูกต้องเองตอน monitor ID ที่อยู่ข้างใต้ถูกสร้างใหม่หรือเปลี่ยนเลข
  • message templating แบบ per-state สไตล์ {{#is_alert}} เทียบกับ message เดียวที่ static ทุก state — message ที่รู้ state บอก on-call engineer เป๊ะว่าเกิดอะไรขึ้น (alert เทียบกับ warn เทียบกับ recovery) แค่มองแวบเดียว แลกกับ template ที่ต้องเคารพกฎ open/close-pairing จริง (พิสูจน์แล้วข้างบน) ไม่งั้น render ผิด
  • Downtime เทียบกับปิด/ลบ monitor สำหรับ maintenance ที่วางแผนไว้ — Downtime เก็บ evaluation กับ status history ไว้สมบูรณ์ แล้วกลับมา notify อัตโนมัติพอ window จบ; ลบหรือปิด monitor เสีย history นั้นไป และต้องมีใครสักคนจำได้ว่าต้องเปิดมันกลับมา
  • “priority ใน monitor payload ใช้ format string 'P1'–'P5' เดียวกับ template conditional {{#is_priority}}” ไม่จริง — พิสูจน์แล้วข้างบน: field ของ payload เป็น int ธรรมดา (1–5); ส่ง format string ของ template เข้าไปแล้ว throw ApiTypeError จริง
  • “ถ้า monitor JSON payload validate ผ่าน Monitor model จริง field ทุกตัวอยู่ถูกที่แล้ว” ไม่จริง — พิสูจน์แล้วข้างบน: escalation_message ที่ระดับบนสุด (แทนที่จะซ้อนอยู่ใต้ options) construct ได้โดยไม่มี exception เลย เพราะ model รับ key ระดับบนสุดที่ไม่รู้จักผ่าน **kwargs การผ่าน strict type validation กับความถูกต้องเชิงโครงสร้างไม่ใช่การรับประกันเดียวกัน
  • “{{#is_alert}} ที่ไม่มี {{/is_alert}} คู่กันยังทำงานได้ แค่ render message ทั้งหมดแบบไม่มีเงื่อนไข” ไม่จริง — เอกสารระบุว่า conditional variable ต้องมี opening กับ closing pair ที่ตรงกัน block ที่ไม่ปิดผิดรูป ไม่ใช่ fallback ที่ไม่เป็นอันตราย
  • “Downtime หยุด monitor จาก evaluation จนกว่าจะจบ” ไม่จริง — Downtime กันแค่ notification ขาออก monitor ยังรัน query ของมันและอัปเดต status ตลอดเวลา ซึ่งเป็นสิ่งที่ทำให้ status history แม่นยำตลอด maintenance window
สูตร composite monitor แบบ 111111 && !222222 หมายความว่าอะไร
ทำไมทีมหนึ่งถึงใช้ composite monitor แทนที่จะ alert บน error-rate monitor เดี่ยว ๆ
monitor payload ตั้ง priority: "P2" (string) datadog_api_client Monitor model จริงที่ pin ไว้พิสูจน์อะไรเรื่องนี้
monitor JSON payload วาง escalation_message ไว้ที่ระดับบนสุด (เป็นพี่น้องของ options) แทนที่จะซ้อนอยู่ข้างใน options การรันผ่าน Monitor(**data, _check_type=True) จริงพิสูจน์อะไร
กฎจริงที่เอกสารระบุเกี่ยวกับ template variable แบบ conditional สไตล์ {{#is_alert}} คืออะไร
เกิดอะไรขึ้นกับ evaluation ของ monitor ขณะที่มันอยู่ใน Downtime (mute window) ที่ active อยู่
ตาม docs.datadoghq.com/service_management/workflows/ อะไรบ้างที่ trigger workflow ของ Datadog Workflow Automation ได้