xref: /PHP-5.5/sapi/fpm/status.html.in (revision 95bd5f18)
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 feet 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>&nbsp;</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&darr;</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&darr;</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(/.$/, "&uarr;");
143							order_active_reverse = 1;
144						} else {
145							cell.innerHTML = cell.innerHTML.replace(/.$/, "&darr;");
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 ? "&darr;" : "&uarr;");
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(/.$/, "&uarr;");
162							order_idle_reverse = 1;
163						} else {
164							cell.innerHTML = cell.innerHTML.replace(/.$/, "&darr;");
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 ? "&darr;" : "&uarr;");
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 + '&micro;s'
446				}
447
448				r = (t % 1000) + '&micro;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