Files
attune/docs/examples/rule-parameter-examples.md

641 lines
14 KiB
Markdown

# Rule Parameter Mapping Examples
This document provides practical, copy-paste ready examples of rule parameter mapping.
---
## Example 1: Static Parameters Only
**Use Case:** Simple echo with fixed message (included in seed data as `core.rule.timer_10s_echo`)
**Rule:**
```json
{
"ref": "core.rule.timer_10s_echo",
"pack_ref": "core",
"trigger_ref": "core.intervaltimer",
"action_ref": "core.echo",
"action_params": {
"message": "hello, world"
},
"enabled": true
}
```
**How it works:**
- The rule references the generic `core.intervaltimer` trigger type
- A sensor (`core.timer_10s_sensor`) is configured with `{"unit": "seconds", "interval": 10}` to fire this trigger every 10 seconds
- When the sensor fires the trigger, the rule evaluates and executes the `core.echo` action with the message "hello, world"
**Result:** Every 10 seconds, the timer sensor fires and the echo action receives the message "hello, world" to print to stdout.
**When to use:** Fixed notifications, health checks, scheduled tasks with constant parameters.
**Note:** This example is included in the core pack seed data (`scripts/seed_core_pack.sql`) and serves as a basic demonstration of rule functionality. The seed script creates both the sensor instance and the rule.
---
## Example 2: Dynamic from Event Payload
**Use Case:** Alert with error details from event
**Event Payload:**
```json
{
"service": "payment-api",
"error": "Database connection timeout",
"severity": "critical",
"timestamp": "2026-01-17T15:30:00Z"
}
```
**Rule:**
```json
{
"ref": "alerts.error_notification",
"pack_ref": "alerts",
"trigger_ref": "core.error_event",
"action_ref": "slack.post_message",
"action_params": {
"channel": "#incidents",
"message": "🚨 Error in {{ event.payload.service }}: {{ event.payload.error }}",
"severity": "{{ event.payload.severity }}",
"timestamp": "{{ event.payload.timestamp }}"
},
"enabled": true
}
```
**Resolved Parameters:**
```json
{
"channel": "#incidents",
"message": "🚨 Error in payment-api: Database connection timeout",
"severity": "critical",
"timestamp": "2026-01-17T15:30:00Z"
}
```
**When to use:** Alerts, notifications, any scenario where event data drives the action.
---
## Example 3: Dynamic from Pack Config
**Use Case:** API integration with credentials from config
**Pack Config:**
```json
{
"ref": "slack",
"config": {
"api_token": "xoxb-1234567890-abcdefghijk",
"default_channel": "#general",
"bot_name": "Attune Bot"
}
}
```
**Rule:**
```json
{
"ref": "slack.auto_notify",
"pack_ref": "slack",
"trigger_ref": "core.notification_event",
"action_ref": "slack.post_message",
"action_params": {
"token": "{{ pack.config.api_token }}",
"channel": "{{ pack.config.default_channel }}",
"username": "{{ pack.config.bot_name }}",
"message": "Notification triggered"
},
"enabled": true
}
```
**Resolved Parameters:**
```json
{
"token": "xoxb-1234567890-abcdefghijk",
"channel": "#general",
"username": "Attune Bot",
"message": "Notification triggered"
}
```
**When to use:** API integrations, any action requiring credentials or configuration.
---
## Example 4: Mixed Static and Dynamic
**Use Case:** GitHub issue creation with mixed parameters
**Event Payload:**
```json
{
"error_message": "Memory leak detected",
"severity": "high",
"service": "worker-pool",
"stack_trace": "Error at line 42..."
}
```
**Pack Config:**
```json
{
"ref": "github",
"config": {
"token": "ghp_xxxxxxxxxxxx",
"repo_owner": "myorg",
"repo_name": "myrepo"
}
}
```
**Rule:**
```json
{
"ref": "github.create_issue_on_error",
"pack_ref": "github",
"trigger_ref": "core.error_event",
"action_ref": "github.create_issue",
"action_params": {
"token": "{{ pack.config.token }}",
"repo": "{{ pack.config.repo_owner }}/{{ pack.config.repo_name }}",
"title": "[{{ event.payload.severity }}] {{ event.payload.service }}: {{ event.payload.error_message }}",
"body": "Error Details:\n\nService: {{ event.payload.service }}\nSeverity: {{ event.payload.severity }}\n\nStack Trace:\n{{ event.payload.stack_trace }}",
"labels": ["bug", "automated"],
"assignees": ["oncall"]
},
"enabled": true
}
```
**Resolved Parameters:**
```json
{
"token": "ghp_xxxxxxxxxxxx",
"repo": "myorg/myrepo",
"title": "[high] worker-pool: Memory leak detected",
"body": "Error Details:\n\nService: worker-pool\nSeverity: high\n\nStack Trace:\nError at line 42...",
"labels": ["bug", "automated"],
"assignees": ["oncall"]
}
```
**When to use:** Complex integrations requiring both configuration and event data.
---
## Example 5: Nested Object Access
**Use Case:** Extract deeply nested values
**Event Payload:**
```json
{
"user": {
"id": 12345,
"profile": {
"name": "Alice Smith",
"email": "alice@example.com",
"department": "Engineering"
}
},
"action": "login",
"metadata": {
"ip": "192.168.1.100",
"user_agent": "Mozilla/5.0..."
}
}
```
**Rule:**
```json
{
"ref": "audit.log_user_action",
"pack_ref": "audit",
"trigger_ref": "core.user_event",
"action_ref": "audit.log",
"action_params": {
"user_id": "{{ event.payload.user.id }}",
"user_name": "{{ event.payload.user.profile.name }}",
"user_email": "{{ event.payload.user.profile.email }}",
"department": "{{ event.payload.user.profile.department }}",
"action": "{{ event.payload.action }}",
"ip_address": "{{ event.payload.metadata.ip }}"
},
"enabled": true
}
```
**Resolved Parameters:**
```json
{
"user_id": 12345,
"user_name": "Alice Smith",
"user_email": "alice@example.com",
"department": "Engineering",
"action": "login",
"ip_address": "192.168.1.100"
}
```
**When to use:** Complex event structures, deeply nested data.
---
## Example 6: Array Access
**Use Case:** Extract specific array elements
**Event Payload:**
```json
{
"errors": [
"Connection timeout",
"Retry failed",
"Circuit breaker open"
],
"tags": ["production", "critical", "api-gateway"]
}
```
**Rule:**
```json
{
"ref": "alerts.first_error",
"pack_ref": "alerts",
"trigger_ref": "core.error_event",
"action_ref": "slack.post_message",
"action_params": {
"channel": "#alerts",
"message": "Primary error: {{ event.payload.errors.0 }}",
"secondary_error": "{{ event.payload.errors.1 }}",
"environment": "{{ event.payload.tags.0 }}",
"severity": "{{ event.payload.tags.1 }}"
},
"enabled": true
}
```
**Resolved Parameters:**
```json
{
"channel": "#alerts",
"message": "Primary error: Connection timeout",
"secondary_error": "Retry failed",
"environment": "production",
"severity": "critical"
}
```
**When to use:** Event payloads with arrays where you need specific elements.
---
## Example 7: System Variables
**Use Case:** Include system-provided metadata
**Rule:**
```json
{
"ref": "monitoring.heartbeat",
"pack_ref": "monitoring",
"trigger_ref": "core.timer_5m",
"action_ref": "http.post",
"action_params": {
"url": "{{ pack.config.monitoring_url }}",
"body": {
"source": "attune",
"timestamp": "{{ system.timestamp }}",
"rule_id": "{{ system.rule.id }}",
"rule_ref": "{{ system.rule.ref }}",
"event_id": "{{ system.event.id }}",
"status": "healthy"
}
},
"enabled": true
}
```
**Resolved Parameters (example):**
```json
{
"url": "https://monitoring.example.com/heartbeat",
"body": {
"source": "attune",
"timestamp": "2026-01-17T15:30:00Z",
"rule_id": 42,
"rule_ref": "monitoring.heartbeat",
"event_id": 123,
"status": "healthy"
}
}
```
**When to use:** Audit trails, logging, debugging, tracking execution context.
---
## Example 8: PagerDuty Integration
**Use Case:** Trigger PagerDuty incident from metrics
**Event Payload:**
```json
{
"metric_name": "cpu_usage",
"current_value": 95.3,
"threshold": 80,
"host": "web-server-01",
"duration_seconds": 300
}
```
**Pack Config:**
```json
{
"ref": "pagerduty",
"config": {
"routing_key": "R123ABC456DEF789",
"default_severity": "error"
}
}
```
**Rule:**
```json
{
"ref": "pagerduty.critical_metric",
"pack_ref": "pagerduty",
"trigger_ref": "metrics.threshold_exceeded",
"action_ref": "pagerduty.trigger_incident",
"action_params": {
"routing_key": "{{ pack.config.routing_key }}",
"event_action": "trigger",
"payload": {
"summary": "{{ event.payload.metric_name }} exceeded threshold on {{ event.payload.host }}",
"severity": "critical",
"source": "{{ event.payload.host }}",
"custom_details": {
"metric": "{{ event.payload.metric_name }}",
"current_value": "{{ event.payload.current_value }}",
"threshold": "{{ event.payload.threshold }}",
"duration": "{{ event.payload.duration_seconds }}s"
}
},
"dedup_key": "{{ event.payload.host }}_{{ event.payload.metric_name }}"
},
"enabled": true
}
```
**Resolved Parameters:**
```json
{
"routing_key": "R123ABC456DEF789",
"event_action": "trigger",
"payload": {
"summary": "cpu_usage exceeded threshold on web-server-01",
"severity": "critical",
"source": "web-server-01",
"custom_details": {
"metric": "cpu_usage",
"current_value": 95.3,
"threshold": 80,
"duration": "300s"
}
},
"dedup_key": "web-server-01_cpu_usage"
}
```
**When to use:** Incident management, alerting, on-call notifications.
---
## Example 9: Webhook to Multiple Services
**Use Case:** Fan-out webhook data to multiple channels
**Event Payload:**
```json
{
"event_type": "deployment",
"service": "api-gateway",
"version": "v2.3.1",
"environment": "production",
"deployed_by": "alice@example.com",
"timestamp": "2026-01-17T15:30:00Z"
}
```
**Pack Config:**
```json
{
"ref": "notifications",
"config": {
"slack_channel": "#deployments",
"slack_token": "xoxb-...",
"teams_webhook": "https://outlook.office.com/webhook/...",
"email_recipients": ["team@example.com"]
}
}
```
**Rule (Slack):**
```json
{
"ref": "notifications.deployment_slack",
"pack_ref": "notifications",
"trigger_ref": "webhooks.deployment",
"action_ref": "slack.post_message",
"action_params": {
"token": "{{ pack.config.slack_token }}",
"channel": "{{ pack.config.slack_channel }}",
"message": "✅ Deployment Complete",
"attachments": [
{
"color": "good",
"fields": [
{
"title": "Service",
"value": "{{ event.payload.service }}",
"short": true
},
{
"title": "Version",
"value": "{{ event.payload.version }}",
"short": true
},
{
"title": "Environment",
"value": "{{ event.payload.environment }}",
"short": true
},
{
"title": "Deployed By",
"value": "{{ event.payload.deployed_by }}",
"short": true
}
],
"footer": "Attune Automation",
"ts": "{{ event.payload.timestamp }}"
}
]
},
"enabled": true
}
```
**When to use:** Multi-channel notifications, deployment tracking, audit trails.
---
## Example 10: Conditional Channels (Future with Filters)
**Use Case:** Route to different channels based on severity
**Event Payload:**
```json
{
"severity": "critical",
"message": "Database unreachable"
}
```
**Rule (Future Enhancement with Filters):**
```json
{
"ref": "alerts.smart_routing",
"pack_ref": "alerts",
"trigger_ref": "core.alert_event",
"action_ref": "slack.post_message",
"action_params": {
"channel": "{{ event.payload.severity | default: 'info' | map: {'critical': '#incidents', 'high': '#alerts', 'medium': '#monitoring', 'low': '#logs'} }}",
"message": "{{ event.payload.message }}",
"color": "{{ event.payload.severity | map: {'critical': 'danger', 'high': 'warning', 'medium': 'good', 'low': '#cccccc'} }}"
},
"enabled": true
}
```
**Note:** This uses advanced filter syntax not yet implemented (Phase 2).
---
## Testing Your Rules
### 1. Create a Test Event
```bash
curl -X POST http://localhost:8080/api/v1/events \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"trigger_ref": "core.error_event",
"payload": {
"service": "test-service",
"error": "Test error message",
"severity": "info"
}
}'
```
### 2. Check Enforcement
```bash
curl -X GET http://localhost:8080/api/v1/enforcements?limit=1 \
-H "Authorization: Bearer $TOKEN"
```
Look at the `config` field to verify parameters were resolved correctly.
### 3. Check Execution
```bash
curl -X GET http://localhost:8080/api/v1/executions?limit=1 \
-H "Authorization: Bearer $TOKEN"
```
The `config` field should contain the same resolved parameters.
---
## Common Patterns
### API Authentication
```json
{
"action_params": {
"url": "{{ pack.config.api_url }}",
"headers": {
"Authorization": "Bearer {{ pack.config.api_token }}",
"Content-Type": "application/json"
}
}
}
```
### Error Context
```json
{
"action_params": {
"summary": "Error: {{ event.payload.message }}",
"details": {
"service": "{{ event.payload.service }}",
"host": "{{ event.payload.host }}",
"timestamp": "{{ event.payload.timestamp }}",
"stack_trace": "{{ event.payload.stack_trace }}"
}
}
}
```
### User Information
```json
{
"action_params": {
"user": {
"id": "{{ event.payload.user.id }}",
"name": "{{ event.payload.user.name }}",
"email": "{{ event.payload.user.email }}"
},
"action": "{{ event.payload.action_type }}"
}
}
```
---
## Tips and Best Practices
1. **Use pack config for secrets** - Never hardcode API keys in rules
2. **Provide context** - Include relevant fields from event payload
3. **Keep templates simple** - Deeply nested access can be fragile
4. **Test with sample events** - Verify your templates work before production
5. **Use descriptive field names** - Make it clear what each parameter is for
6. **Document your rules** - Use clear labels and descriptions
---
## Related Documentation
- [Rule Parameter Mapping Guide](../rule-parameter-mapping.md) - Complete reference
- [Rule Management API](../api-rules.md) - API documentation
- [Pack Management](../api-packs.md) - Pack configuration
---
## Need Help?
If your templates aren't resolving correctly:
1. Check the event payload structure in the database
2. Verify the pack config exists and has the expected fields
3. Review sensor service logs for template resolution warnings
4. Test with a simple template first, then add complexity
5. Ensure field names match exactly (case-sensitive)