1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2<html xmlns="http://www.w3.org/1999/xhtml"> 3<!-- 4 $Id$ 5 (c) 2011 Jerome Loyet 6 The PHP License, version 3.01 7 This is sample real-time status page for FPM. You can change it to better fit your needs. 8--> 9 <head> 10 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> 11 <style type="text/css"> 12 body {background-color: #ffffff; color: #000000;} 13 body, td, th, h1, h2 {font-family: sans-serif;} 14 pre {margin: 0px; font-family: monospace;} 15 a:link {color: #000099; text-decoration: none; background-color: #ffffff;} 16 a:hover {text-decoration: underline;} 17 table {border-collapse: collapse;} 18 .center {text-align: center;} 19 .center table { margin-left: auto; margin-right: auto; text-align: left;} 20 .center th { text-align: center !important; } 21 td, th { border: 1px solid #000000; font-size: 75%; vertical-align: baseline;} 22 h1 {font-size: 150%;} 23 h2 {font-size: 125%;} 24 .p {text-align: left;} 25 .e {background-color: #ccccff; font-weight: bold; color: #000000;} 26 .h {background-color: #9999cc; font-weight: bold; color: #000000;} 27 28 .v {background-color: #cccccc; color: #000000;} 29 .w {background-color: #ccccff; color: #000000;} 30 31 .h th { 32 cursor: pointer; 33 } 34 img {float: right; border: 0px;} 35 hr {width: 600px; background-color: #cccccc; border: 0px; height: 1px; color: #000000;} 36 </style> 37 <title>PHP-FPM status page</title> 38 <meta name="ROBOTS" content="NOINDEX,NOFOLLOW,NOARCHIVE" /></head> 39 <body> 40 <div class="center"> 41 <table border="0" cellpadding="3" width="95%"> 42 <tr class="h"> 43 <td> 44 <a href="http://www.php.net/"><img border="0" src="https://static.php.net/www.php.net/images/php.gif" alt="PHP Logo" /></a><h1 class="p">PHP-FPM real-time status page</h1> 45 </td> 46 </tr> 47 </table> 48 <br /> 49 <table border="0" cellpadding="3" width="95%"> 50 <tr><td class="e">Status URL</td><td class="v"><input type="text" id="url" size="45" /></td></tr> 51 <tr><td class="e">Ajax status</td><td class="v" id="status"></td></tr> 52 <tr><td class="e">Refresh Rate</td><td class="v"><input type="text" id="rate" value="1" /></td></tr> 53 <tr> 54 <td class="e">Actions</td> 55 <td class="v"> 56 <button onclick="javascript:refresh();">Manual Refresh</button> 57 <button id="play" onclick="javascript:playpause();">Play</button> 58 </td> 59 </tr> 60 </table> 61 <h1>Pool Status</h1> 62 <table border="0" cellpadding="3" width="95%" id="short"> 63 <tr style="display: none;"><td> </td></tr> 64 </table> 65 <h1>Active Processes status</h1> 66 <table border="0" cellpadding="3" width="95%" id="active"> 67 <tr class="h"><th>PID↓</th><th>Start Time</th><th>Start Since</th><th>Requests Served</th><th>Request Duration</th><th>Request method</th><th>Request URI</th><th>Content Length</th><th>User</th><th>Script</th></tr> 68 </table> 69 <h1>Idle Processes status</h1> 70 <table border="0" cellpadding="3" width="95%" id="idle"> 71 <tr class="h"><th>PID↓</th><th>Start Time</th><th>Start Since</th><th>Requests Served</th><th>Request Duration</th><th>Request method</th><th>Request URI</th><th>Content Length</th><th>User</th><th>Script</th><th>Last Request %CPU</th><th>Last Request Memory</th></tr> 72 </table> 73 </div> 74 <p> 75 <a href="http://validator.w3.org/check?uri=referer"> 76 <img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0 Transitional" height="31" width="88" /> 77 </a> 78 </p> 79 <script type="text/javascript"> 80<!-- 81 var xhr_object = null; 82 var doc_url = document.getElementById("url"); 83 var doc_rate = document.getElementById("rate"); 84 var doc_status = document.getElementById("status"); 85 var doc_play = document.getElementById("play"); 86 var doc_short = document.getElementById("short"); 87 var doc_active = document.getElementById("active"); 88 var doc_idle = document.getElementById("idle"); 89 var rate = 0; 90 var play=0; 91 var delay = 1000; 92 var order_active_index = 0; 93 var order_active_reverse = 0; 94 var order_idle_index = 0; 95 var order_idle_reverse = 0; 96 var sort_index; 97 var sort_order; 98 99 doc_url.value = location.protocol + '//' + location.host + "/status?json&full"; 100 101 ths = document.getElementsByTagName("th"); 102 for (var i=0; i<ths.length; i++) { 103 var th = ths[i]; 104 if (th.parentNode.className == "h") { 105 th.onclick = function() { order(this); return false; }; 106 } 107 } 108 109 xhr_object = create_ajax(); 110 111 function create_ajax() { 112 if (window.XMLHttpRequest) { 113 return new XMLHttpRequest(); 114 } 115 var names = [ 116 "Msxml2.XMLHTTP.6.0", 117 "Msxml2.XMLHTTP.3.0", 118 "Msxml2.XMLHTTP", 119 "Microsoft.XMLHTTP" 120 ]; 121 for(var i in names) 122 { 123 try { 124 return new ActiveXObject(names[i]); 125 } catch(e){} 126 } 127 alert("Browser not compatible ..."); 128 } 129 130 function order(cell) { 131 var table; 132 133 if (cell.constructor != HTMLTableCellElement && cell.constructor != HTMLTableHeaderCellElement) { 134 return; 135 } 136 137 table = cell.parentNode.parentNode.parentNode; 138 139 if (table == doc_active) { 140 if (order_active_index == cell.cellIndex) { 141 if (order_active_reverse == 0) { 142 cell.innerHTML = cell.innerHTML.replace(/.$/, "↑"); 143 order_active_reverse = 1; 144 } else { 145 cell.innerHTML = cell.innerHTML.replace(/.$/, "↓"); 146 order_active_reverse = 0; 147 } 148 } else { 149 var c = doc_active.rows[0].cells[order_active_index]; 150 c.innerHTML = c.innerHTML.replace(/.$/, ""); 151 cell.innerHTML = cell.innerHTML.replace(/$/, order_active_reverse == 0 ? "↓" : "↑"); 152 order_active_index = cell.cellIndex; 153 } 154 reorder(table, order_active_index, order_active_reverse); 155 return; 156 } 157 158 if (table == doc_idle) { 159 if (order_idle_index == cell.cellIndex) { 160 if (order_idle_reverse == 0) { 161 cell.innerHTML = cell.innerHTML.replace(/.$/, "↑"); 162 order_idle_reverse = 1; 163 } else { 164 cell.innerHTML = cell.innerHTML.replace(/.$/, "↓"); 165 order_idle_reverse = 0; 166 } 167 } else { 168 var c = doc_idle.rows[0].cells[order_idle_index]; 169 c.innerHTML = c.innerHTML.replace(/.$/, ""); 170 cell.innerHTML = cell.innerHTML.replace(/$/, order_idle_reverse == 0 ? "↓" : "↑"); 171 order_idle_index = cell.cellIndex; 172 } 173 reorder(table, order_idle_index, order_idle_reverse); 174 return; 175 } 176 } 177 178 function reorder(table, index, order) { 179 var rows = []; 180 while (table.rows.length > 1) { 181 rows.push(table.rows[1]); 182 table.deleteRow(1); 183 } 184 sort_index = index; 185 sort_order = order; 186 rows.sort(sort_table); 187 for (var i in rows) { 188 table.appendChild(rows[i]); 189 } 190 var odd = 1; 191 for (var i=1; i<table.rows.length; i++) { 192 table.rows[i].className = odd++ % 2 == 0 ? "v" : "w"; 193 } 194 return; 195 } 196 197 function sort_table(a, b) { 198 if (a.cells[0].tagName == "TH") return -1; 199 if (b.cells[0].tagName == "TH") return 1; 200 201 if (a.cells[sort_index].__search_t == 0) { /* integer */ 202 if (!sort_order) return a.cells[sort_index].__search_v - b.cells[sort_index].__search_v; 203 return b.cells[sort_index].__search_v - a.cells[sort_index].__search_v;; 204 } 205 206 /* string */ 207 if (!sort_order) return a.cells[sort_index].__search_v.localeCompare(b.cells[sort_index].__search_v); 208 else return b.cells[sort_index].__search_v.localeCompare(a.cells[sort_index].__search_v); 209 } 210 211 function playpause() { 212 rate = 0; 213 if (play) { 214 play = 0; 215 doc_play.innerHTML = "Play"; 216 doc_rate.disabled = false; 217 } else { 218 delay = parseInt(doc_rate.value); 219 if (!delay || delay < 1) { 220 doc_status.innerHTML = "Not valid 'refresh' value"; 221 return; 222 } 223 play = 1; 224 doc_rate.disabled = true; 225 doc_play.innerHTML = "Pause"; 226 setTimeout("callback()", delay * 1000); 227 } 228 } 229 230 function refresh() { 231 if (xhr_object == null) return; 232 if (xhr_object.readyState > 0 && xhr_object.readyState < 4) { 233 return; /* request is running */ 234 } 235 xhr_object.open("GET", doc_url.value, true); 236 xhr_object.onreadystatechange = function() { 237 switch(xhr_object.readyState) { 238 case 0: 239 doc_status.innerHTML = "uninitialized"; 240 break; 241 case 1: 242 doc_status.innerHTML = "loading ..."; 243 break; 244 case 2: 245 doc_status.innerHTML = "loaded"; 246 break; 247 case 3: 248 doc_status.innerHTML = "interactive"; 249 break; 250 case 4: 251 doc_status.innerHTML = "complete"; 252 if (xhr_object.status == 200) { 253 fpm_status(xhr_object.responseText); 254 } else { 255 doc_status.innerHTML = "Error " + xhr_object.status; 256 } 257 break; 258 } 259 } 260 xhr_object.send(); 261 } 262 263 function callback() { 264 if (!play) return; 265 refresh(); 266 setTimeout("callback()", delay * 1000); 267 } 268 269 function fpm_status(txt) { 270 var json = null; 271 272 while (doc_short.rows.length > 0) { 273 doc_short.deleteRow(0); 274 } 275 276 while (doc_active.rows.length > 1) { 277 doc_active.deleteRow(1); 278 } 279 280 while (doc_idle.rows.length > 1) { 281 doc_idle.deleteRow(1); 282 } 283 284 try { 285 json = JSON.parse(txt); 286 } catch (e) { 287 doc_status.innerHTML = "Error while parsing json: '" + e + "': <br /><pre>" + txt + "</pre>"; 288 return; 289 } 290 291 for (var key in json) { 292 if (key == "processes") continue; 293 if (key == "state") continue; 294 var row = doc_short.insertRow(doc_short.rows.length); 295 var value = json[key]; 296 if (key == "start time") { 297 value = new Date(value * 1000).toLocaleString(); 298 } 299 if (key == "start since") { 300 value = time_s(value); 301 } 302 var cell = row.insertCell(row.cells.length); 303 cell.className = "e"; 304 cell.innerHTML = key; 305 306 cell = row.insertCell(row.cells.length); 307 cell.className = "v"; 308 cell.innerHTML = value; 309 } 310 311 if (json.processes) { 312 process_full(json.processes, doc_active, "Idle", 0, 0); 313 reorder(doc_active, order_active_index, order_active_reverse); 314 315 process_full(json.processes, doc_idle, "Idle", 1, 1); 316 reorder(doc_idle, order_idle_index, order_idle_reverse); 317 } 318 } 319 320 function process_full(processes, table, state, equal, cpumem) { 321 var odd = 1; 322 323 for (var i in processes) { 324 var proc = processes[i]; 325 if ((equal && proc.state == state) || (!equal && proc.state != state)) { 326 var c = odd++ % 2 == 0 ? "v" : "w"; 327 var row = table.insertRow(-1); 328 row.className = c; 329 row.insertCell(-1).innerHTML = proc.pid; 330 row.cells[row.cells.length - 1].__search_v = proc.pid; 331 row.cells[row.cells.length - 1].__search_t = 0; 332 333 row.insertCell(-1).innerHTML = date(proc['start time'] * 1000);; 334 row.cells[row.cells.length - 1].__search_v = proc['start time']; 335 row.cells[row.cells.length - 1].__search_t = 0; 336 337 row.insertCell(-1).innerHTML = time_s(proc['start since']); 338 row.cells[row.cells.length - 1].__search_v = proc['start since']; 339 row.cells[row.cells.length - 1].__search_t = 0; 340 341 row.insertCell(-1).innerHTML = proc.requests; 342 row.cells[row.cells.length - 1].__search_v = proc.requests; 343 row.cells[row.cells.length - 1].__search_t = 0; 344 345 row.insertCell(-1).innerHTML = time_u(proc['request duration']); 346 row.cells[row.cells.length - 1].__search_v = proc['request duration']; 347 row.cells[row.cells.length - 1].__search_t = 0; 348 349 row.insertCell(-1).innerHTML = proc['request method']; 350 row.cells[row.cells.length - 1].__search_v = proc['request method']; 351 row.cells[row.cells.length - 1].__search_t = 1; 352 353 row.insertCell(-1).innerHTML = proc['request uri']; 354 row.cells[row.cells.length - 1].__search_v = proc['request uri']; 355 row.cells[row.cells.length - 1].__search_t = 1; 356 357 row.insertCell(-1).innerHTML = proc['content length']; 358 row.cells[row.cells.length - 1].__search_v = proc['content length']; 359 row.cells[row.cells.length - 1].__search_t = 0; 360 361 row.insertCell(-1).innerHTML = proc.user; 362 row.cells[row.cells.length - 1].__search_v = proc.user; 363 row.cells[row.cells.length - 1].__search_t = 1; 364 365 row.insertCell(-1).innerHTML = proc.script; 366 row.cells[row.cells.length - 1].__search_v = proc.script; 367 row.cells[row.cells.length - 1].__search_t = 1; 368 369 if (cpumem) { 370 row.insertCell(-1).innerHTML = cpu(proc['last request cpu']); 371 row.cells[row.cells.length - 1].__search_v = proc['last request cpu']; 372 row.cells[row.cells.length - 1].__search_t = 0; 373 374 row.insertCell(-1).innerHTML = memory(proc['last request memory']); 375 row.cells[row.cells.length - 1].__search_v = proc['last request memory']; 376 row.cells[row.cells.length - 1].__search_t = 0; 377 } 378 } 379 } 380 } 381 382 function date(d) { 383 var t = new Date(d); 384 var r = ""; 385 386 r += (t.getDate() < 10 ? '0' : '') + t.getDate(); 387 r += '/'; 388 r += (t.getMonth() + 1 < 10 ? '0' : '') + (t.getMonth() + 1); 389 r += '/'; 390 r += t.getFullYear(); 391 r += ' '; 392 r += (t.getHours() < 10 ? '0' : '') + t.getHours(); 393 r += ':'; 394 r += (t.getMinutes() < 10 ? '0' : '') + t.getMinutes(); 395 r += ':'; 396 r += (t.getSeconds() < 10 ? '0' : '') + t.getSeconds(); 397 398 399 return r; 400 } 401 402 function cpu(c) { 403 if (c == 0) return 0; 404 return c + "%"; 405 } 406 407 function memory(mem) { 408 if (mem == 0) return 0; 409 if (mem < 1024) { 410 return mem + "B"; 411 } 412 if (mem < 1024 * 1024) { 413 return mem/1024 + "KB"; 414 } 415 if (mem < 1024*1024*1024) { 416 return mem/1024/1024 + "MB"; 417 } 418 } 419 420 function time_s(t) { 421 var r = ""; 422 if (t < 60) { 423 return t + 's'; 424 } 425 426 r = (t % 60) + 's'; 427 t = Math.floor(t / 60); 428 if (t < 60) { 429 return t + 'm ' + r; 430 } 431 432 r = (t % 60) + 'm ' + r; 433 t = Math.floor(t/60); 434 435 if (t < 24) { 436 return t + 'h ' + r; 437 } 438 439 return Math.floor(t/24) + 'd ' + (t % 24) + 'h ' + t; 440 } 441 442 function time_u(t) { 443 var r = ""; 444 if (t < 1000) { 445 return t + 'µs' 446 } 447 448 r = (t % 1000) + 'µs'; 449 t = Math.floor(t / 1000); 450 if (t < 1000) { 451 return t + 'ms ' + r; 452 } 453 454 return time_s(Math.floor(t/1000)) + ' ' + (t%1000) + 'ms ' + r; 455 } 456--> 457 </script> 458 </body> 459</html> 460