Webhook integrations are using custom JavaScript code to perform HTTP calls. This allows creating an integration with external systems such as messengers or ticket systems. To ensure that the webhook meets all the quality requirements, the following guidelines should be used.
The whole data validation process can be split into two parts: input data validation and external system response data validation.
While supported macro values are strictly defined, it is possible to assign a custom macro value during webhook testing. The webhook should implement user input validations to guide the user during all stages of using the webhook (including testing).
This includes the following validations:
All error messages from input data validations should contain information about the cause of the problem (for example, the fact that a value "bebebe" is not acceptable as an event value) and a potential solution (for example, a list of values that are acceptable for a specific field).
Please see the Error handling section for information on the proper error message format.
Same as with user input validations, the response data validation should ensure that responses from the external system are in the expected format.
This includes the following validations:
While some external services are promising to respond using only a single message format (for example, JSON), it is possible for users to misconfigure the webhook by providing invalid endpoints (in cases, when it is configurable). Users can also have an HTTP proxy between the Zabbix server and external services, which can give unexpected responses in some cases.
Webhooks use parameters to retrieve configuration and macro values. There could be no "full list of required macros", but the following macros are required for most of the webhooks:
Please note, that the value of the {ALERT.SENDTO} field is shown in the list of problems, so putting credentials in the "Send to" field will cause exposure of the credentials to other Zabbix users.
Additionally, the following macros can be used to implement additional logic or provide supplementary information:
All parameters that must be set or changed before using the webhook should have special value placeholders:
Example: a parameter defining an endpoint can have the value <PUT ENDPOINT HERE>
.
All webhooks should accept an additional optional parameter HTTPProxy
. This is required to provide an ability to set an HTTP proxy for requests sent from the Zabbix server. This parameter may have an empty value, which should be treated the same way as the absence of the parameter.
The following code can be used to set the proxy in the webhook code:
// "params" is an object holding parsed data from the "value" variable
if (typeof params.HTTPProxy === 'string' && params.HTTPProxy.trim() !== '') {
request.setProxy(params.HTTPProxy);
}
JavaScript code of the integration should comply with the JavaScript coding guidelines. The only exception from guidelines is that 4 (four) spaces should be used for indents instead of the tabs. The webhook code should be implemented as three logical parts:
var Jira = {
request: function (method, query, data) {
// ...
},
createIssue: function(summary, description, fields) {
// ...
},
updateIssue: function(summary, fields) {
// ...
},
// ...
};
For simple integrations, class implementation can be omitted.
// ...
if ([0, 1, 2, 3].indexOf(parseInt(params.event_source)) === -1) {
throw 'Incorrect value "' + params.event_source + '" for "event_source" field. Must be 0-3.';
}
// Check {EVENT.VALUE} for trigger-based and internal events.
if (params.event_value !== '0' && params.event_value !== '1'
&& (params.event_source === '0' || params.event_source === '3')) {
throw 'Incorrect value "' + params.event_value + '" for "event_value" field. Must be 0 or 1.';
}
// ...
// ...
if (params.event_source !== '0' && params.event_recovery_value !== '0') {
Jira.createIssue(params.alert_subject, params.alert_message);
}
// ...
Please note, that the input data validation block and webhook logic share the same try/catch block to properly format errors.
try {
// Validation block.
// Webhook logic block.
}
catch (error) {
Zabbix.Log(4, '[ Jira Webhook ] ERROR: ' + error);
throw 'Sending failed: ' + error;
}
Tags are used to store event data (for trigger-based events only). A webhook using tags to store ticket IDs, links, or any other info received from the external system, should store this information as event tags. The following rules should be taken into account when creating tag names:
While there are no requirements to return specific values, one of the following approaches should be used when defining a webhook's response:
If a webhook doesn't use tags: it is recommended to return a generic string (for example, OK
) to signify that the execution was successful.
If a webhook uses tags (the Process tags checkbox is marked): the webhook should always return a JSON object containing at least an empty object for tags:{tags: {}}
.
If the webhook is working with the ticket-based system and wants to store a ticket ID in the event tags, it should still return empty tags for update/recovery operations. This is the only way to make sure that the Zabbix server will not produce errors when parsing webhook result and that there will be no overhead on parsing existing tags when this is not needed. Please note that JSON should be returned as a string and not as an object as the Zabbix server is converting objects to [Object object]
string.
The webhooks should perform error handling in all cases, including:
Error messages must meet the requirements listed below.
Error messages should:
Webhooks should use logging capabilities provided by Zabbix to store debug information for users. The following logging requirements should be met:
This can be used to find out the cause of the errors in webhook logic. Simple logging of requests sent and responses received is considered the best practice.
Example:
// ...
Zabbix.Log(4, '[ Custom Webhook ] Sending request: ' + url + ((typeof data === 'string')
? ('\n' + data)
: ''));
switch (method) {
case 'get':
response = request.Get(url, data);
break;
case 'post':
response = request.Post(url, data);
break;
case 'put':
response = request.Put(url, data);
break;
default:
throw 'Unsupported HTTP request method: ' + method;
}
Zabbix.Log(4, '[ Custom Webhook ] Received response with status code ' +
request.Status() + '\n' + response);
// ...
Exceptions can be made when it is required to keep track of failed or executed webhooks on higher levels. For most webhooks, there is no need to create log entries on higher levels as the Zabbix server will log failed webhooks on the "Warning" (3) level automatically.
For example, a webhook called "Bebebe" should use the prefix "[Bebebe Webhook]" for all of the log entries. This is done to ensure that log entries created by webhook are distinguishable from the other log entries in the Zabbix Server log file.
Only the steps where significant actions have been performed (e.g. external requests), should be logged.
The last (but not the least) step of creating a good integration is to create a Readme file containing the following information:
To avoid creating duplicate integrations, make sure that a webhook doesn't already exist in Zabbix. Existing webhooks are available in Zabbix Git repository