Introduction to Nightingale v8 notification media, including the use of Webhook, Email, SMS and other notification methods.
Before reading this section, please make sure you have read the Notification Rules chapter, and the external links mentioned in the Notification Rules chapter have also been read.
Let me simulate a scenario. Suppose I want to use a WeCom application (not the same as a WeCom bot) for alert notifications. Let’s sort out the entire process.
Basic Configuration
- When using WeCom application notifications, you need to know the WeCom account of the person being notified. By default, Nightingale does not have this information. We can customize a contact field called wecomid, and then each user configures it themselves.

In the figure above, wecomid is the field name I customized. Click “Contact Management” (only administrators have permission) to create a new contact method. Here I created a new contact method called wecomid, used to configure the WeCom ID of each user.
- Create a custom notification medium corresponding to my own program. When the user configures Nightingale to send alert messages to this notification medium, Nightingale will call my program, which will call the WeCom interface to send notification messages using the WeCom application (of course, I’m not actually sending here, just a demo, still using the gohttpd small program introduced in the Event Processor chapter for demonstration).

The key fields of the notification medium in the above figure are explained as follows:
- Media type: Can be customized. I randomly named it wecomapp. The notification medium usually needs to be used in conjunction with a message template. As long as the media type of the message template is also called wecomapp, the medium and the message template can be associated.
- Contact method: Select the wecomid contact method created earlier, so that when Nightingale calls my program, it will pass the WeCom ID of the
alert recipientto me. - URL: The address of my program. Nightingale will call this address via HTTP POST. The content of the request body can be defined below.
- Request Body: Used to define the content of the HTTP request body for the callback. Several variables can be referenced. In this example, I referenced all three key variables.
My request body:
{
"events": {{ jsonMarshal $events }},
"sendtos": {{ jsonMarshal $sendtos }},
"tpl": {{ jsonMarshal $tpl }}
}
$eventsis the list of alert events to be sent. Although it is a list, in the open source version there will always be only one event.$sendtosis the list of recipients to send to. In the end, it is a list of WeCom IDs. If the contact method configured is Phone, this$sendtoswill be a list of phone numbers.$tplis the content of the message template, which will be introduced shortly.
Message Template
When finally calling the WeCom interface to send alert messages, obviously we cannot send the entire event JSON, as users would not be able to read it. We need to format the event for display (such as in markdown format). Just like other notification media, custom notification media also need message templates. Below we will create a message template:

Multiple fields can be created in the message template (for example, the email template needs to customize the title and content, so there are two fields). However, in the WeCom application scenario, multiple fields are not needed. We just create one content field, and later we can use markdown format to define the content of the content field. For example:

I’ll also paste the content of the markdown for your reference:
**Rule Title**: {{$event.RuleName}}
**Monitoring Metric**: {{$event.TagsJSON}}
**Send Time**: {{timestamp}}
I’m just demonstrating here, so few fields are rendered in the markdown. Later, you can refer to other templates to enrich this content.
💡 Note that the media type of the message template needs to be consistent with the media type of the notification medium, so that they can be associated. Therefore, here I still wrote wecomapp.
Test
Now we can test it. Create a notification rule:

For ease of testing, I did not configure any filter conditions for this notification rule, that is, any alert event generated will be sent to the “WeCom Application” custom notification medium.
Finally, we create an alert rule and associate the notification rule just created:

Wait a moment and observe whether the program http://10.99.1.107:8888/print receives the callback HTTP request. The result I see in my environment is as follows:

I’ll paste the content of the HTTP request body for your reference:
{
"events": [{
"id": 1097655,
"cate": "prometheus",
"cluster": "prom",
"datasource_id": 1,
"group_id": 2,
"group_name": "DBA-Postgres",
"hash": "f75556af7cedbe250d3d8ab709634c96",
"rule_id": 56,
"rule_name": "测试自定义通知媒介2",
"rule_note": "",
"rule_prod": "metric",
"rule_algo": "",
"severity": 2,
"prom_for_duration": 0,
"prom_ql": "cpu_usage_active{ident=\"ulric-flashcat.local\"} > 0",
"rule_config": {
"queries": [{
"from": 0,
"prom_ql": "cpu_usage_active{ident=\"ulric-flashcat.local\"} > 0",
"range": {
"display": "now to now",
"end": "now",
"start": "now"
},
"severity": 2,
"to": 0,
"unit": "none"
}]
},
"prom_eval_interval": 15,
"callbacks": [],
"runbook_url": "",
"notify_recovered": 1,
"target_ident": "ulric-flashcat.local",
"target_note": "",
"trigger_time": 1749196393,
"trigger_value": "33.06867",
"trigger_values": "",
"trigger_values_json": {
"values_with_unit": {
"v": {
"value": 33.06867479671808,
"unit": "",
"text": "33.07",
"stat": 33.06867479671808
}
}
},
"tags": ["__name__=cpu_usage_active", "cpu=cpu-total", "ident=ulric-flashcat.local", "rulename=测试自定义通知媒介2"],
"tags_map": {
"__name__": "cpu_usage_active",
"cpu": "cpu-total",
"ident": "ulric-flashcat.local",
"rulename": "测试自定义通知媒介2"
},
"original_tags": ["", "", "", ""],
"annotations": {},
"is_recovered": false,
"last_eval_time": 1749196393,
"last_sent_time": 1749196393,
"notify_cur_number": 1,
"first_trigger_time": 1749196393,
"extra_config": {
"enrich_queries": []
},
"status": 0,
"claimant": "",
"sub_rule_id": 0,
"extra_info": null,
"target": null,
"recover_config": {
"judge_type": 0,
"recover_exp": ""
},
"rule_hash": "3c73b1b7f98f4c5a0178c85dedabf008",
"extra_info_map": null,
"notify_rule_ids": [4],
"notify_version": 0,
"notify_rules": null
}],
"sendtos": ["qinxiaohui"],
"tpl": {
"content": "**规则标题**: 测试自定义通知媒介2 \\n**监控指标**: [__name__=cpu_usage_active cpu=cpu-total ident=ulric-flashcat.local rulename=测试自定义通知媒介2] \\n**发送时间**: 2025-06-06 15:53:13 "
}
}
This request body contains not only the event details, but also tpl. tpl is the rendered content, you can directly take this content to call the WeCom interface. The sendtos is a list of WeCom IDs because the contact method we configured in the WeCom application notification medium is wecomid, so the final sendtos contains a list of WeCom IDs. If the contact method you configured in the notification medium is Phone, then sendtos will contain a list of phone numbers.
Now that the data is available, the rest is your custom logic and calling the WeCom interface. I used gohttpd here just to demonstrate the content of the request body. Obviously, the gohttpd tool does not have the capability to send WeCom application messages. You need to implement this logic yourself. That is: you need to write a program yourself that listens on an HTTP port and provides an HTTP POST interface, just like the gohttpd above, receives Nightingale’s callback request, then parses the request body, gets the event details, recipient list, and message template content, and finally calls the WeCom interface to send the message.