อาการล้าจากการแจ้งเตือนมีจริง: นักพัฒนาที่เก่งแก้มันอย่างไร

เมื่อการแจ้งเตือนทุกอันดูเร่งด่วนเท่ากัน ก็เลยไม่มีอะไรรู้สึกเร่งด่วน นี่คือวิธีจัดระบบมอนิเตอร์ใหม่ด้วยการแจ้งเตือนแบบแบ่งระดับ และเครื่องมือที่เข้ากับ Echobell ได้ดี

อัปเดตเมื่อ

สารบัญ

มันมีชื่อเรียกของมัน: อาการล้าจากการแจ้งเตือน (alert fatigue) คือสิ่งที่เกิดขึ้นเมื่อเครื่องมือมอนิเตอร์ของคุณส่งการแจ้งเตือนมามากจนสมองเริ่มกรองมันทิ้งเองโดยอัตโนมัติ แม้แต่อันที่สำคัญจริง ๆ

มันมักเริ่มจากเรื่องเล็ก ๆ คุณตั้งการแจ้งเตือนทางอีเมลสำหรับข้อผิดพลาด 5xx ทุกครั้ง จากนั้นก็ตั้งการแจ้งเตือนใน Slack สำหรับทุกบิลด์ที่ล้มเหลว แล้วก็มี Datadog เด้ง อีเมลจาก Sentry ข้อความจาก UptimeRobot ภายในเดือนเดียว มือถือคุณสั่นวันละ 50 ครั้งและไม่มีอะไรรู้สึกเร่งด่วนเลย ส่วนที่แย่จริง ๆ คืออะไร? พอมีอะไรพังขึ้นมาจริง ๆ คุณก็ฝึกตัวเองให้เพิกเฉยไปเรียบร้อยแล้ว

อาการล้าจากการแจ้งเตือนฆ่าเวลาตอบสนอง และเวลาตอบสนองที่ช้าก็ฆ่าผลิตภัณฑ์

ทำไมระบบมอนิเตอร์ส่วนใหญ่จึงสร้างสัญญาณรบกวนมากกว่าสัญญาณจริง

ปัญหาพื้นฐานคือเครื่องมือแจ้งเตือนส่วนใหญ่ปฏิบัติกับทุกอีเวนต์เหมือนกันหมด เทสต์ที่ล้มเหลวแบบไม่คงเส้นคงวา 10% ของเวลาทั้งหมด ได้รูปแบบการแจ้งเตือนเดียวกับ "API การชำระเงินคืนค่า 500 ให้ผู้ใช้ทุกคน" อันหนึ่งควรโทรปลุกคุณตอนตีสอง อีกอันน่าจะแค่โผล่ในสรุปประจำสัปดาห์ก็พอ

เมื่อทุกอย่างได้รับการปฏิบัติเหมือนกัน คนก็เริ่มเพิกเฉยกับทุกอย่าง

ทางแก้ไม่ใช่การลดจำนวนการแจ้งเตือน แต่คือการส่งที่ฉลาดขึ้น อีเวนต์เดียวกันที่ระดับความรุนแรงต่างกัน หรือที่ความถี่ต่างกัน ควรให้ความเร่งด่วนบนมือถือของคุณต่างกันด้วย

แนวทางสามระดับ

Echobell ให้โหมดการส่งการแจ้งเตือนสามแบบ และการใช้ทั้งสามแบบให้ดีคือหัวใจทั้งหมด:

  • ปกติ (Active): การแจ้งเตือนแบบพุชมาตรฐาน เหมาะกับอีเวนต์เชิงข้อมูลที่ไม่ต้องลงมือทำทันที
  • สำคัญตามเวลา: ทะลุโหมดโฟกัสของ iOS ได้ เหมาะกับเรื่องที่ต้องจัดการภายในหนึ่งถึงสองชั่วโมงข้างหน้า
  • โทรเข้า: ทำให้มือถือของคุณดังเหมือนสายเรียกเข้า สงวนไว้ให้เรื่องประเภท "แก้เดี๋ยวนี้ ไม่งั้นเกิดผลเสียจริง"

เป้าหมายคือรักษาระดับโทรเข้าไว้ให้อีเวนต์ที่การตอบสนองช้าแล้วมีผลกระทบจริง เช่น รายได้ที่หายไป ความล้มเหลวลูกโซ่ หรือข้อมูลผู้ใช้ที่เสี่ยง ส่วนที่เหลือให้ลดลงมาเป็นสำคัญตามเวลาหรือต่ำกว่านั้น

Sentry: เลิกถูกเรียกทุกครั้งที่มี exception ของ Python

Sentry คือตัวอย่างคลาสสิกของอาการล้าจากการแจ้งเตือน ค่าเริ่มต้นของมันคือส่งอีเมลหาคุณทุกครั้งที่มี issue ประเภทใหม่ ในโค้ดเบสที่มีความเคลื่อนไหวช่วงสัปดาห์ปกติ นั่นคือสายน้ำที่ไหลไม่หยุด

