Webhook Notification System Architecture in the INFINI Console Alerting Module
The webhook notification system architecture in INFINI Console implements a pipeline-based design that transforms triggered alerts into HTTP POST requests through discrete components including channel resolution, template rendering, and asynchronous execution.
The alerting subsystem within the infinilabs/console repository provides a robust webhook notification system architecture that enables external integrations. This system processes alert events through a structured pipeline, converting rule violations into formatted HTTP requests dispatched to configurable endpoints.
Overview of the Webhook Notification Pipeline
The architecture follows a five-stage pipeline pattern that separates concerns between configuration storage, runtime resolution, action execution, HTTP dispatch, and result collection.
- Configuration Storage – Webhook destinations persist as
Channelentities withType = "webhook". - Runtime Resolution – The engine retrieves channels and resolves templated values in URLs and bodies.
- Action Execution – Resolved data instantiates a concrete
WebhookAction. - HTTP Dispatch – The action constructs and sends HTTP POST requests via a shared
http.Client. - Result Collection – Response data aggregates into
ActionExecutionResultrecords for audit trails.
Each stage is handled by specialized components within the service/alerting package, ensuring clean separation between data models, business logic, and transport mechanisms.
Core Components and Data Models
Channel Configuration
Webhook destinations are persisted as Channel entities defined in model/alerting/destination.go. Each channel specifies a Type field set to "webhook" and embeds a CustomWebhook configuration struct containing the endpoint details.
Webhook Payload Structure
The CustomWebhook struct in model/alerting/webhook.go defines the HTTP request parameters:
Method: HTTP verb (typically POST)URL: Endpoint address supporting Gotext/templatesyntaxHeaderParams: Custom HTTP headers for authentication or content-typeBody: Request payload with template variables
Runtime Execution Flow
Channel Retrieval
When an alert triggers, the engine invokes common.RetrieveChannel from service/alerting/common/helper.go. This function loads the persisted channel configuration, validates that the channel is enabled, and populates default values for missing fields.
Template Resolution
The common.ResolveMessage function processes the webhook URL and Body fields as Go text/template strings. It injects alert-specific context variables including title, message, rule_name, and environment variables from the ctx map.
Action Dispatch
The resolved configuration is passed to common.PerformChannel, which instantiates a WebhookAction from service/alerting/action/webhook.go. The action's Execute method constructs the HTTP request, applies custom headers, and dispatches the POST request using a shared http.Client.
Result Aggregation
The performChannels function in service/alerting/elasticsearch/engine.go orchestrates the entire workflow. It iterates over configured channels, invokes PerformChannel for each, and aggregates the results into ActionExecutionResult structs that are persisted with the alert record.
Implementation Example
The following example demonstrates defining and executing a webhook channel:
// Define a webhook channel configuration
channel := alerting.Channel{
Name: "Production Slack Alerts",
Type: alerting.ChannelWebhook,
Webhook: &alerting.CustomWebhook{
Method: "POST",
URL: "https://hooks.slack.com/services/{{.env.SLACK_WEBHOOK}}",
HeaderParams: map[string]string{
"Content-Type": "application/json",
},
Body: `{
"text": "{{.title}} - {{.message}}",
"attachments": [
{"title": "{{.rule_name}}", "color": "danger"}
]
}`,
},
Enabled: true,
}
// Simulate alert context
ctx := map[string]interface{}{
"title": "High CPU Usage",
"message": "CPU utilization exceeded 90% on node-1",
"rule_name": "CPU_Critical",
"env": map[string]string{
"SLACK_WEBHOOK": "T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX",
},
}
// Execute the webhook
result, err, _ := common.PerformChannel(&channel, ctx)
if err != nil {
log.Fatalf("Webhook delivery failed: %v", err)
}
log.Printf("Webhook response: %s", string(result))
The same logic is invoked automatically when an alert rule matches, as part of the Engine.Do workflow in service/alerting/elasticsearch/engine.go.
Key Source Files
| File | Responsibility |
|---|---|
model/alerting/destination.go |
Defines the Channel struct and webhook configuration storage |
model/alerting/webhook.go |
Contains the CustomWebhook payload structure |
service/alerting/common/helper.go |
Implements RetrieveChannel, ResolveMessage, and PerformChannel |
service/alerting/action/webhook.go |
Houses the WebhookAction HTTP client implementation |
service/alerting/elasticsearch/engine.go |
Orchestrates alert processing and channel execution |
plugin/api/alerting/channel.go |
Provides the REST API endpoint for testing webhook channels |
Summary
- The webhook notification system architecture in INFINI Console employs a pipeline pattern separating configuration, resolution, and execution concerns.
- Channel configurations are stored as
Channelentities with embeddedCustomWebhookstructs inmodel/alerting/destination.go. - Template resolution occurs via
common.ResolveMessage, which processes Gotext/templatesyntax in URLs and request bodies. - HTTP dispatch is handled by
WebhookAction.Executeinservice/alerting/action/webhook.go, using a sharedhttp.Clientfor connection reuse. - The alert engine in
service/alerting/elasticsearch/engine.goorchestrates the entire workflow, aggregating results intoActionExecutionResultrecords.
Frequently Asked Questions
How does the webhook notification system handle authentication headers?
The system supports custom HTTP headers through the HeaderParams field in the CustomWebhook struct. You can define authentication tokens, API keys, or content-type specifications in this map, and WebhookAction.Execute applies these headers to the outgoing HTTP request before dispatch.
Can webhook URLs and payloads use dynamic variables from the alert context?
Yes. The common.ResolveMessage function in service/alerting/common/helper.go treats both the URL and Body fields as Go text/template strings. It injects alert-specific variables such as title, message, rule_name, and environment variables from the ctx map, enabling dynamic endpoint targeting and personalized payloads.
What happens if a webhook delivery fails?
When WebhookAction.Execute encounters an HTTP error or non-success status code, it returns the error to the caller. The performChannels function in service/alerting/elasticsearch/engine.go captures these results in ActionExecutionResult structs, which are persisted alongside the alert record. This allows operators to review delivery failures through the alert history API.
Is there a way to test webhook configurations before enabling them?
Yes. The AlertAPI.testChannel handler in plugin/api/alerting/channel.go exposes a REST endpoint at /alert/channel/test. This endpoint constructs a sample alert context and invokes common.PerformChannel against the provided webhook configuration, allowing administrators to verify connectivity and payload formatting without triggering actual alert conditions.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →