├── 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 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
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 |
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("");
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("");
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 |
--------------------------------------------------------------------------------