├── config.php ├── README.md ├── index.php ├── functions.php └── json.php /config.php: -------------------------------------------------------------------------------- 1 | . 14 | ini_set('display_errors',1); 15 | ini_set('display_startup_errors',1); 16 | error_reporting(-1); 17 | 18 | $title = "Service Status Dashboard"; 19 | $organization = "My Company"; 20 | $support_url = "https://support.mycompany.org"; 21 | $json_url = "https://monitoring.mycompany.org/nagios.json"; 22 | $nagios_url = "https://monitoring.mycompany.org/nagios3/"; 23 | $extinfo_url = "https://monitoring.mycompany.org/cgi-bin/nagios3/extinfo.cgi"; 24 | 25 | # for a list of available themes: http://www.bootstrapcdn.com/bootswatch/ 26 | $dashboard_theme = "united"; 27 | 28 | ?> 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Simple Nagios Dashboard 2 | 3 | 4 | 5 | 6 | 7 | Simple Nagios Dashboard is a simple php based Nagios Dashboard. It is intended for a wall mounted monitor. It displays all host and service warnings. 8 | 9 | It requires that the Nagios status.dat file is available as JSON, it includes a module for that. 10 | 11 | Setup is very simple, only PHP 5 is required. No database or whatsoever. 12 | 13 | ### Installation 14 | 15 | - Extract code on Nagios Server 16 | - Edit `$statusFile` in `json.php` to point to the location of your nagios status.dat file 17 | - Install cronjob to generate JSON file: 18 | 19 | 20 | # /etc/cron.d/nagios-json 21 | * * * * * root /usr/bin/php5 /var/www/json.php > /var/www/nagios.json.tmp; cp /var/www/nagios.json.tmp /var/www/nagios.json 22 | 23 | 24 | - Extract code on webserver 25 | - Edit `config.php` and fill in your specific names and locations 26 | - ??? 27 | - Visit page in web browser and PROFIT!!! 28 | 29 | 30 | ### Credits 31 | 32 | - [PHP Nagios JSON by Christian Lizell](https://github.com/lizell/php-nagios-json) - GPLv3 33 | - [Job van der Voort](https://github.com/JobV), Design 34 | - Twitter Bootstrap 3 35 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | . 14 | require_once("./functions.php"); 15 | ?> 16 | 17 | 18 | 19 | 20 | <?php print($title . " - " . $organization); ?> 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 |
30 |

31 |
32 |
33 | 34 |
35 |
36 | " . $service_total . " Services
"); 39 | if($criticals_count > 0 || $host_issue_count > 0) { 40 | print('

'); 41 | #print(''); 42 | if($criticals_count > 0) { 43 | print(($criticals_count)); 44 | print(" Critical Issues. "); 45 | } 46 | if ($host_issue_count > 0) { 47 | print($host_issue_count . " Hosts Down!"); 48 | } 49 | print("

"); 50 | } elseif(($warnings_count) > 0) { 51 | print(($warnings_count)); 52 | print(" Non Critical Issues
"); 53 | } else { 54 | print('

'); 55 | print(" Everything Running Fine!

