v2.11 - Improved error handling and ability to pick random problem via Zabbix for testing

This commit is contained in:
Mark Oudsen 2023-07-01 13:26:29 +02:00
parent 9c42ee4b89
commit 32b8582757
4 changed files with 281 additions and 205 deletions

View File

@ -1,10 +1,12 @@
## mailGraph v2.10 release ## ## mailGraph v2.11 release ##
_(2023/06/30)_ _(2023/07/01)_
_This version has been verified with Zabbix 5.4, 6.0 LTS and 6.4._ _This version has been verified with Zabbix 5.4 and 6.0 LTS and is expected to work with 6.4 and later (based on v2.10 testing)_
Minor updates to the mailGraph code Release notes
- When not defining zabbix_api_user and zabbix_api_pwd in the configuration file the zbx_user and zbx_user_pwd wll be used - Added pre- and postchecking of variables to the Zabbix javascript - this will prevent the 'invalid JSON' messages and provide better feedback for errors
- When testing MailGraph it is now possible to set the eventId to zero - a random problem will be picked up via the API
- Zabbix Media Type XML reverted back to version 5.4 (for backwards compatibility)
Modified files Modified files
- mailGraph.php - mailGraph.php
@ -18,6 +20,14 @@ For those upgrading to the latest release without installing the media type:
Changes are in effect immediately, no need to restart any services. Changes are in effect immediately, no need to restart any services.
## mailGraph v2.10 release ##
_(2023/06/30)_
_This version has been verified with Zabbix 5.4, 6.0 LTS and 6.4._
Minor updates to the mailGraph code
- When not defining zabbix_api_user and zabbix_api_pwd in the configuration file the zbx_user and zbx_user_pwd wll be used
## Zabbix 6.4.x testing ## ## Zabbix 6.4.x testing ##
_(2023/06/30)_ _(2023/06/30)_

View File

