From e7cd0fd8a23b0b3e46c53ff185fe194a09e6601d Mon Sep 17 00:00:00 2001 From: Mark Oudsen Date: Sat, 27 Feb 2021 13:40:40 +0100 Subject: [PATCH] Initial release version (v1.01) --- mailGraph.php | 703 +++++++++++++++++++++++++++++++++++++++ mailGraph.xml | 215 ++++++++++++ templates/html.template | 74 +++++ templates/plain.template | 29 ++ 4 files changed, 1021 insertions(+) create mode 100644 mailGraph.php create mode 100755 mailGraph.xml create mode 100644 templates/html.template create mode 100644 templates/plain.template diff --git a/mailGraph.php b/mailGraph.php new file mode 100644 index 0000000..4ee0bd8 --- /dev/null +++ b/mailGraph.php @@ -0,0 +1,703 @@ + POST data'.json_encode($data)); } + + $ch = curl_init(); + + // Set options + curl_setopt($ch, CURLOPT_USERAGENT, 'Zabbix-mailGraph - '.$cVersion); + + curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20); + + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json')); + curl_setopt($ch, CURLOPT_POST, TRUE); + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data,JSON_PRETTY_PRINT|JSON_NUMERIC_CHECK)); + + // Execute Curl + $data = curl_exec($ch); + + if ($data===FALSE) + { + _log('! Failed: '.curl_error($ch)); + + $data = 'An error occurred while retreiving the requested page.'.$cCRLF; + $data .= 'Requested page = '.$url.$cCRLF; + $data .= 'Error = '.curl_error($ch).$cCRLF; + } + else + { + _log('> Received '.strlen($data).' bytes'); + $data = json_decode($data,TRUE); + } + + // Close Curl + curl_close($ch); + + // Return received response + return $data; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + // Fetch the given Zabbix image + // --- Store with unique name + // --- Pass filename back to caller + + function GraphImageById ($graphid, $width = 400, $height = 100, $showLegend = 0) + { + global $z_server; + global $z_user; + global $z_pass; + global $z_tmp_cookies; + global $z_images_path; + global $z_url_api; + global $cVersion; + + // Unique names + $thisTime = time(); + + // Relative web calls + $z_url_index = $z_server ."index.php"; + $z_url_graph = $z_server ."chart2.php"; + $z_url_fetch = $z_url_graph ."?graphid=" .$graphid ."&width=" .$width ."&height=" .$height ."&legend=".$showLegend."&profileIdx=web.charts.filter"; + + // Prepare POST login + $z_login_data = array('name' => $z_user, 'password' => $z_pass, 'enter' => "Sign in"); + + // Cookie and image names + $filename_cookie = $z_tmp_cookies ."zabbix_cookie_" .$graphid . "." .$thisTime. ".txt"; + $filename = "zabbix_graph_" .$graphid . "." . $thisTime . ".png"; + $image_name = $z_images_path . $filename; + + // Configure CURL + _log('% GraphImageById: '.$z_url_fetch); + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_URL, $z_url_index); + curl_setopt($ch, CURLOPT_HEADER, false); + curl_setopt($ch, CURLOPT_USERAGENT, 'Zabbix-mailGraph - '.$cVersion); + + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $z_login_data); + + curl_setopt($ch, CURLOPT_COOKIEJAR, $filename_cookie); + curl_setopt($ch, CURLOPT_COOKIEFILE, $filename_cookie); + + // Login to Zabbix + curl_exec($ch); + + // Get the graph + curl_setopt($ch, CURLOPT_URL, $z_url_fetch); + $output = curl_exec($ch); + curl_close($ch); + + // Delete cookie + unlink($filename_cookie); + + // Write file + $fp = fopen($image_name, 'w'); + fwrite($fp, $output); + fclose($fp); + + // Return filename + _log('> Received '.strlen($output).' bytes'); + _log('> Saved to '.$z_images_path.$filename); + + return($filename); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + // Log information + + $logging = array(); + + function _log($information) + { + global $logging; + global $maskDateTime; + global $showLog; + global $cCRLF; + + $logString = date($maskDateTime).' : '.$information; + + $logging[] = $logString; + if ($showLog) { echo $logString.$cCRLF; } + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + // API request ID counter - for best practice / debug purposes only + + $requestCounter = 0; + + function nextRequestID() + { + global $requestCounter; + + $requestCounter++; + return($requestCounter); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + // Create easy to read duration + + function getNiceDuration($durationInSeconds) + { + $duration = ''; + + $days = floor($durationInSeconds / 86400); + $durationInSeconds -= $days * 86400; + $hours = floor($durationInSeconds / 3600); + $durationInSeconds -= $hours * 3600; + $minutes = floor($durationInSeconds / 60); + $seconds = $durationInSeconds - $minutes * 60; + + if ($days>0) + { + $duration .= $days . ' day'; + if ($days!=1) { $duration .= 's'; } + } + + if ($hours>0) + { + $duration .= ' ' . $hours . ' hr'; + if ($hours!=1) { $duration .= 's'; } + } + + if ($minutes>0) + { + $duration .= ' ' . $minutes . ' min'; + if ($minutes!=1) { $duration .= 's'; } + } + + if ($seconds>=0) { $duration .= ' ' . $seconds . ' sec'; } + if ($seconds!=1) { $duration .= 's'; } + + return $duration; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + // Initialize /////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + + $problemJSON = file_get_contents('php://input'); + $problemData = json_decode($problemJSON,TRUE); + + if (isset($argc)) + { + // [CONFIGURE] note: required only for debugging purpose, otherwise just leave as is + + if (($argc>1) && ($argv[1]=='test')) + { + // Insert the correct ids taken from an e-mail to provide debug capability via CLI + + $problemData['itemId'] = 0; + $problemData['triggerId'] = 0; + $problemData['eventId'] = 0; + $problemData['eventValue'] = 0; + $problemData['recipient'] = ''; + $problemData['baseURL'] = ''; + $problemData['duration'] = 10; + + // Switch on CLI log display + + $showLog = TRUE; + } + } + + if (!isset($problemData['itemId'])) { echo "Missing ITEM ID?\n"; die; } + $p_itemId = intval($problemData['itemId']); + + if (!isset($problemData['triggerId'])) { echo "Missing TRIGGER ID?\n"; die; } + $p_triggerId = intval($problemData['triggerId']); + + if (!isset($problemData['eventId'])) { echo "Missing EVENT ID?\n"; die; } + $p_eventId = intval($problemData['eventId']); + + if (!isset($problemData['recipient'])) { echo "Missing RECIPIENT?\n"; die; } + $p_recipient = $problemData['recipient']; + + if (!isset($problemData['eventValue'])) { echo "Missing EVENTVALUE?\n"; die; } + $p_eventValue = intval($problemData['eventValue']); + + if (!isset($problemData['duration'])) { echo "Missing DURATION?\n"; die; } + $p_duration = intval($problemData['duration']); + + if (!isset($problemData['baseURL'])) { echo "Missing URL?\n"; die; } + $p_URL = $problemData['baseURL']; + + $p_subject = '{{ EVENT_SEVERITY }}: {{ EVENT_NAME }}'; + if ((isset($problemData['subject'])) && ($problemData['subject']!='')) { $p_subject = $problemData['subject']; } + + $p_graphWidth = 450; + if (isset($problemData['graphWidth'])) { $p_graphWidth = intval($problemData['graphWidth']); } + + $p_graphHeight = 120; + if (isset($problemData['graphHeight'])) { $p_graphHeight = intval($problemData['graphHeight']); } + + $p_showLegend = 0; + if (isset($problemData['showLegend'])) { $p_showLegend = intval($problemData['showLegend']); } + + _log('# Data passed from Zabbix'.$cCRLF.json_encode($problemData,JSON_PRETTY_PRINT|JSON_NUMERIC_CHECK)); + + // --- CONFIGURATION --- + // [CONFIGURE] + + $z_url = ''; // Script URL location (for relative paths to images, templates, log, tmp) + $z_path = ''; // Absolute base path on the filesystem for this url + $z_url_image = $z_url.'images/'; // Images URL (included in plain message text) + + // Absolute path where to store the generated images - note: script does not take care of clearing out old images! + $z_images_path = $z_path.'/images/'; + $z_template_path = $z_path.'/templates/'; + $z_tmp_cookies = $z_path.'//tmp/'; + $z_log_path = $z_path.'/log/'; + + // Zabbix user (requires Super Admin access rights to access image generator script) + $z_user = 'graphreader'; + $z_pass = 'givemeastrongpassword'; + + // Zabbix API user (requires Super Admin access rights) + // TODO: Check if information retreival can be done with less rigths + $z_api_user = 'zabbixapi'; + $z_api_pass = 'givemeastrongpassword'; + + // Mail sender + $mailFrom = array('myemailname.noreply@mydomain.com'=>'Zabbix Mailgraph'); + + // Derived variables - do not change! + $z_server = $p_URL; // Zabbix server URL from config + $z_url_api = $z_server ."api_jsonrpc.php"; // Zabbix API URL + + // Check accessibility of paths and files + + if (!file_exists($z_images_path)) + { + echo 'Image path inaccessible?'.$cCRLF; + die; + } + + if (!file_exists($z_tmp_cookies)) + { + echo 'Image path inaccessible?'.$cCRLF; + die; + } + + if (!file_exists($z_log_path)) + { + echo 'Image path inaccessible?'.$cCRLF; + die; + } + + if (!file_exists($z_template_path.'html.template')) + { + echo 'INIT: HTML template missing?'.$cCRLF; + die; + } + + if (!file_exists($z_template_path.'plain.template')) + { + echo 'INIT: PLAIN template missing?'.$cCRLF; + die; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + // Fetch information via API //////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + + $mailData = array(); + $mailData['baseURL'] = $p_URL; + + // --- LOGIN --- + + _log('# LOGIN to Zabbix'); + + $request = array('jsonrpc'=>'2.0', + 'method'=>'user.login', + 'params'=>array('user'=>$z_api_user, + 'password'=>$z_api_pass), + 'id'=>nextRequestID(), + 'auth'=>null); + + $result = postJSON($z_url_api,$request); + + $token = ''; + if (isset($result['result'])) { $token = $result['result']; } + + if ($token=='') { echo 'Error logging in to Zabbix?'; die; } + + _log('> Token = '.$token); + + // --- GET TRIGGER INFO --- + + _log('# Retrieve TRIGGER information'); + + $request = array('jsonrpc'=>'2.0', + 'method'=>'trigger.get', + 'params'=>array('triggerids'=>$p_triggerId, + 'output'=>'extend', + 'selectFunctions'=>'extend'), + 'expandComment'=>1, + 'expandDescription'=>1, + 'expandExpression'=>1, + 'auth'=>$token, + 'id'=>nextRequestID()); + + $thisTrigger = postJSON($z_url_api,$request); + _log('> Trigger data'.$cCRLF.json_encode($thisTrigger,JSON_PRETTY_PRINT|JSON_NUMERIC_CHECK)); + + $mailData['TRIGGER_ID'] = $thisTrigger['result'][0]['triggerid']; + $mailData['TRIGGER_DESCRIPTION'] = $thisTrigger['result'][0]['description']; + $mailData['TRIGGER_COMMENTS'] = $thisTrigger['result'][0]['comments']; + + // --- GET ITEM INFO --- + + _log('# Retrieve ITEM information'); + + $itemId = $thisTrigger['result'][0]['functions'][0]['itemid']; + + $request = array('jsonrpc'=>'2.0', + 'method'=>'item.get', + 'params'=>array('itemids'=>$itemId, + 'output'=>'extend'), + 'auth'=>$token, + 'id'=>nextRequestID()); + + $thisItem = postJSON($z_url_api,$request); + _log('> Item data'.$cCRLF.json_encode($thisItem,JSON_PRETTY_PRINT|JSON_NUMERIC_CHECK)); + + $mailData['ITEM_ID'] = $thisItem['result'][0]['itemid']; + $mailData['ITEM_KEY'] = $thisItem['result'][0]['key_']; + $mailData['ITEM_NAME'] = $thisItem['result'][0]['name']; + $mailData['ITEM_DESCRIPTION'] = $thisItem['result'][0]['description']; + $mailData['ITEM_LASTVALUE'] = $thisItem['result'][0]['lastvalue']; + $mailData['ITEM_PREVIOUSVALUE'] = $thisItem['result'][0]['prevvalue']; + + // Catch elements that have a recordset definition returned as a value ... + if (substr($mailData['ITEM_LASTVALUE'],0,5)==''2.0', + 'method'=>'host.get', + 'params'=>array('hostids'=>$hostId, + 'output'=>'extend'), + 'auth'=>$token, + 'id'=>nextRequestID()); + + $thisHost = postJSON($z_url_api,$request); + _log('> Host data'.$cCRLF.json_encode($thisHost,JSON_PRETTY_PRINT|JSON_NUMERIC_CHECK)); + + $mailData['HOST_ID'] = $thisHost['result'][0]['hostid']; + $mailData['HOST_NAME'] = $thisHost['result'][0]['name']; + $mailData['HOST_ERROR'] = $thisHost['result'][0]['error']; + $mailData['HOST_DESCRIPTION'] = $thisHost['result'][0]['description']; + + // --- GET GRAPHS ASSOCIATED WITH THIS ITEM --- + + _log('# Retrieve associated graphs to this item'); + + $keyName = $thisItem['result'][0]['key_']; + $hostId = $thisItem['result'][0]['hostid']; + + // Look for graphs across all functions inside the item + $itemIds = array(); + + foreach($thisItem['result'][0]['functions'] as $aFunction) + { + $itemIds[] = $aFunction['itremid']; + } + + $request = array('jsonrpc'=>'2.0', + 'method'=>'graph.get', + 'params'=>array('itemids'=>implode(',',$itemIds), + 'hostids'=>$hostId, + 'output'=>'extend'), + 'auth'=>$token, + 'id'=>nextRequestID()); + + $thisGraph = postJSON($z_url_api,$request); + _log('> Graph data'.$cCRLF.json_encode($thisGraph,JSON_PRETTY_PRINT|JSON_NUMERIC_CHECK)); + + // --- FIND ASSOCIATED GRAPH ITEMS --- + + _log('# Retreiving associated graph items for the identified graphs'); + + $matchedGraphs = array(); + + foreach($thisGraph['result'] as $aGraph) + { + $request = array('jsonrpc'=>'2.0', + 'method'=>'graphitem.get', + 'params'=>array('graphids'=>$aGraph['graphid'], + 'output'=>'extend'), + 'auth'=>$token, + 'id'=>nextRequestID()); + + $thisGraphItems[$aGraph['graphid']] = postJSON($z_url_api,$request); + + foreach($thisGraphItems[$aGraph['graphid']]['result'] as $graphItem) + { + if ($graphItem['itemid']==$itemId) + { + $matchedGraphs[] = $aGraph; + _log('+ Graph item ### MATCH ###'.$cCRLF.json_encode($aGraph,JSON_PRETTY_PRINT|JSON_NUMERIC_CHECK)); + } + else + { + _log('- Graph item (nomatch)'.$cCRLF.json_encode($aGraph,JSON_PRETTY_PRINT|JSON_NUMERIC_CHECK)); + } + } + } + + _log('> Graphs found (matching) = '.sizeof($matchedGraphs)); + + // --- READ EVENT INFORMATION --- + + _log('# Retreiving EVENT information'); + + $request = array('jsonrpc'=>'2.0', + 'method'=>'event.get', + 'params'=>array('eventids'=>$p_eventId, + 'output'=>'extend'), + 'auth'=>$token, + 'id'=>nextRequestID()); + + $thisEvent = postJSON($z_url_api,$request); + _log('> Event data'.$cCRLF.json_encode($thisEvent,JSON_PRETTY_PRINT|JSON_NUMERIC_CHECK)); + + $mailData['EVENT_ID'] = $thisEvent['result'][0]['eventid']; + $mailData['EVENT_NAME'] = $thisEvent['result'][0]['name']; + $mailData['EVENT_OPDATA'] = $thisEvent['result'][0]['opdata']; + $mailData['EVENT_VALUE'] = $p_eventValue; + + switch($p_eventValue) + { + case 0: // Recovering + $mailData['EVENT_SEVERITY'] = 'Resolved'; + break; + + case 1: // Triggered/Active + $_severity = array('Not classified','Information','Warning','Average','High','Disaster'); + $mailData['EVENT_SEVERITY'] = $_severity[$thisEvent['result'][0]['severity']]; + break; + } + + $_status = array('Recovered','Triggered/Active'); + $mailData['EVENT_STATUS'] = $_status[$p_eventValue]; + + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + // Fetch Graph ////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + + $graphFile = ''; + $graphURL = ''; + + if (sizeof($matchedGraphs)>0) + { + // TODO: if multiple graphs, pick the first one or the one that is TAGGED with a mailGraph tag/value + + _log('# Adding graph #'.$matchedGraphs[0]['graphid']); + $graphFile = GraphImageById($matchedGraphs[0]['graphid'],$p_graphWidth,$p_graphHeight,$p_showLegend); + + _log('> Filename = '.$graphFile); + + $mailData['GRAPH_ID'] = $matchedGraphs[0]['graphid']; + $mailData['GRAPH_NAME'] = $matchedGraphs[0]['name']; + $mailData['GRAPH_URL'] = $z_url_image . $graphFile; + } + + // Prepare HTML LOG content + + $mailData['LOG_HTML'] = implode('
',$logging); + $mailData['LOG_HTML'] = str_replace($cCRLF,'
',$mailData['LOG_HTML']); + $mailData['LOG_HTML'] = str_replace('
','
'.$cCRLF,$mailData['LOG_HTML']); + + $mailData['LOG_HTML'] = ''.$cCRLF. + ''.$cCRLF. + $mailData['LOG_HTML'].$cCRLF. + ''.$cCRLF. + ''; + + // Prepare PLAIN LOG content + + $mailData['LOG_PLAIN'] = implode(chr(10),$logging); + + // Prepare others + + $mailData['TRIGGER_URL'] = $z_server.'/triggers.php?form=update&triggerid='.$mailData['TRIGGER_ID']; + $mailData['ITEM_URL'] = $z_server.'/items.php?form=update&hostid='.$mailData['HOST_ID'].'&itemid='.$mailData['ITEM_ID']; + $mailData['HOST_URL'] = $z_server.'/zabbix/hosts.php?form=update&hostid='.$mailData['HOST_ID']; + $mailData['EVENTDETAILS_URL'] = $z_server.'/tr_events.php?triggerid='.$mailData['TRIGGER_ID'].'&eventid='.$mailData['EVENT_ID'].'"'; + + $mailData['EVENT_DURATION'] = getNiceDuration($p_duration); + + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + // Compose & Send Message /////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + + _log('# Setting up mailer'); + + $transport = (new Swift_SmtpTransport('mail.puzzl.nl', 25)); + $mailer = new Swift_Mailer($transport); + + $message = (new Swift_Message()); + + // Fetch mailer ID from this message (no Swift function available for it ...) + // --- "Message-ID: <...id...@swift.generated>" + + $content = $message->toString(); + $lines = explode(chr(10),$content); + $firstLine = $lines[0]; + $idParts = explode(' ',$firstLine); + $messageId = substr($idParts[1],1,-2); + + _log('# Message ID = '.$messageId); + + // Build parts for HTML and PLAIN + + _log('# Processing templates'); + _log('+ '.$z_template_path.'html.template'); + _log('+ '.$z_template_path.'plain.template'); + + $loader = new \Twig\Loader\ArrayLoader([ + 'html' => file_get_contents($z_template_path.'html.template'), + 'plain' => file_get_contents($z_template_path.'plain.template'), + 'subject' => $p_subject, + ]); + + $twig = new \Twig\Environment($loader); + + if ($graphFile!='') + { + // Embed the image + $mailData['GRAPH_CID'] = $message->embed(Swift_Image::fromPath($z_images_path.$graphFile)); + _log('> Embedded graph image '.$z_images_path.$graphFile); + } + + $bodyHTML = $twig->render('html', $mailData); + $bodyPlain = $twig->render('plain', $mailData); + $mailSubject = $twig->render('subject', $mailData); + + // Prepare message + + $message->setSubject($thisEvent['result'][0]['name']) + ->setFrom($mailFrom) + ->setTo($p_recipient) + ->setBody($bodyHTML, 'text/html') + ->addPart($bodyPlain, 'text/plain'); + + if ($cDebugMail) + { + _log('# Attaching logs to mail message'); + + $attachLogHTML = new Swift_Attachment($mailData['LOG_HTML'], 'log.html', 'text/html'); + $message->attach($attachLogHTML); + + $attachLogPlain = new Swift_Attachment($mailData['LOG_PLAIN'], 'log.txt', '/text/plain'); + $message->attach($attachLogPlain); + } + + // Send message + + $result = $mailer->send($message); + + // Return TAG information + + $response = array('messageId'=>$messageId); + echo json_encode($response).$cCRLF; + + // Store log? + + if ($cDebug) + { + unset($mailData['LOG_HTML']); + unset($mailData['LOG_PLAIN']); + + $content = implode(chr(10),$logging).$cCRLF.$cCRLF.'=== MAILDATA ==='.$cCRLF.$cCRLF.json_encode($mailData,JSON_PRETTY_PRINT|JSON_NUMERIC_CHECK); + $content = str_replace(chr(13),'',$content); + + file_put_contents($z_log_path.'log.'.$p_eventId.'.dump',$content); + } +?> diff --git a/mailGraph.xml b/mailGraph.xml new file mode 100755 index 0000000..347e090 --- /dev/null +++ b/mailGraph.xml @@ -0,0 +1,215 @@ + + + 5.0 + 2021-02-27T12:14:57Z + + + MailGraph + WEBHOOK + + + baseURL + https://zbx.puzzl.nl/zabbix + + + duration + {EVENT.DURATION} + + + eventId + {EVENT.ID} + + + eventValue + {EVENT.VALUE} + + + graphHeight + 120 + + + graphWidth + 300 + + + HTTPProxy + + + + itemId + {ITEM.ID} + + + recipient + {ALERT.SENDTO} + + + showLegend + 0 + + + subject + {{ EVENT_SEVERITY }} --- {{ EVENT_NAME }} + + + triggerId + {TRIGGER.ID} + + + URL + https://zbx.puzzl.nl/mailGraph.php + + + + YES + 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 + +The html.template and plain.template files can be adjusted (TWIG format). + +Values available: +{{ baseURL }} - base url of the Zabbix system (use for references to API and login) +{{ TRIGGER_ID }} - id of the applicable trigger +{{ TRIGGER_DESCRIPTION }} - raw trigger description (note: macros are not parsed!) +{{ TRIGGER_COMMENTS }} - comments of the trigger +{{ TRIGGER_URL }} - url of the trigger form +{{ ITEM_ID }} - id of the associated item to the trigger +{{ ITEM_KEY }} - key of the item +{{ ITEM_NAME }} - item name +{{ ITEM_DESCRIPTION }} - description of the item +{{ ITEM_LASTVALUE }} - last value of the item +{{ ITEM_PREVIOUSVALUE }} - the value of the before LASTVALUE +{{ ITEM_URL }} - url of the item form +{{ HOST_ID }} - id of the associated host to the item +{{ HOST_NAME }} - name of the host +{{ HOST_ERROR }} - last error state of the applicable host +{{ HOST_DESCRIPTION }} - description of the host +{{ HOST_URL }} - url of the host form +{{ EVENT_ID }} - id of the associated event +{{ EVENT_NAME }} - name of the event (note: macros are parsed!) +{{ EVENT_OPDATA }} - associated operational data of the vent +{{ EVENT_VALUE }} - event state (0=Recovered, 1=Triggered/Active) +{{ EVENT_SEVERITY }} - severity of the event +{{ EVENT_STATUS }} - status of the event +{{ EVENT_URL }} - url of the event details +{{ GRAPH_ID }} - id of the (first) associated graph that contains the item +{{ GRAPH_NAME }} - name of this graph +{{ GRAPH_URL }} - URL to this graph (assuming script produces to an accessible location) +{{ GRAPH_CID }} - IMG embed string (<img src="{{ GRAPH_CID }}" />) +{{ LOG_HTML }} - script log in HTML format +{{ LOG_PLAIN }} - script log in PLAIN text format + + + TRIGGERS + PROBLEM + Problem: {EVENT.NAME} + 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} + + + TRIGGERS + RECOVERY + Resolved in {EVENT.DURATION}: {EVENT.NAME} + Problem has been resolved at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE} +Problem name: {EVENT.NAME} +Problem duration: {EVENT.DURATION} +Host: {HOST.NAME} +Severity: {EVENT.SEVERITY} +Original problem ID: {EVENT.ID} +{TRIGGER.URL} + + + TRIGGERS + UPDATE + Updated problem in {EVENT.AGE}: {EVENT.NAME} + {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}. + + + DISCOVERY + PROBLEM + Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS} + Discovery rule: {DISCOVERY.RULE.NAME} + +Device IP: {DISCOVERY.DEVICE.IPADDRESS} +Device DNS: {DISCOVERY.DEVICE.DNS} +Device status: {DISCOVERY.DEVICE.STATUS} +Device uptime: {DISCOVERY.DEVICE.UPTIME} + +Device service name: {DISCOVERY.SERVICE.NAME} +Device service port: {DISCOVERY.SERVICE.PORT} +Device service status: {DISCOVERY.SERVICE.STATUS} +Device service uptime: {DISCOVERY.SERVICE.UPTIME} + + + AUTOREGISTRATION + PROBLEM + Autoregistration: {HOST.HOST} + Host name: {HOST.HOST} +Host IP: {HOST.IP} +Agent port: {HOST.PORT} + + + + + diff --git a/templates/html.template b/templates/html.template new file mode 100644 index 0000000..5dd42f3 --- /dev/null +++ b/templates/html.template @@ -0,0 +1,74 @@ + + + + + + + + +{% if GRAPH_CID|length > 0 %} + + + +{% endif %} +
+ + +
+

