Notification Channels
Notification channels have two main functions:
- Control which notification channels are displayed in alert rules, allowing you to disable unused contact methods for a more streamlined notification channel configuration.
- Users can create new notification channels to adapt to their company’s own notification systems. Custom notification scripts can then use these new channels to send notifications accordingly.
Configuration Details
Name: Display name in the frontend
Identifier: Unique identifier for invocation
Hidden: Whether to display in the notification configuration of alert rules
Enabled: Whether this notification channel is enabled
Note: If not enabled, it will not be displayed in the alert rule configuration by default.
Use Cases
User-created notification channels and contact methods are primarily used in custom notification scripts. Below is an example of script invocation, which you can refer to when integrating with your internal communication tools.
The system will encode the content of the alert event as JSON and pass it to the notification script via stdin. Here’s a sample script:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import sys
import json
import urllib2
reload(sys)
sys.setdefaultencoding('utf8') # Set default encoding to utf-8
class Sender(object):
@classmethod
# The method send_newtalk, where newtalk should match the configured notification channel
def send_newtalk(cls, payload):
try:
#print("Starting send_newtalk".encode('utf-8'))
# Get event data from payload
event = payload.get('event')
# Get notified user objects
users = event.get("notify_users_obj")
# Get alert rule name
rule_name = event.get("rule_name")
# Default event state is "Triggered"
event_state = "Triggered"
# If the event has recovered, state is "Recovered"
if event.get("is_recovered"):
event_state = "Recovered"
# Store Dingtalk robot tokens and user phones
tokens = {}
phones = {}
#print("Extracting user information".encode('utf-8'))
# Iterate through users, collecting phones and Dingtalk tokens
for u in users:
if u.get("phone"):
phones[u.get("phone")] = 1
contacts = u.get("contacts")
# dingtalk_robot_token, replace with the corresponding name as needed,
# set the name in Nightingale notification settings - contact methods, configure parameters in user settings
if contacts.get("dingtalk_robot_token", ""):
tokens[contacts.get("dingtalk_robot_token", "")] = 1
# Set request headers
headers = {
"Content-Type": "application/json;charset=utf-8"
}
#print("Tokens: {}".format(tokens).encode('utf-8'))
#print("Phones: {}".format(phones).encode('utf-8'))
# Iterate through tokens, construct requests and send to Dingtalk
for t in tokens:
url = "https://oapi.dingtalk.com/robot/send?access_token={}".format(t)
body = {
"msgtype": "markdown",
"markdown": {
"title": "{} - {}".format(event_state, rule_name),
"text": "{} {}".format(payload.get('tpls').get("dingtalk.tpl", "dingtalk.tpl not found"), ' '.join(["@"+i for i in phones.keys()]))
},
"at": {
"atMobiles": list(phones.keys()),
"isAtAll": False
}
}
#print("Sending request to URL: {}".format(url).encode('utf-8'))
#print("Request body: {}".format(body).encode('utf-8'))
data = json.dumps(body)
req = urllib2.Request(url, data=data, headers=headers)
req.get_method = lambda: "POST"
response = urllib2.urlopen(req)
result = response.read()
#print("Response status code: {}".format(response.getcode()).encode('utf-8'))
#print("Response text: {}".format(result).encode('utf-8'))
# Catch all exceptions to prevent program crashes
except Exception as e:
#print("Error in send_newtalk: {}".format(e).encode('utf-8'))
def main():
try:
#print("Reading payload from stdin".encode('utf-8'))
payload = json.load(sys.stdin)
with open(".payload", 'w') as f:
f.write(json.dumps(payload, indent=4))
#print("Payload written to .payload file".encode('utf-8'))
for ch in payload.get('event').get('notify_channels'):
send_func_name = "send_{}".format(ch.strip())
#print("Processing channel: {}, function name: {}".format(ch, send_func_name).encode('utf-8'))
if not hasattr(Sender, send_func_name):
#print("Function {} not found".format(send_func_name).encode('utf-8'))
continue
send_func = getattr(Sender, send_func_name)
send_func(payload)
except Exception as e:
print("Error in main: {}".format(e).encode('utf-8'))
def hello():
print("hello nightingale".encode('utf-8'))
if __name__ == "__main__":
if len(sys.argv) == 1:
main()
elif sys.argv[1] == "hello":
hello()
else:
print("I am confused".encode('utf-8'))
The sample script contains many print statements for output, mainly for debugging purposes. If enabled, these can be viewed through n9e logs. Debug logs are in INFO.log, error states are in ERROR.log, filter for the keyword event_script_notify