"); 56 | } 57 | ?> 58 |
59 |
60 | 61 |
62 |
63 | 68 |
69 |
70 | 75 |
76 |
77 | 79 |
80 |
81 |
82 |
83 | Simple Nagios Dashboard by Remy van Elst (code) and Job van der Voort (design). 84 |
85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /functions.php: -------------------------------------------------------------------------------- 1 | . 14 | require_once('./config.php'); 15 | 16 | function data_to_json($url) { 17 | $json = file_get_contents($url); 18 | $data = json_decode($json, true); 19 | return $data; 20 | } 21 | 22 | $data = data_to_json($json_url); 23 | 24 | if(empty($data)) { 25 | die("Dashboard ErrorJSON File $json_url could not be loadedi"); 26 | } 27 | 28 | $hosts = $data["hosts"]; 29 | $services = $data["services"]; 30 | $host = array(); 31 | foreach ($services as $key => $value) { 32 | $host["$key"] = $value; 33 | } 34 | 35 | function host_total($hosts) { 36 | $hosts_total = count($hosts); 37 | return $hosts_total; 38 | } 39 | 40 | function service_total($services) { 41 | $service_total = 0; 42 | $host = array(); 43 | foreach ($services as $key => $value) { 44 | $host["$key"] = $value; 45 | $service_total += count($value); 46 | } 47 | return $service_total; 48 | } 49 | 50 | function alert_services($host, $state, $ack, $not) { 51 | global $extinfo_url; 52 | $alert_json = array(); 53 | $alert_count = 0; 54 | foreach($host as $host_name => $services) { 55 | foreach($services as $service_name => $service_info) { 56 | if($service_info["current_state"] == $state && $service_info["problem_has_been_acknowledged"] == $ack && $service_info["notifications_enabled"] == $not) { 57 | $alert_json["$alert_count"]["service_name"] = $service_name; 58 | $alert_json["$alert_count"]["host_name"] = $host_name; 59 | $alert_json["$alert_count"]["plugin_output"] = $service_info["plugin_output"]; 60 | $alert_json["$alert_count"]["url"] = $extinfo_url . "?type=2&host=" . str_replace(" ", "+", $host_name) . "&service=" . str_replace(" ", "+", $service_name); 61 | $alert_count += 1; 62 | } 63 | } 64 | } 65 | return $alert_json; 66 | } 67 | 68 | function service_alert_cards($severety, $card_type, $counter, $card_data) { 69 | $c_count = 1; 70 | print("

" . $severety . "

"); 71 | if($counter == 0) { 72 | print("
"); 73 | print(str_repeat("   ", 2)); 74 | print("No " . $severety . "!"); 75 | print("
"); 76 | } else { 77 | foreach($card_data as $key => $card) { 78 | print("
"); 79 | print(""); 80 | print("#" . $c_count . " "); 81 | print("" . $card["service_name"] . ""); 82 | print(" on "); 83 | print("" . $card["host_name"] . " "); 84 | print(""); 85 | print("" . $card["plugin_output"] . "."); 86 | print("
"); 87 | $c_count += 1; 88 | } 89 | } 90 | } 91 | 92 | function host_issue_count($hosts, $state, $ack, $not) { 93 | $alert_count = 0; 94 | foreach($hosts as $key => $value) { 95 | if($value["current_state"] == $state && $value["problem_has_been_acknowledged"] == $ack && $value["notifications_enabled"] == $not) { 96 | $alert_count += 1; 97 | } 98 | } 99 | return $alert_count; 100 | } 101 | 102 | function alert_hosts($host, $state, $ack, $notif) { 103 | global $extinfo_url; 104 | $alert_json = array(); 105 | $alert_count = 0; 106 | foreach($host as $key => $value) { 107 | if($value["current_state"] == "$state" && $value["problem_has_been_acknowledged"] == "$ack" && $value["notifications_enabled"] == "$notif") { 108 | #print($key . " - " . $value["current_state"] . " - " . $value["problem_has_been_acknowledged"] . " - " . $value["notifications_enabled"] . "
"); 109 | $alert_json["$alert_count"]["host_name"] = $value["host_name"]; 110 | switch ($value["current_state"]) { 111 | case "1": 112 | $alert_json["$alert_count"]["current_state"] = "Down"; 113 | break; 114 | case "2": 115 | $alert_json["$alert_count"]["current_state"] = "Unknown"; 116 | break; 117 | default: 118 | $alert_json["$alert_count"]["current_state"] = "Unknown!"; 119 | break; 120 | } 121 | $alert_json["$alert_count"]["plugin_output"] = $value["plugin_output"]; 122 | $alert_json["$alert_count"]["url"] = $extinfo_url . "?type=1&host=" . str_replace(" ", "+", $value["host_name"]); 123 | $alert_count += 1; 124 | } 125 | } 126 | return $alert_json; 127 | } 128 | 129 | function host_alert_cards($severety, $card_type, $counter, $card_data) { 130 | $c_count = 1; 131 | print("

" . $severety . "

"); 132 | if($counter == 0) { 133 | print("
"); 134 | print(str_repeat("   ", 3)); 135 | print("No " . $severety . "!"); 136 | print("
"); 137 | } else { 138 | foreach($card_data as $key => $card) { 139 | print("
"); 140 | print(""); 141 | print("#" . $c_count . " "); 142 | print("" . $card["host_name"] . ""); 143 | print(" " . $card["plugin_output"] . "."); 144 | print("
"); 145 | $c_count += 1; 146 | } 147 | } 148 | } 149 | $hosts_total = host_total($hosts); 150 | $service_total = service_total($services); 151 | 152 | $host_issue_count = host_issue_count($hosts, 1, 0, 1); 153 | $host_issues = alert_hosts($hosts, 1, 0, 1); 154 | 155 | $host_ackn_issues = alert_hosts($hosts, 1, 1, 1); 156 | $host_not_issues = alert_hosts($hosts, 1, 0, 0); 157 | $host_ack_issues = array_merge($host_ackn_issues, $host_not_issues); 158 | $host_ack_issues_count = count($host_ack_issues); 159 | 160 | $warnings = alert_services($host, 1, 0, 1); 161 | $warnings_count = count($warnings); 162 | 163 | $warnings_ackn = alert_services($host, 1, 1, 1); 164 | $warnings_not = alert_services($host, 1, 0, 0); 165 | 166 | $warnings_ack_issues = array_merge($warnings_ackn, $warnings_not); 167 | $warnings_ack_count = count($warnings_ack_issues); 168 | 169 | 170 | $criticals = alert_services($host, 2, 0, 1); 171 | $criticals_count = count($criticals); 172 | 173 | $criticals_ackn = alert_services($host, 2, 1, 1); 174 | $criticals_not = alert_services($host, 2, 0, 0); 175 | 176 | $criticals_ack = array_merge($criticals_ackn, $criticals_not); 177 | $criticals_ack_count = count($criticals_ack); 178 | 179 | ?> 180 | -------------------------------------------------------------------------------- /json.php: -------------------------------------------------------------------------------- 1 | $val) { 59 | echo ' "' . jsonString($key) . '": "' . jsonString($val) . '"' . (isLast($program, $key) ? '' : ',') . "\n"; 60 | } 61 | unset($key, $val); 62 | echo ' },' . "\n"; 63 | } 64 | 65 | // hosts 66 | echo ' "hosts": {' . "\n"; 67 | foreach ($hosts as $hostName => $hostArray) { 68 | echo ' "' . jsonString($hostName) . '": {' . "\n"; 69 | foreach ($hostArray as $key => $val) { 70 | echo ' "' . jsonString($key) . '": "' . jsonString($val) . '"' . (isLast($hostArray, $key) ? '' : ',') . "\n"; 71 | } 72 | unset($key, $val); 73 | echo ' }' . (isLast($hosts, $hostName) ? '' : ',') . "\n"; 74 | } 75 | unset($hostName, $hostArray); 76 | echo ' },' . "\n"; 77 | 78 | // loop through the services 79 | echo ' "services": {' . "\n"; 80 | foreach ($services as $hostName => $service) { 81 | echo ' "' . jsonString($hostName) . '": {' . "\n"; 82 | foreach ($service as $serviceDesc => $serviceArray) { 83 | echo ' "' . jsonString($serviceDesc) . '": {' . "\n"; 84 | foreach ($serviceArray as $key => $val) { 85 | echo ' "' . jsonString($key) . '": "' . jsonString($val) . '"' . (isLast($serviceArray, $key) ? '' : ',') . "\n"; 86 | } 87 | unset($key, $val); 88 | echo ' }' . (isLast($service, $serviceDesc) ? '' : ',') . "\n"; 89 | } 90 | echo ' }' . (isLast($services, $hostName) ? '' : ',') . "\n"; 91 | unset($serviceDesc, $serviceArray); 92 | } 93 | unset($hostName, $service); 94 | echo ' }' . "\n"; 95 | echo "}"; 96 | } 97 | 98 | 99 | // Determines if the given key is last in the given array 100 | function isLast($array, $key) 101 | { 102 | end($array); 103 | return ($key === key($array)); 104 | } 105 | 106 | 107 | // replace reserved characters in json 108 | function jsonString($s) 109 | { 110 | $s = str_replace('\\', '\\\\', $s); 111 | $s = str_replace('"', '\"', $s); 112 | $s = str_replace("\t", '\t', $s); 113 | $s = str_replace("\n", " ", $s); 114 | $s = str_replace("\r", " ", $s); 115 | return $s; 116 | } 117 | 118 | 119 | // figure out what version the file is 120 | function getFileVersion($statusFile) 121 | { 122 | global $created_ts; 123 | $version = 2; 124 | 125 | $fh = fopen($statusFile, 'r'); 126 | $inInfo = false; 127 | while ($line = fgets($fh)) { 128 | if (trim($line) == "info {") { 129 | $inInfo = true; 130 | } elseif (trim($line) == "}") { 131 | $inInfo = false; 132 | break; 133 | } elseif ($inInfo) { 134 | $vals = explode("=", $line); 135 | if (trim($vals[0]) == "created") { 136 | $created = $vals[1]; 137 | } elseif (trim($vals[0]) == "version") { 138 | if (substr($vals[1], 0, 1) == "3") { 139 | $version = 3; 140 | } 141 | } 142 | } 143 | } 144 | return $version; 145 | } 146 | 147 | 148 | // parse nagios2 status.dat 149 | function getData2($statusFile) 150 | { 151 | // the keys to get from host status: 152 | $host_keys = array('host_name', 'has_been_checked', 'check_execution_time', 'check_latency', 'check_type', 'current_state', 'current_attempt', 'state_type', 'last_state_change', 'last_time_up', 'last_time_down', 'last_time_unreachable', 'last_notification', 'next_notification', 'no_more_notifications', 'current_notification_number', 'notifications_enabled', 'problem_has_been_acknowledged', 'acknowledgement_type', 'active_checks_enabled', 'passive_checks_enabled', 'last_update'); 153 | 154 | // keys to get from service status: 155 | $service_keys = array('host_name', 'service_description', 'has_been_checked', 'check_execution_time', 'check_latency', 'current_state', 'state_type', 'last_state_change', 'last_time_ok', 'last_time_warning', 'last_time_unknown', 'last_time_critical', 'plugin_output', 'last_check', 'notifications_enabled', 'active_checks_enabled', 'passive_checks_enabled', 'problem_has_been_acknowledged', 'acknowledgement_type', 'last_update', 'is_flapping'); 156 | 157 | # open the file 158 | $fh = fopen($statusFile, 'r'); 159 | 160 | # variables to keep state 161 | $inSection = false; 162 | $sectionType = ""; 163 | $lineNum = 0; 164 | $sectionData = array(); 165 | 166 | $hostStatus = array(); 167 | $serviceStatus = array(); 168 | 169 | #variables for total hosts and services 170 | $typeTotals = array(); 171 | 172 | # loop through the file 173 | while ($line = fgets($fh)) { 174 | $lineNum++; // increment counter of line number, mainly for debugging 175 | $line = trim($line); // strip whitespace 176 | if ($line == "") { 177 | continue; 178 | } // ignore blank line 179 | if (substr($line, 0, 1) == "#") { 180 | continue; 181 | } // ignore comment 182 | 183 | // ok, now we need to deal with the sections 184 | 185 | if (!$inSection) { 186 | // we're not currently in a section, but are looking to start one 187 | if (strstr($line, " ") && (substr($line, -1) == "{")) // space and ending with {, so it's a section header 188 | { 189 | $sectionType = substr($line, 0, strpos($line, " ")); // first word on line is type 190 | $inSection = true; 191 | // we're now in a section 192 | $sectionData = array(); 193 | 194 | // increment the counter for this sectionType 195 | if (isset($typeTotals[$sectionType])) { 196 | $typeTotals[$sectionType] = $typeTotals[$sectionType] + 1; 197 | } else { 198 | $typeTotals[$sectionType] = 1; 199 | } 200 | 201 | } 202 | } 203 | 204 | if ($inSection && $line == "}") // closing a section 205 | { 206 | if ($sectionType == "service") { 207 | $serviceStatus[$sectionData['host_name']][$sectionData['service_description']] = $sectionData; 208 | } 209 | if ($sectionType == "host") { 210 | $hostStatus[$sectionData["host_name"]] = $sectionData; 211 | } 212 | $inSection = false; 213 | $sectionType = ""; 214 | continue; 215 | } else { 216 | // we're currently in a section, and this line is part of it 217 | $lineKey = substr($line, 0, strpos($line, "=")); 218 | $lineVal = substr($line, strpos($line, "=") + 1); 219 | 220 | // add to the array as appropriate 221 | if ($sectionType == "service") { 222 | if (in_array($lineKey, $service_keys)) { 223 | $sectionData[$lineKey] = $lineVal; 224 | } 225 | } elseif ($sectionType == "host") { 226 | if (in_array($lineKey, $host_keys)) { 227 | $sectionData[$lineKey] = $lineVal; 228 | } 229 | } 230 | // else continue on, ignore this section, don't save anything 231 | } 232 | 233 | } 234 | 235 | fclose($fh); 236 | 237 | $retArray = array("hosts" => $hostStatus, "services" => $serviceStatus); 238 | 239 | return $retArray; 240 | } 241 | 242 | 243 | // parse nagios3 status.dat 244 | function getData3($statusFile) 245 | { 246 | global $debug; 247 | 248 | # open the file 249 | $fh = fopen($statusFile, 'r'); 250 | 251 | # variables to keep state 252 | $inSection = false; 253 | $sectionType = ""; 254 | $lineNum = 0; 255 | $sectionData = array(); 256 | 257 | $hostStatus = array(); 258 | $serviceStatus = array(); 259 | $programStatus = array(); 260 | 261 | #variables for total hosts and services 262 | $typeTotals = array(); 263 | 264 | # loop through the file 265 | while ($line = fgets($fh)) { 266 | $lineNum++; // increment counter of line number, mainly for debugging 267 | $line = trim($line); // strip whitespace 268 | if ($line == "") { 269 | continue; 270 | } // ignore blank line 271 | if (substr($line, 0, 1) == "#") { 272 | continue; 273 | } // ignore comment 274 | 275 | // ok, now we need to deal with the sections 276 | if (!$inSection) { 277 | // we're not currently in a section, but are looking to start one 278 | if (substr($line, strlen($line) - 1, 1) == "{") // space and ending with {, so it's a section header 279 | { 280 | $sectionType = substr($line, 0, strpos($line, " ")); // first word on line is type 281 | $inSection = true; 282 | // we're now in a section 283 | $sectionData = array(); 284 | 285 | // increment the counter for this sectionType 286 | if (isset($typeTotals[$sectionType])) { 287 | $typeTotals[$sectionType] = $typeTotals[$sectionType] + 1; 288 | } else { 289 | $typeTotals[$sectionType] = 1; 290 | } 291 | 292 | } 293 | } elseif ($inSection && trim($line) == "}") // closing a section 294 | { 295 | if ($sectionType == "servicestatus") { 296 | $serviceStatus[$sectionData['host_name']][$sectionData['service_description']] = $sectionData; 297 | } elseif ($sectionType == "hoststatus") { 298 | $hostStatus[$sectionData["host_name"]] = $sectionData; 299 | } elseif ($sectionType == "programstatus") { 300 | $programStatus = $sectionData; 301 | } 302 | $inSection = false; 303 | $sectionType = ""; 304 | continue; 305 | } else { 306 | // we're currently in a section, and this line is part of it 307 | $lineKey = substr($line, 0, strpos($line, "=")); 308 | $lineVal = substr($line, strpos($line, "=") + 1); 309 | 310 | // add to the array as appropriate 311 | if ($sectionType == "servicestatus" || $sectionType == "hoststatus" || $sectionType == "programstatus") { 312 | if ($debug) { 313 | echo "LINE " . $lineNum . ": lineKey=" . $lineKey . "= lineVal=" . $lineVal . "=\n"; 314 | } 315 | $sectionData[$lineKey] = $lineVal; 316 | } 317 | // else continue on, ignore this section, don't save anything 318 | } 319 | 320 | } 321 | 322 | fclose($fh); 323 | 324 | $retArray = array("hosts" => $hostStatus, "services" => $serviceStatus, "program" => $programStatus); 325 | return $retArray; 326 | } 327 | 328 | 329 | // this formats the age of a check in seconds into a nice textual description 330 | function ageString($seconds) 331 | { 332 | $age = ""; 333 | if ($seconds > 86400) { 334 | $days = (int)($seconds / 86400); 335 | $seconds = $seconds - ($days * 86400); 336 | $age .= $days . " days "; 337 | } 338 | if ($seconds > 3600) { 339 | $hours = (int)($seconds / 3600); 340 | $seconds = $seconds - ($hours * 3600); 341 | $age .= $hours . " hours "; 342 | } 343 | if ($seconds > 60) { 344 | $minutes = (int)($seconds / 60); 345 | $seconds = $seconds - ($minutes * 60); 346 | $age .= $minutes . " minutes "; 347 | } 348 | $age .= $seconds . " seconds "; 349 | return $age; 350 | } 351 | ?> 352 | 353 | --------------------------------------------------------------------------------