From 9ceabe5df4682f76619460b7896398d8a391f2cb Mon Sep 17 00:00:00 2001 From: Ryan Cater Date: Wed, 1 Apr 2026 11:05:40 -0500 Subject: [PATCH 1/9] feat(notifier): add NotificationRequest dataclass and update plugin metadata to onwrite Co-Authored-By: Claude Opus 4.6 (1M context) --- influxdata/notifier/notifier_plugin.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/influxdata/notifier/notifier_plugin.py b/influxdata/notifier/notifier_plugin.py index 182f538..8d6939f 100644 --- a/influxdata/notifier/notifier_plugin.py +++ b/influxdata/notifier/notifier_plugin.py @@ -1,6 +1,6 @@ """ { - "plugin_type": ["http"] + "plugin_type": ["http", "onwrite"] } """ @@ -11,6 +11,7 @@ import random import time import uuid +from dataclasses import dataclass from json import JSONDecodeError import httpx @@ -18,6 +19,13 @@ from twilio.rest import Client +@dataclass +class NotificationRequest: + sender_type: str + notification_text: str + sender_config: dict[str, str] + + def send_sms_via_twilio(influxdb3_local, params: dict, task_id: str) -> bool: """ Sends an SMS via the Twilio API. From 4869f887a0140284563b162e91f6399306aa8ef0 Mon Sep 17 00:00:00 2001 From: Ryan Cater Date: Wed, 1 Apr 2026 11:06:10 -0500 Subject: [PATCH 2/9] feat(notifier): add resolve_sender_config for env var credential resolution --- influxdata/notifier/notifier_plugin.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/influxdata/notifier/notifier_plugin.py b/influxdata/notifier/notifier_plugin.py index 8d6939f..d7e2ce9 100644 --- a/influxdata/notifier/notifier_plugin.py +++ b/influxdata/notifier/notifier_plugin.py @@ -26,6 +26,22 @@ class NotificationRequest: sender_config: dict[str, str] +def resolve_sender_config(influxdb3_local, args: dict, task_id: str) -> dict | None: + config = {} + for key, value in args.items(): + if not key.endswith("_env"): + continue + env_value = os.getenv(value) + if env_value is None: + influxdb3_local.error( + f"[{task_id}] Environment variable '{value}' (from arg '{key}') is not set" + ) + return None + clean_key = key[: -len("_env")] + config[clean_key] = env_value + return config + + def send_sms_via_twilio(influxdb3_local, params: dict, task_id: str) -> bool: """ Sends an SMS via the Twilio API. From 4dcc7e459febc3460ddf654087c9389f7010fd26 Mon Sep 17 00:00:00 2001 From: Ryan Cater Date: Wed, 1 Apr 2026 11:06:46 -0500 Subject: [PATCH 3/9] feat(notifier): add build_sender_args adapter for existing sender functions --- influxdata/notifier/notifier_plugin.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/influxdata/notifier/notifier_plugin.py b/influxdata/notifier/notifier_plugin.py index d7e2ce9..b7358e0 100644 --- a/influxdata/notifier/notifier_plugin.py +++ b/influxdata/notifier/notifier_plugin.py @@ -42,6 +42,21 @@ def resolve_sender_config(influxdb3_local, args: dict, task_id: str) -> dict | N return config +ASYNC_SENDER_TYPES = {"slack", "discord", "http"} +SYNC_SENDER_TYPES = {"sms", "whatsapp"} + + +def build_sender_args(request: NotificationRequest) -> dict: + args = {} + if request.sender_type in ASYNC_SENDER_TYPES: + for key, value in request.sender_config.items(): + args[f"{request.sender_type}_{key}"] = value + else: + args.update(request.sender_config) + args["notification_text"] = request.notification_text + return args + + def send_sms_via_twilio(influxdb3_local, params: dict, task_id: str) -> bool: """ Sends an SMS via the Twilio API. From ea0fab60950cdc6a781633ab722d42beed5ccb62 Mon Sep 17 00:00:00 2001 From: Ryan Cater Date: Wed, 1 Apr 2026 11:07:15 -0500 Subject: [PATCH 4/9] feat(notifier): add extract_requests_from_rows for WAL batch processing --- influxdata/notifier/notifier_plugin.py | 30 ++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/influxdata/notifier/notifier_plugin.py b/influxdata/notifier/notifier_plugin.py index b7358e0..1115638 100644 --- a/influxdata/notifier/notifier_plugin.py +++ b/influxdata/notifier/notifier_plugin.py @@ -57,6 +57,36 @@ def build_sender_args(request: NotificationRequest) -> dict: return args +def extract_requests_from_rows( + influxdb3_local, + table_batches: list, + sender_type: str, + sender_config: dict[str, str], + task_id: str, +) -> list[NotificationRequest]: + requests = [] + for batch in table_batches: + for row in batch["rows"]: + # Skip rows with missing or empty notification_text + notification_text = row.get("notification_text") + if not notification_text: + row_id = row.get("id", "unknown") + alert_name = row.get("alert_name", "unknown") + influxdb3_local.warn( + f"[{task_id}] Skipping row missing 'notification_text' " + f"(table={batch['table_name']}, id={row_id}, alert_name={alert_name})" + ) + continue + requests.append( + NotificationRequest( + sender_type=sender_type, + notification_text=notification_text, + sender_config=sender_config, + ) + ) + return requests + + def send_sms_via_twilio(influxdb3_local, params: dict, task_id: str) -> bool: """ Sends an SMS via the Twilio API. From ec2b50b02dafbe071a5702db3f689e28c6b1fb69 Mon Sep 17 00:00:00 2001 From: Ryan Cater Date: Wed, 1 Apr 2026 11:08:15 -0500 Subject: [PATCH 5/9] feat(notifier): add dispatch_notifications with async gather batching Co-Authored-By: Claude Sonnet 4.6 --- influxdata/notifier/notifier_plugin.py | 64 ++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/influxdata/notifier/notifier_plugin.py b/influxdata/notifier/notifier_plugin.py index 1115638..aaa340c 100644 --- a/influxdata/notifier/notifier_plugin.py +++ b/influxdata/notifier/notifier_plugin.py @@ -87,6 +87,70 @@ def extract_requests_from_rows( return requests +async def _dispatch_async_batch( + influxdb3_local, + requests: list[NotificationRequest], + task_id: str, +) -> list: + tasks = [ + alert_async(influxdb3_local, req.sender_type, build_sender_args(req), task_id) + for req in requests + ] + return await asyncio.gather(*tasks, return_exceptions=True) + + +def dispatch_notifications( + influxdb3_local, + requests: list[NotificationRequest], + task_id: str, +) -> list[dict]: + if not requests: + return [] + + async_requests = [r for r in requests if r.sender_type in ASYNC_SENDER_TYPES] + sync_requests = [r for r in requests if r.sender_type in SYNC_SENDER_TYPES] + unknown_requests = [ + r for r in requests + if r.sender_type not in ASYNC_SENDER_TYPES and r.sender_type not in SYNC_SENDER_TYPES + ] + + results = [] + + # Dispatch async senders concurrently in a single event loop + if async_requests: + async_results = asyncio.run( + _dispatch_async_batch(influxdb3_local, async_requests, task_id) + ) + for req, res in zip(async_requests, async_results): + success = not isinstance(res, Exception) and res + results.append({ + "sender_type": req.sender_type, + "success": success, + "notification_text": req.notification_text, + }) + + # Dispatch sync senders sequentially + for req in sync_requests: + sender_fn = send_sms_via_twilio if req.sender_type == "sms" else send_whatsapp_via_twilio + success = sender_fn(influxdb3_local, build_sender_args(req), task_id) + results.append({ + "sender_type": req.sender_type, + "success": success, + "notification_text": req.notification_text, + }) + + # Handle unknown sender types + for req in unknown_requests: + influxdb3_local.warn(f"[{task_id}] Invalid sender type: {req.sender_type}") + results.append({ + "sender_type": req.sender_type, + "success": "Invalid sender", + "notification_text": req.notification_text, + }) + + return results + + def send_sms_via_twilio(influxdb3_local, params: dict, task_id: str) -> bool: """ Sends an SMS via the Twilio API. From a2a80e468ed91d77c991142200c6afe198d8a37a Mon Sep 17 00:00:00 2001 From: Ryan Cater Date: Wed, 1 Apr 2026 11:08:49 -0500 Subject: [PATCH 6/9] feat(notifier): add process_writes WAL trigger entry point --- influxdata/notifier/notifier_plugin.py | 33 ++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/influxdata/notifier/notifier_plugin.py b/influxdata/notifier/notifier_plugin.py index aaa340c..b3a7501 100644 --- a/influxdata/notifier/notifier_plugin.py +++ b/influxdata/notifier/notifier_plugin.py @@ -151,6 +151,39 @@ def dispatch_notifications( return results +def process_writes(influxdb3_local, table_batches, args=None): + task_id = str(uuid.uuid4()) + influxdb3_local.info(f"[{task_id}] Starting process_writes") + + if not args or "sender_type" not in args: + influxdb3_local.error( + f"[{task_id}] Missing 'sender_type' in trigger args" + ) + return None + + sender_type = args["sender_type"] + + sender_config = resolve_sender_config(influxdb3_local, args, task_id) + if sender_config is None: + return None + + requests = extract_requests_from_rows( + influxdb3_local, table_batches, sender_type, sender_config, task_id + ) + + if not requests: + influxdb3_local.info(f"[{task_id}] No valid notification requests to dispatch") + return None + + results = dispatch_notifications(influxdb3_local, requests, task_id) + + influxdb3_local.info( + f"[{task_id}] Dispatched {len(results)} notifications: " + + ", ".join(f"{r['sender_type']}={'ok' if r['success'] is True else 'fail'}" for r in results) + ) + return None + + def send_sms_via_twilio(influxdb3_local, params: dict, task_id: str) -> bool: """ Sends an SMS via the Twilio API. From 4bf233d72ea18e456b7e181d113a12b1f49f62d1 Mon Sep 17 00:00:00 2001 From: Ryan Cater Date: Wed, 1 Apr 2026 11:09:37 -0500 Subject: [PATCH 7/9] feat(notifier): add new mode to process_request with env var credentials Co-Authored-By: Claude Sonnet 4.6 --- influxdata/notifier/notifier_plugin.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/influxdata/notifier/notifier_plugin.py b/influxdata/notifier/notifier_plugin.py index b3a7501..c561c56 100644 --- a/influxdata/notifier/notifier_plugin.py +++ b/influxdata/notifier/notifier_plugin.py @@ -421,6 +421,32 @@ def process_request( task_id: str = str(uuid.uuid4()) influxdb3_local.info(f"[{task_id}] Starting request process") + # New mode: sender_type in args — credentials from env vars, body has notification_text only + if args and "sender_type" in args: + if not request_body: + influxdb3_local.error(f"[{task_id}] No request body provided.") + return {"status": "failed", "message": "No request body provided."} + try: + data = json.loads(request_body) + except JSONDecodeError: + influxdb3_local.error(f"[{task_id}] Invalid JSON in request body.") + return {"status": "failed", "message": "Invalid JSON in request body."} + if "notification_text" not in data: + influxdb3_local.error(f"[{task_id}] Missing 'notification_text' in request body.") + return {"status": "failed", "message": "Missing required field: 'notification_text'."} + + sender_config = resolve_sender_config(influxdb3_local, args, task_id) + if sender_config is None: + return {"status": "failed", "message": "Failed to resolve sender credentials from environment variables."} + + request = NotificationRequest( + sender_type=args["sender_type"], + notification_text=data["notification_text"], + sender_config=sender_config, + ) + results = dispatch_notifications(influxdb3_local, [request], task_id) + return {"status": "success", "message": "Request processed", "results": results} + # Process the request body if request_body: try: From c4e46e31860b2837336ca2be691c24df13b45ba4 Mon Sep 17 00:00:00 2001 From: Ryan Cater Date: Wed, 1 Apr 2026 11:11:52 -0500 Subject: [PATCH 8/9] docs(notifier): document WAL trigger support, table schema, and pub-sub architecture Co-Authored-By: Claude Sonnet 4.6 --- influxdata/notifier/README.md | 221 ++++++++++++++++++++++++++++++++-- 1 file changed, 211 insertions(+), 10 deletions(-) diff --git a/influxdata/notifier/README.md b/influxdata/notifier/README.md index 87dbfd4..d5c6cc7 100644 --- a/influxdata/notifier/README.md +++ b/influxdata/notifier/README.md @@ -1,21 +1,27 @@ # Notifier Plugin -⚡ http +⚡ http, onwrite 🏷️ notifications, webhooks, messaging, alerts 🔧 InfluxDB 3 Core, InfluxDB 3 Enterprise ## Description -The Notifier Plugin provides multi-channel notification capabilities for InfluxDB 3, enabling real-time alert delivery through various communication channels. Send notifications via Slack, Discord, HTTP webhooks, SMS, or WhatsApp based on incoming HTTP requests. Acts as a centralized notification dispatcher that receives data from other plugins or external systems and routes notifications to the appropriate channels. +The Notifier Plugin provides multi-channel notification capabilities for InfluxDB 3, enabling real-time alert delivery through various communication channels. Send notifications via Slack, Discord, HTTP webhooks, SMS, or WhatsApp — either via incoming HTTP requests or when rows are written to a table (WAL trigger). Acts as a centralized notification dispatcher that receives data from other plugins or external systems and routes notifications to the appropriate channels. ## Configuration +### HTTP trigger (legacy mode) + This HTTP plugin receives all configuration via the request body. No trigger arguments are required. +### WAL trigger (onwrite mode) + +The WAL trigger receives `sender_type` and credential env var names via trigger arguments. No secrets are stored in the table or trigger args — all credentials live in environment variables, referenced by name. + ### Plugin metadata 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](https://docs.influxdata.com/influxdb3/explorer/) UI to display and configure the plugin. -### Request body parameters +### Request body parameters (HTTP trigger) Send these parameters as JSON in the HTTP POST request body: @@ -109,15 +115,124 @@ influxdb3 create trigger \ This registers an HTTP endpoint at `/api/v3/engine/notify`. +### WAL trigger + +Create a WAL trigger to fire notifications when rows are written to a table. Each trigger is configured for a single sender type; use multiple triggers on the same table to fan out to multiple channels. + +**Slack example:** + +```bash +influxdb3 create trigger \ + --database mydb \ + --plugin "gh:influxdata/notifier/notifier_plugin.py" \ + --trigger-spec "table:notifications" \ + --trigger-arguments sender_type="slack",webhook_url_env="INFLUXDB3_SLACK_WEBHOOK_URL",headers_env="INFLUXDB3_SLACK_HEADERS" \ + slack_notifier +``` + +This fires whenever a row is written to the `notifications` table and dispatches a Slack notification using the webhook URL stored in the `INFLUXDB3_SLACK_WEBHOOK_URL` environment variable. + ### Enable trigger ```bash influxdb3 enable trigger --database mydb notification_trigger ``` +## Table schema (WAL trigger contract) + +When using the WAL trigger, alert plugins write rows to a shared table. The notifier reads these columns from each row: + +| Column | Type | Required | Description | +|---------------------|--------------|----------|--------------------------------------------------------------------------| +| `time` | timestamp | yes | When the alert fired (set automatically by InfluxDB on write) | +| `notification_text` | string field | yes | The notification message to dispatch | +| `id` | string field | no | Unique ID for this alert instance (set by the alert plugin) | +| `alert_name` | tag | no | Identifies the source, e.g. `"cpu_threshold:prod_monitor"` | + +One row = one notification event. All notifier triggers attached to the table fire on every row. Rows missing `notification_text` are skipped with a warning. + +The table name is user-configured when creating the WAL trigger. The plugin processes rows from any table it is attached to. + +## WAL trigger arguments + +Each WAL trigger is configured with `sender_type` and the names of the environment variables that hold the credentials. The `*_env` keys tell the plugin which env vars to read — the trigger args contain env var **names**, not secret values. + +### Slack + +| Argument | Required | Description | +|-------------------|----------|----------------------------------------------------------| +| `sender_type` | yes | Must be `"slack"` | +| `webhook_url_env` | yes | Name of env var holding the Slack webhook URL | +| `headers_env` | no | Name of env var holding Base64-encoded JSON headers | + +### Discord + +| Argument | Required | Description | +|-------------------|----------|----------------------------------------------------------| +| `sender_type` | yes | Must be `"discord"` | +| `webhook_url_env` | yes | Name of env var holding the Discord webhook URL | +| `headers_env` | no | Name of env var holding Base64-encoded JSON headers | + +### HTTP (generic webhook) + +| Argument | Required | Description | +|-------------------|----------|----------------------------------------------------------| +| `sender_type` | yes | Must be `"http"` | +| `webhook_url_env` | yes | Name of env var holding the custom webhook URL | +| `headers_env` | no | Name of env var holding Base64-encoded JSON headers | + +### SMS (via Twilio) + +| Argument | Required | Description | +|-------------------------|----------|----------------------------------------------------------| +| `sender_type` | yes | Must be `"sms"` | +| `twilio_sid_env` | yes | Name of env var holding the Twilio Account SID | +| `twilio_token_env` | yes | Name of env var holding the Twilio Auth Token | +| `twilio_from_number_env`| yes | Name of env var holding the sender phone number (E.164) | +| `twilio_to_number_env` | yes | Name of env var holding the recipient phone number (E.164)| + +### WhatsApp (via Twilio) + +| Argument | Required | Description | +|-------------------------|----------|-------------------------------------------------------------| +| `sender_type` | yes | Must be `"whatsapp"` | +| `twilio_sid_env` | yes | Name of env var holding the Twilio Account SID | +| `twilio_token_env` | yes | Name of env var holding the Twilio Auth Token | +| `twilio_from_number_env`| yes | Name of env var holding the sender WhatsApp number (E.164) | +| `twilio_to_number_env` | yes | Name of env var holding the recipient WhatsApp number (E.164)| + +## Pub-sub architecture + +The WAL trigger enables a pub-sub notification pattern where the table acts as a message bus: + +``` + PUBLISHERS SUBSCRIBERS + (alert plugins write rows) (notifier triggers fire on writes) + + ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ + │ threshold │ │ deadman │ │ slack │ │ sms │ + │ alert │ │ alert │ │ notifier │ │ notifier │ + │ plugin │ │ plugin │ │ (trigger) │ │ (trigger) │ + └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ + │ │ │ │ + └────────┬────────┘ └────────┬────────┘ + │ │ + ▼ ▼ + ┌────────────────────────────────────────────────────────┐ + │ notifications table │ + │ (the contract) │ + └────────────────────────────────────────────────────────┘ +``` + +- **Publishers** (alert plugins) write rows containing the notification message and optional metadata +- **Subscribers** (notifier triggers) fire on every write and dispatch via their configured sender +- **Fan-out** is structural: attach N triggers to the same table and every row triggers N notifications +- **Fan-in** is natural: M alert plugins write to the same table and all messages reach all subscribers +- **Secrets never touch the table.** Each notifier trigger owns its credentials via env var names in trigger args and secret values in environment variables + ## Example usage -### Example 1: Slack notification +### Example 1: Slack notification (HTTP trigger) Send a notification to Slack: @@ -141,7 +256,7 @@ Set `INFLUXDB3_AUTH_TOKEN` and `SLACK_WEBHOOK_URL` to your credentials. Notification sent to Slack channel with message: "Alert: High CPU usage detected on server1" -### Example 2: SMS notification +### Example 2: SMS notification (HTTP trigger) Send an SMS via Twilio: @@ -162,7 +277,7 @@ curl -X POST http://localhost:8181/api/v3/engine/notify \ Set `TWILIO_FROM_NUMBER` and `TWILIO_TO_NUMBER` to your phone numbers. Twilio credentials can be set via `TWILIO_SID` and `TWILIO_TOKEN` environment variables. -### Example 3: Multi-channel notification +### Example 3: Multi-channel notification (HTTP trigger) Send notifications via multiple channels simultaneously: @@ -185,11 +300,51 @@ curl -X POST http://localhost:8181/api/v3/engine/notify \ Set `SLACK_WEBHOOK_URL` and `DISCORD_WEBHOOK_URL` to your webhook URLs. +### Example 4: End-to-end WAL trigger (alert plugin → notifier) + +This example shows an alert plugin writing a row to the `notifications` table and the notifier WAL trigger dispatching the notification to Slack. + +**Step 1: Set up credentials** + +```bash +export INFLUXDB3_SLACK_WEBHOOK_URL="https://hooks.slack.com/services/..." +``` + +**Step 2: Create the WAL trigger** + +```bash +influxdb3 create trigger \ + --database mydb \ + --plugin "gh:influxdata/notifier/notifier_plugin.py" \ + --trigger-spec "table:notifications" \ + --trigger-arguments sender_type="slack",webhook_url_env="INFLUXDB3_SLACK_WEBHOOK_URL" \ + slack_notifier + +influxdb3 enable trigger --database mydb slack_notifier +``` + +**Step 3: Alert plugin writes a row (publisher)** + +An alert plugin (or any code with write access) writes a row to the `notifications` table: + +```python +# Inside an alert plugin's process_scheduled_call or process_writes +influxdb3_local.write_line_protocol( + "notifications,alert_name=cpu_threshold:prod_monitor " + "notification_text=\"CPU usage at 95% on server1\"," + "id=\"alert-20260401-001\"" +) +``` + +**Step 4: Notifier fires automatically (subscriber)** + +The `slack_notifier` WAL trigger fires on the write, reads `notification_text` from the row, resolves the Slack webhook URL from the `INFLUXDB3_SLACK_WEBHOOK_URL` env var, and dispatches the notification to Slack — no further action required. + ## Code overview ### Files -- `notifier_plugin.py`: The main plugin code containing the HTTP handler for notification dispatch +- `notifier_plugin.py`: The main plugin code containing both the WAL trigger and HTTP handler for notification dispatch ### Logging @@ -201,9 +356,36 @@ influxdb3 query --database YOUR_DATABASE "SELECT * FROM system.processing_engine ### Main functions -#### `process_http_request(influxdb3_local, request_body, args)` +#### `process_writes(influxdb3_local, table_batches, args)` -Handles incoming HTTP notification requests. Parses the request body, extracts notification text and sender configurations, and dispatches notifications to configured channels. +WAL trigger entry point. Called by the InfluxDB Processing Engine each time rows are written to a table the trigger is attached to. + +Key operations: + +1. Validates `sender_type` is present in `args`; logs error and returns early if missing +2. Resolves credentials once from env vars (reads each `*_env` arg, looks up the corresponding env var) +3. Iterates `table_batches` and rows, skipping any row missing `notification_text` +4. Dispatches all notifications in a single batched call (async senders run concurrently) +5. Logs summary results per sender + +Returns `None` (WAL trigger API contract; return value is ignored by the engine). + +#### `process_request(influxdb3_local, query_parameters, request_headers, request_body, args)` + +HTTP trigger entry point. Routes between two modes based on the presence of `sender_type` in `args`: + +**New mode** (`sender_type` present in `args`): + +Credentials come from environment variables, referenced by `*_env` trigger args. The request body need only contain `notification_text`. + +1. Parses and validates JSON body for `notification_text`; returns error dict if missing or invalid +2. Resolves credentials from env vars using the `*_env` trigger args; returns error dict if resolution fails +3. Builds a single notification request and dispatches it +4. Returns dispatch results + +**Legacy mode** (no `sender_type` in `args`): + +All credentials and channel configuration come from the request body in `senders_config`. This code path is unchanged — existing integrations continue to work without modification. Key operations: @@ -228,11 +410,30 @@ Key operations: **Solution**: Plugin includes built-in retry logic with exponential backoff. Consider implementing client-side rate limiting for high-frequency notifications. +#### Issue: WAL trigger rows skipped + +**Solution**: Ensure rows written to the notifications table include the `notification_text` field. Rows missing this field are skipped with a warning logged to `system.processing_engine_logs`. + +#### Issue: WAL trigger missing `sender_type` + +**Solution**: Verify `--trigger-arguments` includes `sender_type=` when creating the WAL trigger. The trigger will log an error and return early if `sender_type` is absent. + ### Environment variables -For security, set Twilio credentials as environment variables: +For security, set credentials as environment variables rather than passing them in requests: ```bash +# Slack +export INFLUXDB3_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/... + +# Discord +export INFLUXDB3_DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/... + +# Twilio (SMS/WhatsApp) +export INFLUXDB3_TWILIO_SID=your_account_sid +export INFLUXDB3_TWILIO_TOKEN=your_auth_token + +# Legacy HTTP trigger (Twilio fallback) export TWILIO_SID=your_account_sid export TWILIO_TOKEN=your_auth_token ``` From 44f884cf70b6149f7083bfe745a55269a93fba87 Mon Sep 17 00:00:00 2001 From: Ryan Cater Date: Wed, 1 Apr 2026 15:55:31 -0500 Subject: [PATCH 9/9] chore: update plugin_library.json for notifier WAL trigger support Co-Authored-By: Claude Opus 4.6 (1M context) --- influxdata/library/plugin_library.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/influxdata/library/plugin_library.json b/influxdata/library/plugin_library.json index 1131eba..98aa207 100644 --- a/influxdata/library/plugin_library.json +++ b/influxdata/library/plugin_library.json @@ -64,13 +64,13 @@ { "name": "Notification sender", "path": "influxdata/notifier/notifier_plugin.py", - "description": "Standalone notification dispatcher that sends notifications through various channels (Slack, Discord, HTTP, SMS, WhatsApp) based on incoming HTTP requests. Features retry logic and environment variable support.", + "description": "Standalone notification dispatcher that sends notifications through various channels (Slack, Discord, HTTP, SMS, WhatsApp) based on incoming HTTP requests or table writes (WAL triggers). Features retry logic, environment variable credential resolution, and concurrent async dispatch.", "author": "InfluxData", "docs_file_link": "https://github.com/influxdata/influxdb3_plugins/blob/main/influxdata/notifier/README.md", "required_plugins": [], "required_libraries": ["httpx", "twilio"], - "last_update": "2025-06-16", - "trigger_types_supported": ["http"] + "last_update": "2026-04-01", + "trigger_types_supported": ["http", "data_writes"] }, { "name": "Basic Transformation",