content/shared/influxdb3-plugins/plugins-library/official/mad-check.md
The MAD-Based Anomaly Detection Plugin provides real-time anomaly detection for time series data in {{% product-name %}} using Median Absolute Deviation (MAD). Detect outliers in your field values as data is written, with configurable thresholds for both count-based and duration-based alerts. The plugin maintains in-memory deques for efficient computation and integrates with the Notification Sender Plugin to deliver alerts via multiple channels.
Plugin parameters may be specified as key-value pairs in the --trigger-arguments flag (CLI) or in the trigger_arguments field (API) when creating a trigger. Some plugins support TOML configuration files, which can be specified using the plugin's config_file_path parameter.
If a plugin supports multiple trigger specifications, some parameters may depend on the trigger specification that you use.
This plugin includes a JSON metadata schema in its docstring that defines supported trigger types and configuration parameters. This metadata enables the InfluxDB 3 Explorer UI to display and configure the plugin.
| Parameter | Type | Default | Description |
|---|---|---|---|
measurement | string | required | Source measurement to monitor for anomalies |
mad_thresholds | string | required | MAD threshold conditions. Format: field:k:window_count:threshold |
senders | string | required | Dot-separated list of notification channels (for example, "slack.discord") |
| Component | Description | Example |
|---|---|---|
field_name | The numeric field to monitor | temp |
k | MAD multiplier for anomaly threshold | 2.5 |
window_count | Number of recent points for MAD computation | 20 |
threshold | Count (integer) or duration (for example, "2m", "1h") | 5 or 2m |
Multiple thresholds are separated by @: temp:2.5:20:5@load:3:10:2m
| Parameter | Type | Default | Description |
|---|---|---|---|
influxdb3_auth_token | string | env var | API token for {{% product-name %}} (or use INFLUXDB3_AUTH_TOKEN env var) |
state_change_count | string | "0" | Maximum allowed value flips before suppressing notifications |
notification_count_text | string | see Default notification templates | Template for count-based alerts with variables: $table, $field, $threshold_count, $tags |
notification_time_text | string | see Default notification templates | Template for duration-based alerts with variables: $table, $field, $threshold_time, $tags |
notification_path | string | "notify" | URL path for the notification sending plugin |
port_override | string | "8181" | Port number where InfluxDB accepts requests |
"MAD count alert: Field $field in $table outlier for $threshold_count consecutive points. Tags: $tags""MAD duration alert: Field $field in $table outlier for $threshold_time. Tags: $tags"| Parameter | Type | Required | Description |
|---|---|---|---|
slack_webhook_url | string | Yes | Webhook URL from Slack |
slack_headers | string | No | Base64-encoded HTTP headers |
| Parameter | Type | Required | Description |
|---|---|---|---|
discord_webhook_url | string | Yes | Webhook URL from Discord |
discord_headers | string | No | Base64-encoded HTTP headers |
| Parameter | Type | Required | Description |
|---|---|---|---|
http_webhook_url | string | Yes | Custom webhook URL for POST requests |
http_headers | string | No | Base64-encoded HTTP headers |
| Parameter | Type | Required | Description |
|---|---|---|---|
twilio_sid | string | Yes | Twilio Account SID (or use TWILIO_SID env var) |
twilio_token | string | Yes | Twilio Auth Token (or use TWILIO_TOKEN env var) |
twilio_from_number | string | Yes | Sender phone number |
twilio_to_number | string | Yes | Recipient phone number |
| Parameter | Type | Default | Description |
|---|---|---|---|
config_file_path | string | none | TOML config file path relative to PLUGIN_DIR (required for TOML configuration) |
To use a TOML configuration file, set the PLUGIN_DIR environment variable and specify the config_file_path in the trigger arguments. This is in addition to the --plugin-dir flag when starting {{% product-name %}}.
mad_anomaly_config_data_writes.toml
For more information on using TOML configuration files, see the Using TOML Configuration Files section in the influxdb3_plugins/README.md.
requests (for notification delivery)senders parameter. See the influxdata/notifier plugin.Start {{% product-name %}} with the Processing Engine enabled (--plugin-dir /path/to/plugins):
influxdb3 serve \
--node-id node0 \
--object-store file \
--data-dir ~/.influxdb3 \
--plugin-dir ~/.plugins
Install required Python packages:
influxdb3 install package requests
(Optional) For notifications, install the influxdata/notifier plugin and create an HTTP trigger for it.
The plugin assumes that the table schema is already defined in the database, as it relies on this schema to retrieve field and tag names required for processing.
Detect anomalies as data is written:
influxdb3 create trigger \
--database mydb \
--path "gh:influxdata/mad_check/mad_check_plugin.py" \
--trigger-spec "all_tables" \
--trigger-arguments 'measurement=cpu,mad_thresholds="temp:2.5:20:5@load:3:10:2m",senders=slack,slack_webhook_url="$SLACK_WEBHOOK_URL"' \
mad_anomaly_detector
Set SLACK_WEBHOOK_URL to your Slack incoming webhook URL.
Detect when temperature exceeds 2.5 MADs from the median for 5 consecutive points:
# Create trigger for count-based detection
influxdb3 create trigger \
--database sensors \
--path "gh:influxdata/mad_check/mad_check_plugin.py" \
--trigger-spec "all_tables" \
--trigger-arguments 'measurement=environment,mad_thresholds="temperature:2.5:20:5",senders=slack,slack_webhook_url="$SLACK_WEBHOOK_URL"' \
temp_anomaly_detector
# Write test data with an anomaly
influxdb3 write \
--database sensors \
"environment,room=office temperature=22.1"
influxdb3 write \
--database sensors \
"environment,room=office temperature=22.3"
influxdb3 write \
--database sensors \
"environment,room=office temperature=45.8" # Anomaly
# Continue writing anomalous values...
Set SLACK_WEBHOOK_URL to your Slack incoming webhook URL.
Expected output
Monitor CPU load and memory usage with different thresholds:
# Create trigger with multiple thresholds
influxdb3 create trigger \
--database monitoring \
--path "gh:influxdata/mad_check/mad_check_plugin.py" \
--trigger-spec "all_tables" \
--trigger-arguments 'measurement=system_metrics,mad_thresholds="cpu_load:3:30:2m@memory_used:2.5:30:5m",senders=slack.discord,slack_webhook_url="$SLACK_WEBHOOK_URL",discord_webhook_url="$DISCORD_WEBHOOK_URL"' \
system_anomaly_detector
Set SLACK_WEBHOOK_URL and DISCORD_WEBHOOK_URL to your webhook URLs.
Expected output
cpu_load: Alerts when exceeds 3 MADs for 2 minutesmemory_used: Alerts when exceeds 2.5 MADs for 5 minutesPrevent alert fatigue from rapidly fluctuating values:
# Create trigger with flip suppression
influxdb3 create trigger \
--database iot \
--path "gh:influxdata/mad_check/mad_check_plugin.py" \
--trigger-spec "all_tables" \
--trigger-arguments 'measurement=sensor_data,mad_thresholds="vibration:2:50:10",state_change_count=3,senders=http,http_webhook_url="$HTTP_WEBHOOK_URL",notification_count_text="Vibration anomaly detected on $table. Field: $field, Tags: $tags"' \
vibration_monitor
Set HTTP_WEBHOOK_URL to your HTTP webhook endpoint.
Expected output
This plugin supports using TOML configuration files to specify all plugin arguments.
To use TOML configuration files, you must set the PLUGIN_DIR environment variable in the {{% product-name %}} host environment.
PLUGIN_DIR=~/.plugins influxdb3 serve \
--node-id node0 \
--object-store file \
--data-dir ~/.influxdb3 \
--plugin-dir ~/.plugins
cp mad_anomaly_config_data_writes.toml ~/.plugins/
Edit the TOML file to match your requirements:
# Required parameters
measurement = "cpu"
mad_thresholds = "temp:2.5:20:5@load:3:10:2m"
senders = "slack"
# Notification settings
slack_webhook_url = "$SLACK_WEBHOOK_URL"
notification_count_text = "Custom alert: $field anomaly detected"
Set SLACK_WEBHOOK_URL to your Slack incoming webhook URL.
Create a trigger using the config_file_path argument:
influxdb3 create trigger \
--database mydb \
--path "gh:influxdata/mad_check/mad_check_plugin.py" \
--trigger-spec "all_tables" \
--trigger-arguments config_file_path=mad_anomaly_config_data_writes.toml \
mad_toml_trigger
mad_check_plugin.py: The main plugin code containing the handler for data write triggersmad_anomaly_config_data_writes.toml: Example TOML configuration fileLogs are stored in the trigger's database in the system.processing_engine_logs table:
influxdb3 query --database YOUR_DATABASE "SELECT * FROM system.processing_engine_logs WHERE trigger_name = 'your_trigger_name'"
Log columns:
process_writes(influxdb3_local, table_batches, args)Handles real-time anomaly detection on incoming data.
Key operations:
median = statistics.median(values)
mad = statistics.median([abs(x - median) for x in values])
threshold = k * mad
is_anomaly = abs(value - median) > threshold
Counts transitions between normal and anomalous states within the window to prevent alert fatigue from rapidly changing values.
Solution:
bash influxdb3 query --database YOUR_DATABASE "SELECT * FROM system.processing_engine_logs WHERE log_text LIKE '%notification%'" Solution: Check threshold format is correct:
field:k:window:count (for example, temp:2.5:20:5)field:k:window:duration (for example, temp:2.5:20:2m)@Solution:
state_change_countSolution:
influxdb3 query --database YOUR_DATABASE "SELECT * FROM system.processing_engine_logs WHERE log_text LIKE '%Deque%'"
influxdb3 query --database YOUR_DATABASE "SELECT * FROM system.processing_engine_logs WHERE log_text LIKE '%MAD:%'"
window_count valuesFor plugin issues, see the Plugins repository issues page.
The InfluxDB Discord server is the best place to find support for InfluxDB 3 Core and InfluxDB 3 Enterprise. For other InfluxDB versions, see the Support and feedback options.