EVENT INFORMATION

+ Description: {{ EVENT_NAME }}
+ Host: {{ HOST_NAME }} +{% if HOST_ERROR|length > 0 %} + ({{ HOST_ERROR }}) +{% endif %} +
+ Operational data: {{ EVENT_OPDATA }}
+ Status: {{ EVENT_STATUS }}
+ Severity: {{ EVENT_SEVERITY }}
+{% if EVENT_SEVERITY == "Resolved" %} + Duration: {{ EVENT_DURATION }}
+{% endif %} + Item: {{ ITEM_NAME }} ({{ ITEM_KEY }})
+ Previous/Last: {{ ITEM_PREVIOUSVALUE }} ==> {{ ITEM_LASTVALUE }} +

Event Details

+
+
+

+ Event ID: {{ EVENT_ID }} // + Trigger ID: {{ TRIGGER_ID }} // + Item ID: {{ ITEM_ID }} // + Host ID: {{ HOST_ID }} +

+ + \ No newline at end of file diff --git a/templates/plain.template b/templates/plain.template new file mode 100644 index 0000000..15e8d36 --- /dev/null +++ b/templates/plain.template @@ -0,0 +1,29 @@ +EVENT INFORMATION #{{ EVENT_ID }} + +Severity: {{ EVENT_SEVERITY }} +Description: {{ EVENT_NAME }} + +{% if GRAPH_CID|length > 0 %} +GRAPH #{{ GRAPH_ID }} +{{ GRAPH_URL }} +This graph will remain available for approx. the next 2 weeks only; use HTML reader after this period to view the graph. +{% endif %} + +TRIGGER #{{ TRIGGER_ID }} + +Operational data: {{ EVENT_OPDATA }} +Status: {{ EVENT_STATUS }} +Description: {{ TRIGGER_DESCRIPTION }} + +ITEM #{{ ITEM_ID }} + +Name: {{ ITEM_NAME }} +Key: {{ ITEM_KEY }} +Value: {{ ITEM_LASTVALUE }} + +HOST + +Name: {{ HOST_NAME }} + +EVENT DETAILS +{{ baseURL }}/tr_events.php?triggerid={TRIGGER_ID}&eventid={EVENT_ID} \ No newline at end of file