@ -1,3 +1,4 @@
// mailGraph v2.11
try { try {
// Pickup parameters // Pickup parameters
params = JSON.parse(value), params = JSON.parse(value),
@ -16,11 +17,23 @@ try {
req.addHeader('Content-Type: application/json'); req.addHeader('Content-Type: application/json');
// Must have fields // Must have fields
fields.itemId = params.itemId; fields.itemId = params.itemId * 1;
fields.eventId = params.eventId; fields.eventId = params.eventId * 1;
fields.recipient = params.recipient; fields.recipient = params.recipient;
fields.baseURL = params.baseURL; fields.baseURL = params.baseURL;
fields.duration = params.duration; fields.duration = params.duration * 1;
if (isNaN(fields.eventId)) {
throw '[MailGraph Webhook] Invalid event ID? Integer required (use actual event ID from Zabbix!)';
}
if (isNaN(fields.duration)) {
throw '[MailGraph Webhook] Invalid duration? Integer required (set to zero if unknown)!';
}
if (fields.recipient.charAt(0) == '{') {
throw '[MailGraph Webhook] Please define recipient for the test message!';
}
// Optional fields // Optional fields
if (typeof params.graphWidth === 'string') { fields.graphWidth = params.graphWidth; } if (typeof params.graphWidth === 'string') { fields.graphWidth = params.graphWidth; }
@ -41,14 +54,26 @@ try {
// Post information to the processing script // Post information to the processing script
Zabbix.Log(4, '[MailGraph Webhook] Sending request: ' + params.URL + '?' + JSON.stringify(fields)); Zabbix.Log(4, '[MailGraph Webhook] Sending request: ' + params.URL + '?' + JSON.stringify(fields));
var resp = req.post(params.URL,JSON.stringify(fields)); var resp = req.post(params.URL,JSON.stringify(fields));
Zabbix.Log(4, '[Mailgraph Webhook] Receiving response:' + resp); Zabbix.Log(4, '[Mailgraph Webhook] Received response:' + resp);
// If there was an error, report it // If blank the email address is likely incorrect
if (resp==null) {
throw '[MailGraph Webhook] No data received from mailGraph! Likely the email processing failed? Check mailGraph logging';
}
// If there was an error, report it and stop
if (req.getStatus() != 200) { throw JSON.parse(resp).errors[0]; } if (req.getStatus() != 200) { throw JSON.parse(resp).errors[0]; }
// If no datas returned, report it and stop
if (resp.charAt(0) == "!") {
throw '[MailGraph Webhook] No data received from mailGraph! Likely the event ID provided does not exist? Check mailGraph logging';
}
// We expect the message id back from the processing script // We expect the message id back from the processing script
resp = JSON.parse(resp); msg = JSON.parse(resp);
result.tags.__message_id = resp.messageId;
result.tags.__message_id = msg.messageId;
Zabbix.Log(4, '[MailGraph Webhook] Message sent with identification "' + msg.messageId + '"');
// Pass the result back to Zabbix // Pass the result back to Zabbix
return JSON.stringify(result); return JSON.stringify(result);
@ -56,6 +81,6 @@ try {
catch (error) catch (error)
{ {
// In case something went wrong in the processing, pass the error back to Zabbix // In case something went wrong in the processing, pass the error back to Zabbix
Zabbix.Log(127, 'MailGraph notification failed : '+error); Zabbix.Log(127, 'MailGraph notification failed: '+error);
throw 'MailGraph notification failed : '+error; throw 'MailGraph notification failed : '+error;
} }

View File

@ -49,6 +49,8 @@
// 2.01 2021/12/16 - Mark Oudsen - Screens are no longer available - reverting to using Dashboards now // 2.01 2021/12/16 - Mark Oudsen - Screens are no longer available - reverting to using Dashboards now
// 2.02 2022/01/30 - Mark Oudsen - Added cleanup routine for old logs and images // 2.02 2022/01/30 - Mark Oudsen - Added cleanup routine for old logs and images
// 2.10 2023/06/30 - Mark Oudsen - Refactored deprecated code - now compatible with Zabbix 6.0 LTS, 6.4 // 2.10 2023/06/30 - Mark Oudsen - Refactored deprecated code - now compatible with Zabbix 6.0 LTS, 6.4
// 2.11 2023/07/01 - Mark Oudsen - Refactored Zabbix javascript - now capturing obvious errors
// Added ability to locate latest problems for testing purposes
// ------------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------------
// //
// (C) M.J.Oudsen, mark.oudsen@puzzl.nl // (C) M.J.Oudsen, mark.oudsen@puzzl.nl
@ -70,7 +72,7 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////
// CONSTANTS // CONSTANTS
$cVersion = 'v2.10'; $cVersion = 'v2.11';
$cCRLF = chr(10).chr(13); $cCRLF = chr(10).chr(13);
$maskDateTime = 'Y-m-d H:i:s'; $maskDateTime = 'Y-m-d H:i:s';
$maxGraphs = 4; $maxGraphs = 4;
@ -663,6 +665,31 @@
_log('> Token = '.$token); _log('> Token = '.$token);
// -----------------------------------
// --- IF NO EVENT ID FETCH LATEST ---
// -----------------------------------
if ($p_eventId=="0")
{
_log('# No event ID given, picking up random event from Zabbix');
$request = array('jsonrpc'=>'2.0',
'method'=>'problem.get',
'params'=>array('output'=>'extend',
'recent'=>'true',
'limit'=>1),
'auth'=>$token,
'id'=>nextRequestID());
$thisProblems = postJSON($z_url_api, $request);
_log('> Problem data'.$cCRLF.json_encode($thisProblems,JSON_PRETTY_PRINT|JSON_NUMERIC_CHECK));
if (!isset($thisProblems['result'][0])) { echo '! No response data received?'.$cCRLF; die; }
$p_eventId = $thisProblems['result'][0]['eventid'];
_log('> Picked up random last event #'.$p_eventId);
}
// ------------------------------ // ------------------------------
// --- READ EVENT INFORMATION --- // --- READ EVENT INFORMATION ---
// ------------------------------ // ------------------------------
@ -1440,8 +1467,15 @@
// Return Event TAG information for Zabbix // Return Event TAG information for Zabbix
$response = array('messageId.mailGraph'=>$messageId); $response = array('messageId'=>$messageId);
echo json_encode($response).$cCRLF;
if ($response=="")
{
_log("! Failed to send mail message");
echo "! Failed to send mail message. Likely an issue with the recipient email address?".$cCRLF;
} else {
echo json_encode($response).$cCRLF;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////
// Wrap up ////////////////////////////////////////////////////////////////////////////////////////////// // Wrap up //////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -1,191 +1,198 @@
<?xml version="1.0" encoding="UTF-8"?> zabbix_export:
<zabbix_export> version: '5.4'
<version>6.0</version> date: '2023-07-01T10:54:39Z'
<date>2023-06-29T23:22:52Z</date> media_types:
<media_types> -
<media_type> name: MailGraph
<name>MailGraph</name> type: WEBHOOK
<type>WEBHOOK</type> parameters:
<parameters> -
<parameter> name: baseURL
<name>baseURL</name> value: 'https://myzabbix.example.com/'
<value>https://mydomain.com/zabbix/</value> -
</parameter> name: duration
<parameter> value: '{EVENT.DURATION}'
<name>duration</name> -
<value>{EVENT.DURATION}</value> name: eventId
</parameter> value: '{EVENT.ID}'
<parameter> -
<name>eventId</name> name: graphHeight
<value>{EVENT.ID}</value> value: '120'
</parameter> -
<parameter> name: graphWidth
<name>graphHeight</name> value: '300'
<value>120</value> -
</parameter> name: HTTPProxy
<parameter> value: ''
<name>graphWidth</name> -
<value>300</value> name: infoTest
</parameter> value: Test
<parameter> -
<name>HTTPProxy</name> name: itemId
<value/> value: '{ITEM.ID}'
</parameter> -
<parameter> name: periods
<name>infoTest</name> value: '10m,4h,1d,7d'
<value>Test</value> -
</parameter> name: periods_headers
<parameter> value: 'Last 10 minutes,Last 4 hours,Last day,Last 7 days'
<name>itemId</name> -
<value>{ITEM.ID}</value> name: recipient
</parameter> value: '{ALERT.SENDTO}'
<parameter> -
<name>periods</name> name: showLegend
<value>10m,4h,1d,7d</value> value: '0'
</parameter> -
<parameter> name: subject
<name>periods_headers</name> value: '{{ HOST_NAME|raw }}: ({{ EVENT_SEVERITY }}) {{ EVENT_NAME|raw }}'
<value>Last 10 minutes,Last 4 hours,Last day,Last 7 days</value> -
</parameter> name: URL
<parameter> value: 'https://myzabbix.example.com/mailGraph.php'
<name>recipient</name> script: |
<value>{ALERT.SENDTO}</value> // mailGraph v2.11
</parameter> try {
<parameter> // Pickup parameters
<name>showLegend</name> params = JSON.parse(value),
<value>0</value> req = new HttpRequest(),
</parameter> fields = {},
<parameter> resp = '',
<name>subject</name> result = { tags: {} };
<value>{{ HOST_NAME|raw }}: ({{ EVENT_SEVERITY }}) {{ EVENT_NAME|raw }}</value>
</parameter> // Set HTTP proxy if required
<parameter> if (typeof params.HTTPProxy === 'string' && params.HTTPProxy.trim() !== '') {
<name>URL</name> req.setProxy(params.HTTPProxy);
<value>https://mydomain.com/mailGraph.php</value> fields.HTTPProxy = params.HTTPProxy;
</parameter> }
</parameters>
// Declare output type
<script>try { req.addHeader('Content-Type: application/json');
// Pickup parameters
params = JSON.parse(value), // Must have fields
req = new HttpRequest(), fields.itemId = params.itemId * 1;
fields = {}, fields.eventId = params.eventId * 1;
resp = '', fields.recipient = params.recipient;
result = { tags: {} }; fields.baseURL = params.baseURL;
fields.duration = params.duration * 1;
// Set HTTP proxy if required
if (typeof params.HTTPProxy === 'string' &amp;&amp; params.HTTPProxy.trim() !== '') { if (isNaN(fields.eventId)) {
req.setProxy(params.HTTPProxy); throw '[MailGraph Webhook] Invalid event ID? Integer required (use actual event ID from Zabbix!)';
fields.HTTPProxy = params.HTTPProxy; }
}
if (isNaN(fields.duration)) {
// Declare output type throw '[MailGraph Webhook] Invalid duration? Integer required (set to zero if unknown)!';
req.addHeader('Content-Type: application/json'); }
// Must have fields if (fields.recipient.charAt(0) == '{') {
fields.itemId = params.itemId; throw '[MailGraph Webhook] Please define recipient for the test message!';
fields.eventId = params.eventId; }
fields.recipient = params.recipient;
fields.baseURL = params.baseURL; // Optional fields
fields.duration = params.duration; if (typeof params.graphWidth === 'string') { fields.graphWidth = params.graphWidth; }
if (typeof params.graphHeight === 'string') { fields.graphHeight = params.graphHeight; }
// Optional fields if (typeof params.subject === 'string') { fields.subject = params.subject; }
if (typeof params.graphWidth === 'string') { fields.graphWidth = params.graphWidth; } if (typeof params.showLegend === 'string') { fields.showLegend = params.showLegend; }
if (typeof params.graphHeight === 'string') { fields.graphHeight = params.graphHeight; } if (typeof params.periods === 'string') { fields.periods = params.periods; }
if (typeof params.subject === 'string') { fields.subject = params.subject; } if (typeof params.periods_headers === 'string') { fields.periods_headers = params.periods_headers; }
if (typeof params.showLegend === 'string') { fields.showLegend = params.showLegend; } if (typeof params.debug === 'string') { fields.debug = params.debug; }
if (typeof params.periods === 'string') { fields.periods = params.periods; }
if (typeof params.periods_headers === 'string') { fields.periods_headers = params.periods_headers; } // Add generic fields
if (typeof params.debug === 'string') { fields.debug = params.debug; } Object.keys(params).forEach(function(key) {
if (key.substring(0, 4) == 'info') {
// Add generic fields fields[key] = params[key];
Object.keys(params).forEach(function(key) { }
if (key.substring(0, 4) == 'info') { });
fields[key] = params[key];
// Post information to the processing script
Zabbix.Log(4, '[MailGraph Webhook] Sending request: ' + params.URL + '?' + JSON.stringify(fields));
var resp = req.post(params.URL,JSON.stringify(fields));
Zabbix.Log(4, '[Mailgraph Webhook] Received response:' + resp);
// If blank the email address is likely incorrect
if (resp==null) {
throw '[MailGraph Webhook] No data received from mailGraph! Likely the email processing failed? Check mailGraph logging';
}
// If there was an error, report it and stop
if (req.getStatus() != 200) { throw JSON.parse(resp).errors[0]; }
// If no datas returned, report it and stop
if (resp.charAt(0) == "!") {
throw '[MailGraph Webhook] No data received from mailGraph! Likely the event ID provided does not exist? Check mailGraph logging';
}
// We expect the message id back from the processing script
msg = JSON.parse(resp);
result.tags.__message_id = msg.messageId;
Zabbix.Log(4, '[MailGraph Webhook] Message sent with identification "' + msg.messageId + '"');
// Pass the result back to Zabbix
return JSON.stringify(result);
} }
}); catch (error)
{
// In case something went wrong in the processing, pass the error back to Zabbix
Zabbix.Log(127, 'MailGraph notification failed: '+error);
throw 'MailGraph notification failed : '+error;
}
process_tags: 'YES'
description: |
The "URL" must point to the location of the processing script. If a proxy is required, define "HTTPProxy" for the proxy address.
Customization:
- "graphWidth" and "graphWidth" can be defined for the image size
- "showLegend" can be defined to show or hide the legend of the graph
- "subject" can be defined for a customized subject for the mail message
- "periods" and "periods_headers" can be defined for displaying multiple periods of the same graph, or
- "period" and "period_header" can be defined to display a single graph
The html.template and plain.template files can be adjusted (TWIG format).
More details are available at https://github.com/moudsen/mailGraph
message_templates:
-
event_source: TRIGGERS
operation_mode: PROBLEM
subject: 'Problem: {EVENT.NAME}'
message: |
Problem started at {EVENT.TIME} on {EVENT.DATE}
Problem name: {EVENT.NAME}
Host: {HOST.NAME}
Severity: {EVENT.SEVERITY}
Operational data: {EVENT.OPDATA}
Original problem ID: {EVENT.ID}
{TRIGGER.URL}
eventId: {EVENT.ID}
TriggerId: {TRIGGER.ID}
itemId: {ITEM.ID]
-
event_source: TRIGGERS
operation_mode: RECOVERY
subject: 'Resolved in {EVENT.DURATION}: {EVENT.RECOVERY.NAME}'
message: |
Problem has been resolved at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
Problem name: {EVENT.RECOVERY.NAME}
Problem duration: {EVENT.DURATION}
Host: {HOST.NAME}
Severity: {EVENT.SEVERITY}
Original problem ID: {EVENT.ID}
{TRIGGER.URL}
eventId: {EVENT.ID}
TriggerId: {TRIGGER.ID}
itemId: {ITEM.ID]
-
event_source: TRIGGERS
operation_mode: UPDATE
subject: 'Updated problem in {EVENT.AGE}: {EVENT.NAME}'
message: |
{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
{EVENT.UPDATE.MESSAGE}
Current problem status is {EVENT.STATUS}, age is {EVENT.AGE}, acknowledged: {EVENT.ACK.STATUS}.
eventId: {EVENT.ID}
TriggerId: {TRIGGER.ID}
itemId: {ITEM.ID]
// Post information to the processing script
Zabbix.Log(4, '[MailGraph Webhook] Sending request: ' + params.URL + '?' + JSON.stringify(fields));
var resp = req.post(params.URL,JSON.stringify(fields));
Zabbix.Log(4, '[Mailgraph Webhook] Receiving response:' + resp);
// If there was an error, report it
if (req.getStatus() != 200) { throw JSON.parse(resp).errors[0]; }
// We expect the message id back from the processing script
resp = JSON.parse(resp);
result.tags.__message_id = resp.messageId;
// Pass the result back to Zabbix
return JSON.stringify(result);
}
catch (error)
{
// In case something went wrong in the processing, pass the error back to Zabbix
Zabbix.Log(127, 'MailGraph notification failed : '+error);
throw 'MailGraph notification failed : '+error;
}</script>
<process_tags>YES</process_tags>
<description>The &quot;URL&quot; must point to the location of the processing script. If a proxy is required, define &quot;HTTPProxy&quot; for the proxy address.
Customization:
- &quot;graphWidth&quot; and &quot;graphWidth&quot; can be defined for the image size
- &quot;showLegend&quot; can be defined to show or hide the legend of the graph
- &quot;subject&quot; can be defined for a customized subject for the mail message
- &quot;periods&quot; and &quot;periods_headers&quot; can be defined for displaying multiple periods of the same graph, or
- &quot;period&quot; and &quot;period_header&quot; can be defined to display a single graph
The html.template and plain.template files can be adjusted (TWIG format).
More details are available at https://github.com/moudsen/mailGraph</description>
<message_templates>
<message_template>
<event_source>TRIGGERS</event_source>
<operation_mode>PROBLEM</operation_mode>
<subject>Problem: {EVENT.NAME}</subject>
<message>Problem started at {EVENT.TIME} on {EVENT.DATE}
Problem name: {EVENT.NAME}
Host: {HOST.NAME}
Severity: {EVENT.SEVERITY}
Operational data: {EVENT.OPDATA}
Original problem ID: {EVENT.ID}
{TRIGGER.URL}
eventId: {EVENT.ID}
TriggerId: {TRIGGER.ID}
itemId: {ITEM.ID]</message>
</message_template>
<message_template>
<event_source>TRIGGERS</event_source>
<operation_mode>RECOVERY</operation_mode>
<subject>Resolved in {EVENT.DURATION}: {EVENT.RECOVERY.NAME}</subject>
<message>Problem has been resolved at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
Problem name: {EVENT.RECOVERY.NAME}
Problem duration: {EVENT.DURATION}
Host: {HOST.NAME}
Severity: {EVENT.SEVERITY}
Original problem ID: {EVENT.ID}
{TRIGGER.URL}
eventId: {EVENT.ID}
TriggerId: {TRIGGER.ID}
itemId: {ITEM.ID]</message>
</message_template>
<message_template>
<event_source>TRIGGERS</event_source>
<operation_mode>UPDATE</operation_mode>
<subject>Updated problem in {EVENT.AGE}: {EVENT.NAME}</subject>
<message>{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
{EVENT.UPDATE.MESSAGE}
Current problem status is {EVENT.STATUS}, age is {EVENT.AGE}, acknowledged: {EVENT.ACK.STATUS}.
eventId: {EVENT.ID}
TriggerId: {TRIGGER.ID}
itemId: {ITEM.ID]</message>
</message_template>
</message_templates>
</media_type>
</media_types>
</zabbix_export>