|
1 | 1 | # Alert |
2 | 2 |
|
3 | | -Timeplus alerts enable you to monitor your streaming data and automatically trigger actions when specific conditions are met. When your streaming queries detect events of interest, alerts can notify stakeholders via email or Slack, send data to downstream systems like Apache Kafka, or execute custom Python functions for automated responses. |
| 3 | +## Overview |
4 | 4 |
|
5 | | -## Create New Alert |
| 5 | +A **Timeplus Alert** continuously monitors events in a source stream using a **streaming query**. When the specified conditions are met, it triggers a [Python UDF](/py-udf) to **interact with external systems** — for example, sending notifications to **Slack**, **Email**, or other services. |
| 6 | + |
| 7 | +Alerts are often used in combination with [Scheduled Tasks](/task) and [Materialized Views](/materialized-view) to form a **complete, automated data pipeline**, as illustrated below: |
| 8 | + |
| 9 | + |
| 10 | + |
| 11 | +## Create Alert |
6 | 12 |
|
7 | | -### Syntax |
8 | 13 | ```sql |
9 | | -CREATE [OR REPLACE] ALERT [IF NOT EXISTS] [database.]alert_name |
10 | | -BATCH <N> EVENTS WITH TIMEOUT <nUnit> |
11 | | -LIMIT <N> ALERTS PER <nUnit> |
12 | | -CALL <python_udf_name> |
13 | | -AS <select_query>; |
| 14 | +CREATE ALERT [IF NOT EXISTS] <db.alert-name> |
| 15 | +BATCH <N> EVENTS WITH TIMEOUT <interval> |
| 16 | +LIMIT <M> ALERTS PER <interval> |
| 17 | +CALL <python-udf-name> |
| 18 | +AS <streaming-select-query>; |
14 | 19 | ``` |
15 | 20 |
|
16 | | -For example: |
| 21 | +:::info |
| 22 | +The **streaming select query** in an **Alert** must be a **simple** `SELECT` statement that consumes data directly from a stream. |
| 23 | +Stateful operations such as **joins** or **aggregations** are **not supported** within Alerts. |
| 24 | + |
| 25 | +If your use case requires joins, aggregations, or other complex logic, create a **Materialized View** first to perform those computations and **materialize** the results into a target stream. |
| 26 | +Then, the Alert can consume that **pre-computed stream** to trigger external actions. |
| 27 | +::: |
| 28 | + |
| 29 | +### `BATCH N EVENTS WITH TIMEOUT interval` |
| 30 | + |
| 31 | +Defines how events are **batched** before invoking the alert action, improving efficiency and throughput. |
| 32 | +Batching can also help with **alert suppression**, reducing redundant or noisy alerts. |
| 33 | + |
| 34 | +The alert is triggered when **either** of the following conditions is met: |
| 35 | +- The batch accumulates **`N` events**, or |
| 36 | +- The specified **timeout interval** elapses. |
| 37 | + |
| 38 | +**Example:** |
| 39 | + |
17 | 40 | ```sql |
18 | | -CREATE ALERT default.test |
19 | 41 | BATCH 10 EVENTS WITH TIMEOUT 5s |
20 | | -LIMIT 1 ALERTS PER 15s |
21 | | -CALL alert_action_proton_new_star |
22 | | -AS SELECT actor FROM github_events WHERE repo='timeplus-io/proton' AND type='WatchEvent' |
23 | 42 | ``` |
24 | 43 |
|
25 | | -### Limitations |
26 | | -* The alerts only run on the metadata leader node. |
27 | | -* The return value of the Python UDF is ignored. |
28 | | -* The select query cannot include any aggregation or JOIN. You can create a materialized view with complex JOIN or aggregation logic to cache the alert events and `SELECT` the target stream of the materialized view in the alert definition. |
29 | | -* Check `system.stream_state_log` for the alert states or logs. |
30 | | -* The checkpoints of the alerts are available in `system.alert_ckpt_log` stream with the `_tp_sn` column. |
| 44 | +In this example, the alert will invoke the configured Python UDF **as soon as**: |
| 45 | + |
| 46 | +- 10 events are collected, or |
| 47 | +- 5 seconds pass — whichever happens first. |
| 48 | + |
| 49 | +### `LIMIT M ALERTS PER interval` |
| 50 | + |
| 51 | +Defines **alert suppression** rules to prevent excessive notifications. |
| 52 | +This limits the invocation of the configured Python UDF to at most **`M` alerts** within each specified **`interval`**. |
31 | 53 |
|
32 | | -### Python UDF |
33 | | -You can import Python libraries and build the custom alert action via [Python UDF](/py-udf). The return value doesn't matter. Here is an example to send events to a specific Slack channel via Slack webhook: |
| 54 | +**Example:** |
34 | 55 |
|
35 | 56 | ```sql |
36 | | -CREATE OR REPLACE FUNCTION alert_action_proton_new_star(actor string) RETURNS string LANGUAGE PYTHON AS $$ |
| 57 | +LIMIT 1 ALERTS PER 10s |
| 58 | +``` |
| 59 | + |
| 60 | +This example restricts the system to trigger **no more than one alert every 10 seconds**, |
| 61 | +even if multiple batches or events meet the alert conditions during that period. |
| 62 | + |
| 63 | +### `CALL python-udf-name` |
| 64 | + |
| 65 | +Specifies the **Python UDF** to invoke when events are emitted from the streaming query and both the **batching** and **suppression** conditions are met. |
| 66 | + |
| 67 | +The Python UDF must have a compatible function signature (input parameters) that matches the **projection output** of the streaming query (`SELECT` clause). |
| 68 | + |
| 69 | +:::info |
| 70 | +Currently, only **Python UDFs** are supported. |
| 71 | +::: |
| 72 | + |
| 73 | +### Checkpoint |
| 74 | + |
| 75 | +Timeplus automatically **checkpoints** the sequence numbers (or offsets) of the source stream. |
| 76 | +This ensures that upon recovery, **duplicate alerts are not triggered**. |
| 77 | + |
| 78 | +:::info |
| 79 | +Alert checkpoints are stored in the `system.alert_ckpt_log` **Mutable Stream**. |
| 80 | +::: |
| 81 | + |
| 82 | +### Example |
| 83 | + |
| 84 | +```sql |
| 85 | +CREATE FUNCTION send_star_events_to_slack(actor string) |
| 86 | +RETURNS string |
| 87 | +LANGUAGE PYTHON AS $$ |
37 | 88 | import json |
38 | 89 | import requests |
39 | | -def alert_action_proton_new_star(value): |
40 | | - for i in range(len(value)): |
41 | | - github_id=value[i] |
42 | | - requests.post("https://hooks.slack.com/services/T123/B456/other_id", data=json.dumps({"text": f"New 🌟 for Timeplus Proton from https://github.com/{github_id}"})) |
| 90 | + |
| 91 | +def send_star_events_to_slack(value): |
| 92 | + for github_id in value: |
| 93 | + requests.post( |
| 94 | + "https://hooks.slack.com/services/T123/B456/other_id", |
| 95 | + data=json.dumps({ |
| 96 | + "text": f"New 🌟 for Timeplus Proton from https://github.com/{github_id}" |
| 97 | + }) |
| 98 | + ) |
43 | 99 | return value |
44 | 100 | $$ |
| 101 | + |
| 102 | +CREATE ALERT default.watch_event_alert |
| 103 | +BATCH 10 EVENTS WITH TIMEOUT 5s |
| 104 | +LIMIT 1 ALERTS PER 15s |
| 105 | +CALL send_star_events_to_slack |
| 106 | +AS |
| 107 | +SELECT actor |
| 108 | +FROM github_events |
| 109 | +WHERE repo = 'timeplus-io/proton' AND type = 'WatchEvent'; |
45 | 110 | ``` |
46 | | -Please note, similar to regular Python UDF, the input parameter of the Python UDF is an array, instead of a single event. The return value can be anything but you can return the input value, so that you can test the Python UDF via `SELECT udf_name(input)`. |
| 111 | + |
| 112 | +**Explanation**: |
| 113 | + |
| 114 | +- The alert continuously monitors the `github_events` stream in the background. |
| 115 | +- When a new `WatchEvent` occurs for the GitHub repository `timeplus-io/proton`, the Python UDF `send_star_events_to_slack` is triggered. |
| 116 | +- The UDF posts a formatted message to a Slack webhook, notifying the team of new stars. |
| 117 | +- To avoid alert flooding, the alert is **rate-limited** to **1 alert every 15 seconds**. |
| 118 | +- The alert also **batches events** for efficiency — the UDF is invoked when either **10 events** accumulate or **5 seconds** have passed, whichever comes first. |
47 | 119 |
|
48 | 120 | ## List Alerts |
| 121 | + |
49 | 122 | ```sql |
50 | | -SHOW ALERTS [FROM database_name] [SETTINGS verbose=true] |
| 123 | +SHOW ALERTS [FROM db] [SETTINGS verbose=true] |
51 | 124 | ``` |
52 | 125 |
|
53 | | -Without `SETTINGS verbose=true`, it lists the alert name and its UUID. With `SETTINGS verbose=true`, the following columns are added: |
54 | | -* version |
55 | | -* last_modified |
56 | | -* last_modified_by |
57 | | -* created |
58 | | -* created_by |
| 126 | +## Show Alert |
59 | 127 |
|
60 | | -## Show Alert Definition |
61 | 128 | ```sql |
62 | | -SHOW CREATE ALERT [database.]alert_name [SETTINGS show_multi_versions=true] |
| 129 | +SHOW CREATE ALERT <db.alert-name> [SETTINGS show_multi_versions=true] |
63 | 130 | ``` |
64 | 131 |
|
65 | | -## Drop Alerts |
| 132 | +## Drop Alert |
| 133 | + |
66 | 134 | ```sql |
67 | | -DROP ALERT [database.]alert_name |
| 135 | +DROP ALERT <db.alert-name> |
68 | 136 | ``` |
0 commit comments