นี่คือการตั้งค่าที่ฉลาดกว่า:

  1. ใน Sentry ไปที่ Alerts → Create Alert → Issue Alert
  2. เพิ่มเงื่อนไข: The issue is seen more than 10 times in 1 hour
  3. เพิ่มการกระทำ: Send a notification via webhook → วาง URL ของช่อง Echobell ของคุณ
  4. ตั้งประเภทการแจ้งเตือนของช่องเป็น time-sensitive

สำหรับเส้นทางที่วิกฤตจริง ๆ เช่น exception ที่ไม่ถูกจัดการในโฟลว์การชำระเงิน การยืนยันตัวตนล้มเหลว หรือข้อมูลเสียหาย ให้สร้างการแจ้งเตือนแยกอีกอันที่มีเกณฑ์ต่ำกว่า และใช้ช่อง Echobell ระดับ calling ช่องนั้นจะดังเฉพาะเมื่อมีอะไรพังในเส้นทางเจาะจงนั้นเท่านั้น

ผลลัพธ์: issue ทั่วไปสะสมเงียบ ๆ อยู่ในแดชบอร์ด Sentry ส่วนปัญหาที่ทำให้โปรดักชันพังจะโทรเข้ามือถือคุณ

Prometheus และ AlertManager: จัดเส้นทางตามความรุนแรง

ถ้าคุณใช้ Prometheus อยู่ คุณก็มี AlertManager คอยจัดเส้นทางให้อยู่แล้ว คุณส่งการแจ้งเตือนตรงไปยัง Echobell ได้โดยเพิ่มมันเป็น webhook receiver

ในไฟล์ alertmanager.yml ของคุณ:

receivers:
  - name: echobell-critical
    webhook_configs:
      - url: https://hook.echobell.one/t/<channel-token>
        send_resolved: true

  - name: slack-warnings
    slack_configs:
      - api_url: YOUR_SLACK_WEBHOOK

route:
  group_by: ['alertname', 'job']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: slack-warnings
  routes:
    - match:
        severity: critical
      receiver: echobell-critical

ด้วยการตั้งค่านี้ การแจ้งเตือนที่มี severity: critical จะไปยัง Echobell และโทรเข้ามือถือคุณ ส่วนคำเตือนจะไป Slack ที่รอถึงเช้าได้ คุณไม่ต้องแก้กฎของ Prometheus แม้แต่ข้อเดียว แค่เพิ่มชั้นการจัดเส้นทางใน AlertManager เท่านั้น

ตั้งช่อง Echobell เองให้เป็น โทรเข้า เพราะถ้า AlertManager ติดป้ายว่า critical มันก็คู่ควรกับเสียงเรียกเข้าจริง ๆ

AWS CloudWatch: SNS → Lambda → Echobell

CloudWatch ไม่มีเอาต์พุตแบบ webhook ในตัว แต่คุณไปถึงจุดนั้นได้ในไม่กี่นาทีด้วย SNS และฟังก์ชัน Lambda เล็ก ๆ

  1. สร้าง SNS topic แล้วผูกเข้ากับ CloudWatch alarm ของคุณ
  2. สร้างฟังก์ชัน Lambda ที่ subscribe topic นั้น:
import json
import urllib.request

def lambda_handler(event, context):
    message = json.loads(event['Records'][0]['Sns']['Message'])
    alarm_state = message.get('NewStateValue', 'UNKNOWN')

    payload = {
        "title": f"AWS: {message['AlarmName']}",
        "body": message.get('NewStateReason', 'No details'),
        "notificationType": "calling" if alarm_state == "ALARM" else "active"
    }

    req = urllib.request.Request(
        'https://hook.echobell.one/t/<channel-token>',
        data=json.dumps(payload).encode(),
        headers={'Content-Type': 'application/json'},
        method='POST'
    )
    urllib.request.urlopen(req)

รูปแบบนี้ใช้ได้กับทุกบริการของ AWS ที่รองรับ SNS ทั้งอีเวนต์ของ RDS ความล้มเหลวของบริการ ECS การแจ้งเตือนเมื่อค่าใช้จ่ายถึงเกณฑ์ และการเปลี่ยนสถานะของ EC2 instance เพิ่ม Lambda หนึ่งตัว ต่อเข้ากับ SNS แล้วทุก CloudWatch alarm ก็กลายเป็นสายโทรเมื่อมันทำงานจริง

ทำให้การจัดเส้นทางการแจ้งเตือนเป็นการตัดสินใจของทีม

พลังที่แท้จริงของการแจ้งเตือนแบบแบ่งระดับคือการทำให้การตัดสินใจเรื่องเส้นทางชัดเจน ไม่ใช่แค่สิ่งที่คนคนหนึ่งเคยตั้งไว้ครั้งเดียวแล้วไม่มีใครหาเจอ

โครงสร้างที่ใช้ได้จริงสำหรับทีมวิศวกรรมเล็ก ๆ:

ช่องประเภทใครติดตาม
production-api-criticalโทรเข้าวิศวกรที่เข้าเวร on-call
production-api-warningsสำคัญตามเวลาทีมพัฒนาทั้งทีม
staging-allปกติทีมพัฒนา (ไม่บังคับ)
background-jobsปกติใครก็ได้ที่สนใจ

เมื่อรอบเวร on-call เปลี่ยน คนที่ออกเวรก็เลิกติดตามช่องวิกฤต แล้วคนที่เข้าเวรก็กดติดตาม เท่านี้ก็ส่งต่อเวรครบแล้ว ไม่ต้องมีไฟล์คอนฟิก ไม่ต้องมีหน้าจอผู้ดูแลระบบ

ช่องของ Echobell แชร์ผ่านลิงก์ได้ การกดติดตามจึงใช้เวลาราว 10 วินาทีต่อสมาชิกใหม่หนึ่งคน

บททดสอบสัญญาณต่อสัญญาณรบกวน

ก่อนเพิ่มการแจ้งเตือนใหม่ทุกครั้ง ให้ถามคำถามเดียว: ถ้ามันดังขึ้นตอนตีสามของวันศุกร์ ฉันจะทำอะไรกับมันจริง ๆ

  • "ตื่นขึ้นมาแก้เดี๋ยวนี้" → โทรเข้า
  • "จัดการเป็นเรื่องแรกตอนเช้า" → สำคัญตามเวลา หรือปกติ
  • "คงไม่ทำอะไร นอนต่อ" → ให้ทบทวนว่าการแจ้งเตือนนี้ควรมีอยู่หรือไม่

ระบบมอนิเตอร์ส่วนใหญ่มีของอยู่ในกลุ่มแรกมากเกินไป และในกลุ่มที่สองน้อยเกินไป คำตอบที่ถูกต้องสำหรับอีเวนต์ส่วนใหญ่คือ "ค่อยจัดการพรุ่งนี้" และการแจ้งเตือนแบบสำคัญตามเวลาที่ขึ้นบนหน้าจอล็อกโดยไม่ส่งเสียงเรียกเข้า ก็คือเครื่องมือที่เหมาะกับกรณีนั้นพอดี

เปลี่ยนทีละอย่าง

ถ้าระบบปัจจุบันของคุณกำลังสร้างอาการล้าจากการแจ้งเตือน ทางแก้ที่เร็วที่สุดไม่ใช่การรื้อใหม่ทั้งหมด ให้เลือกแหล่งที่ส่งเสียงดังที่สุด ซึ่งน่าจะเป็นอีเมลจาก Sentry หรือห้อง Slack ที่ทุกคนปิดเสียงไปแล้ว จากนั้นจัดหมวดอีเวนต์แต่ละประเภทว่าเป็นโทรเข้า สำคัญตามเวลา หรือปกติ

หนึ่งแหล่ง หนึ่งสัปดาห์ แล้วดูว่าสัญญาณรบกวนลดลงโดยไม่เสียสัญญาณจริงไปไหม

จากนั้นค่อยทำแหล่งถัดไป

ระบบแจ้งเตือนที่จูนมาดีเป็นหนึ่งในสิ่งที่ค่อย ๆ ทำให้ชีวิตการทำงานประจำวันของคุณดีขึ้นอย่างเงียบ ๆ โดยไม่ต้องมีดราม่า คุณจะเลิกกลัวมือถือของตัวเอง และเริ่มเชื่อได้ว่าถ้ามันดังขึ้นมา มันสำคัญจริง


เนื้อหาที่เกี่ยวข้อง

บทความที่เกี่ยวข้อง

แจ้งเตือนด้วยสายโทรเข้าจาก Prometheus Alertmanager: ให้ปลุกเฉพาะเรื่องวิกฤต

Alertmanager ไม่มี receiver แบบเสียง มาดูวิธีส่ง alert ของ Prometheus ไปเป็นสายโทรเข้าเฉพาะระดับวิกฤต ทั้งการตั้งค่า webhook เงื่อนไข และกับดักของ Watchdog

อ่านต่อ

แจ้งเตือนเมื่อ Cron Job ล้มเหลว: ให้โทรหาคุณทันทีที่งานตามกำหนดเวลาหยุดทำงาน

cron job ล้มเหลวแบบเงียบ ๆ มาดูสามรูปแบบที่เชื่อถือได้ในการตรวจจับงานตามกำหนดเวลาที่ล้มเหลวหรือไม่ได้รัน แล้วรับการแจ้งเตือนแบบพุชหรือสายโทรเข้าภายในไม่กี่วินาที

อ่านต่อ

Echobell ในสนามจริง: กรณีใช้งานและการเชื่อมต่อที่ได้ผลจริง

ตั้งแต่การมอนิเตอร์ API ไปจนถึงระบบอัตโนมัติบน Zapier และการแจ้งเตือนงาน AI นี่คือวิธีที่นักพัฒนา ทีมงาน และผู้ใช้ระดับสูงดึงประโยชน์จาก Echobell ได้เต็มที่

อ่านต่อ