Skip to content

Alert System

Tyler Conlee edited this page Apr 1, 2026 · 1 revision

Alert System

Overview

The alert system is the core of TicketPulse. It connects Zendesk ticket events to Slack notifications through a pipeline of tag matching, condition evaluation, deduplication, and delivery.

Alert Types

Type Constant Description
New Ticket new_ticket Fires when a ticket matching a watched tag is created (within 5-minute window)
Ticket Update ticket_update Fires when a matching ticket receives a new public comment from an end user
SLA Reply sla_reply Fires when a reply SLA metric is approaching or has breached its target
SLA Resolution sla_resolution Fires when a resolution SLA metric is approaching or has breached its target
SLA Deadline (legacy) sla_deadline Deprecated catch-all SLA type; matches both reply and resolution metrics

Tag Alert Rules

Each user can configure multiple tag alert rules. A rule consists of:

  • Tag -- A Zendesk tag to watch for (matched against ticket tags)
  • Slack Channel -- The channel where alerts are posted
  • Alert Type -- One of the types above

Rules are stored in the user_tag_alerts database table and loaded fresh on each polling cycle.

Processing Pipeline

flowchart TD
    Poll[Polling Service] --> Fetch[Fetch Tickets from Zendesk]
    Fetch --> Dedup[Deduplicate by Ticket ID]
    Dedup --> LoadRules[Load All Tag Alert Rules]
    LoadRules --> BuildIndex[Build Tag Index<br/>tag -> alerts]
    BuildIndex --> Loop[For Each Ticket]
    Loop --> MatchTags[Match Ticket Tags<br/>Against Index]
    MatchTags --> ForEachAlert[For Each Matching Alert]
    ForEachAlert --> CheckType{Alert Type?}

    CheckType -->|new_ticket| CheckNew{Created < 5min ago?}
    CheckNew -->|Yes| SendGeneric[Send Alert + Log]
    CheckNew -->|No| SkipNew[Skip: outside window]

    CheckType -->|ticket_update| CheckUpdate{Updated since poll?<br/>End-user comment?}
    CheckUpdate -->|Yes| SendGeneric
    CheckUpdate -->|No| SkipUpdate[Skip: no end-user comment]

    CheckType -->|sla_*| CheckSLA{SLA metric active?<br/>Threshold met?}
    CheckSLA -->|Yes| CheckDedup{Duplicate?}
    CheckDedup -->|No| SendSLA[Send Alert + Cache + Log]
    CheckDedup -->|Yes| SkipSLA[Skip: duplicate]
    CheckSLA -->|No| SkipSLAInactive[Skip: inactive/mismatch]
Loading

Step-by-Step

  1. Load rules -- All user_tag_alerts rows are fetched, including the associated user data.
  2. Build tag index -- A map from tag name to list of alert rules is built for fast lookup.
  3. Match tags -- For each ticket, its Zendesk tags are checked against the index. All matching rules are collected.
  4. Evaluate conditions -- Each matching rule is evaluated based on its alert type:
    • new_ticket: Was the ticket created within the last 5 minutes?
    • ticket_update: Was the ticket updated since lastPollTime, and does it have a recent public comment from an end user?
    • sla_*: Is there an active SLA metric that matches the alert type, and has it crossed a threshold?
  5. Deduplication (SLA only): SLA alerts are checked against the sla_alert_cache to avoid sending duplicate alerts for the same threshold.
  6. Send alert: The Slack message is posted and an alert_log entry is created.
  7. Record skips: If an alert was skipped, a skipped_alerts entry is created with the reason.

SLA Alert Deduplication

SLA alerts use a cache table (sla_alert_cache) to prevent duplicate notifications:

  • Before sending an SLA alert, the system checks for an existing cache entry with the same (user_id, ticket_id, alert_type, metric_type).
  • If a cache entry exists with the same label (e.g., "Less than 1 hour remaining"), the alert is skipped as a duplicate.
  • If a cache entry exists with a different label (the SLA has progressed to a new threshold), the old entry is cleared and the new alert is sent.
  • Cache entries older than 24 hours are automatically cleared after each polling cycle.

Skip Reasons

When an alert is not sent, the reason is recorded in the skipped_alerts table:

Reason Constant Description
SLA Duplicate sla_duplicate Same SLA threshold already alerted for this ticket/user/metric
New Ticket Outside Window new_ticket_outside_window Ticket was created more than 5 minutes ago
No End-User Comment update_no_end_user_comment No recent public comment from an end user
Not Modified update_not_modified Ticket wasn't updated since last poll
Metric Mismatch sla_metric_mismatch SLA metric type doesn't match the alert rule (e.g., reply metric on resolution rule)
Inactive Stage sla_stage_inactive SLA metric is in paused or completed stage

Alert Logging

Every sent alert creates an entry in the alert_logs table with:

  • User ID (the user whose rule triggered the alert)
  • Ticket ID
  • Tag that matched
  • Alert type
  • Timestamp

This data powers the dashboard charts, alert history page, and the daily alert log digest.

Acknowledgment

See Slack Integration for the full acknowledge flow. When an alert is acknowledged:

  1. The ticket is assigned to the acknowledging user in Zendesk
  2. An internal note is added to the ticket
  3. An acknowledgment_logs entry is created, linked to the alert_logs entry
  4. The Slack message is updated to remove the button and show who acknowledged it

Alert History

Users can view their alert history at /alerts/history with:

  • Paginated list of all alert log entries (most recent first)
  • Aggregate statistics: total alerts, alerts today, top tags, top alert types

Clone this wiki locally