Apache HTTPD
mod_status.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/* Status Module. Display lots of internal data about how Apache is
18 * performing and the state of all children processes.
19 *
20 * To enable this, add the following lines into any config file:
21 *
22 * <Location /server-status>
23 * SetHandler server-status
24 * </Location>
25 *
26 * You may want to protect this location by password or domain so no one
27 * else can look at it. Then you can access the statistics with a URL like:
28 *
29 * http://your_server_name/server-status
30 *
31 * /server-status - Returns page using tables
32 * /server-status?notable - Returns page for browsers without table support
33 * /server-status?refresh - Returns page with 1 second refresh
34 * /server-status?refresh=6 - Returns page with refresh every 6 seconds
35 * /server-status?auto - Returns page with data for automatic parsing
36 *
37 * Mark Cox, [email protected], November 1995
38 *
39 * 12.11.95 Initial version for www.telescope.org
40 * 13.3.96 Updated to remove rprintf's [Mark]
41 * 18.3.96 Added CPU usage, process information, and tidied [Ben Laurie]
42 * 18.3.96 Make extra Scoreboard variables #definable
43 * 25.3.96 Make short report have full precision [Ben Laurie suggested]
44 * 25.3.96 Show uptime better [Mark/Ben Laurie]
45 * 29.3.96 Better HTML and explanation [Mark/Rob Hartill suggested]
46 * 09.4.96 Added message for non-STATUS compiled version
47 * 18.4.96 Added per child and per slot counters [Jim Jagielski]
48 * 01.5.96 Table format, cleanup, even more spiffy data [Chuck Murcko/Jim J.]
49 * 18.5.96 Adapted to use new rprintf() routine, incidentally fixing a missing
50 * piece in short reports [Ben Laurie]
51 * 21.5.96 Additional Status codes (DNS and LOGGING only enabled if
52 * extended STATUS is enabled) [George Burgyan/Jim J.]
53 * 10.8.98 Allow for extended status info at runtime (no more STATUS)
54 * [Jim J.]
55 */
56
57#include "httpd.h"
58#include "http_config.h"
59#include "http_core.h"
60#include "http_protocol.h"
61#include "http_main.h"
62#include "ap_mpm.h"
63#include "util_script.h"
64#include <time.h>
65#include "scoreboard.h"
66#include "http_log.h"
67#include "mod_status.h"
68#if APR_HAVE_UNISTD_H
69#include <unistd.h>
70#endif
71#define APR_WANT_STRFUNC
72#include "apr_want.h"
73#include "apr_strings.h"
74
75#define STATUS_MAXLINE 64
76
77#define KBYTE 1024
78#define MBYTE 1048576L
79#define GBYTE 1073741824L
80
81#ifndef DEFAULT_TIME_FORMAT
82#define DEFAULT_TIME_FORMAT "%A, %d-%b-%Y %H:%M:%S %Z"
83#endif
84
85#define STATUS_MAGIC_TYPE "application/x-httpd-status"
86
87module AP_MODULE_DECLARE_DATA status_module;
88
91
92/* Implement 'ap_run_status_hook'. */
94 (request_rec *r, int flags),
95 (r, flags),
97
98#ifdef HAVE_TIMES
99/* ugh... need to know if we're running with a pthread implementation
100 * such as linuxthreads that treats individual threads as distinct
101 * processes; that affects how we add up CPU time in a process
102 */
103static pid_t child_pid;
104#endif
105
106/* Format the number of bytes nicely */
108{
109 if (bytes < (5 * KBYTE))
110 ap_rprintf(r, "%d B", (int) bytes);
111 else if (bytes < (MBYTE / 2))
112 ap_rprintf(r, "%.1f kB", (float) bytes / KBYTE);
113 else if (bytes < (GBYTE / 2))
114 ap_rprintf(r, "%.1f MB", (float) bytes / MBYTE);
115 else
116 ap_rprintf(r, "%.1f GB", (float) bytes / GBYTE);
117}
118
120{
121 if (kbytes < KBYTE)
122 ap_rprintf(r, "%d kB", (int) kbytes);
123 else if (kbytes < MBYTE)
124 ap_rprintf(r, "%.1f MB", (float) kbytes / KBYTE);
125 else
126 ap_rprintf(r, "%.1f GB", (float) kbytes / MBYTE);
127}
128
130{
131 int days, hrs, mins, secs;
132
133 secs = (int)(tsecs % 60);
134 tsecs /= 60;
135 mins = (int)(tsecs % 60);
136 tsecs /= 60;
137 hrs = (int)(tsecs % 24);
138 days = (int)(tsecs / 24);
139
140 if (days)
141 ap_rprintf(r, " %d day%s", days, days == 1 ? "" : "s");
142
143 if (hrs)
144 ap_rprintf(r, " %d hour%s", hrs, hrs == 1 ? "" : "s");
145
146 if (mins)
147 ap_rprintf(r, " %d minute%s", mins, mins == 1 ? "" : "s");
148
149 if (secs)
150 ap_rprintf(r, " %d second%s", secs, secs == 1 ? "" : "s");
151}
152
153/* Main handler for x-httpd-status requests */
154
155/* ID values for command table */
156
157#define STAT_OPT_END -1
158#define STAT_OPT_REFRESH 0
159#define STAT_OPT_NOTABLE 1
160#define STAT_OPT_AUTO 2
161
162struct stat_opt {
163 int id;
164 const char *form_data_str;
165 const char *hdr_out_str;
166};
167
168static const struct stat_opt status_options[] = /* see #defines above */
169{
170 {STAT_OPT_REFRESH, "refresh", "Refresh"},
171 {STAT_OPT_NOTABLE, "notable", NULL},
172 {STAT_OPT_AUTO, "auto", NULL},
174};
175
176/* add another state for slots above the MaxRequestWorkers setting */
177#define SERVER_DISABLED SERVER_NUM_STATUS
178#define MOD_STATUS_NUM_STATUS (SERVER_NUM_STATUS+1)
179
181
183{
184 const char *loc;
188 int j, i, res, written;
189 int idle;
190 int graceful;
191 int busy;
192 unsigned long count;
193 unsigned long lres, my_lres, conn_lres;
194 apr_off_t bytes, my_bytes, conn_bytes;
196 long req_time;
199 int short_report;
200 int no_table_report;
204 char *stat_buffer;
209 clock_t tu, ts, tcu, tcs;
210 clock_t gu, gs, gcu, gcs;
212#ifdef HAVE_TIMES
213 float tick;
215#endif
216
218 "server-status")) {
219 return DECLINED;
220 }
221
222#ifdef HAVE_TIMES
224#endif
225
227
228#ifdef HAVE_TIMES
229#ifdef _SC_CLK_TCK
231#else
232 tick = HZ;
233#endif
234#endif
235
236 idle = 0;
237 graceful = 0;
238 busy = 0;
239 count = 0;
240 bcount = 0;
241 kbcount = 0;
242 duration_global = 0;
243 short_report = 0;
244 no_table_report = 0;
245
248 "Server status unavailable in inetd mode");
250 }
251
254 if (is_async) {
258 }
259
261#ifdef HAVE_TIMES
263 gu = global_record->times.tms_utime;
264 gs = global_record->times.tms_stime;
265 gcu = global_record->times.tms_cutime;
266 gcs = global_record->times.tms_cstime;
267#else
268 gu = gs = gcu = gcs = 0;
269#endif
270 tu = ts = tcu = tcs = 0;
271
273 if (r->method_number != M_GET)
274 return DECLINED;
275
276 ap_set_content_type_ex(r, "text/html; charset=ISO-8859-1", 1);
277
278 /*
279 * Simple table-driven form data set parser that lets you alter the header
280 */
281
282 if (r->args) {
283 i = 0;
284 while (status_options[i].id != STAT_OPT_END) {
285 if ((loc = ap_strstr_c(r->args,
287 switch (status_options[i].id) {
288 case STAT_OPT_REFRESH: {
290 long t = 0;
291
292 if (*(loc + len ) == '=') {
293 t = atol(loc + len + 1);
294 }
297 apr_ltoa(r->pool, t < 1 ? 10 : t));
298 break;
299 }
300 case STAT_OPT_NOTABLE:
301 no_table_report = 1;
302 break;
303 case STAT_OPT_AUTO:
304 ap_set_content_type_ex(r, "text/plain; charset=ISO-8859-1", 1);
305 short_report = 1;
306 break;
307 }
308 }
309
310 i++;
311 }
312 }
313
314 ws_record = apr_palloc(r->pool, sizeof *ws_record);
315
316 for (i = 0; i < server_limit; ++i) {
317#ifdef HAVE_TIMES
318 clock_t proc_tu = 0, proc_ts = 0, proc_tcu = 0, proc_tcs = 0;
320#endif
321
323 if (is_async) {
327 }
328 for (j = 0; j < thread_limit; ++j) {
329 int indx = (i * thread_limit) + j;
330
332 res = ws_record->status;
333
334 if ((i >= max_servers || j >= threads_per_child)
335 && (res == SERVER_DEAD))
337 else
339
340 if (!ps_record->quiescing
341 && ps_record->pid) {
342 if (res == SERVER_READY) {
343 if (ps_record->generation == mpm_generation)
344 idle++;
345 if (is_async)
347 }
348 else if (res != SERVER_DEAD &&
349 res != SERVER_STARTING &&
351 if (res == SERVER_GRACEFUL) {
352 graceful++;
353 if (is_async)
355 } else {
356 busy++;
357 if (is_async)
359 }
360 }
361 }
362
363 /* XXX what about the counters for quiescing/seg faulted
364 * processes? should they be counted or not? GLA
365 */
366 if (ap_extended_status) {
367 lres = ws_record->access_count;
368 bytes = ws_record->bytes_served;
369
370 if (lres != 0 || (res != SERVER_READY && res != SERVER_DEAD)) {
371#ifdef HAVE_TIMES
372 tmp_tu = ws_record->times.tms_utime;
373 tmp_ts = ws_record->times.tms_stime;
374 tmp_tcu = ws_record->times.tms_cutime;
375 tmp_tcs = ws_record->times.tms_cstime;
376
377 if (times_per_thread) {
378 proc_tu += tmp_tu;
379 proc_ts += tmp_ts;
380 proc_tcu += tmp_tcu;
381 proc_tcs += tmp_tcs;
382 }
383 else {
384 if (tmp_tu > proc_tu ||
385 tmp_ts > proc_ts ||
386 tmp_tcu > proc_tcu ||
387 tmp_tcs > proc_tcs) {
388 proc_tu = tmp_tu;
389 proc_ts = tmp_ts;
392 }
393 }
394#endif /* HAVE_TIMES */
395
396 count += lres;
397 bcount += bytes;
398 duration_global += ws_record->duration;
399
400 if (bcount >= KBYTE) {
401 kbcount += (bcount >> 10);
402 bcount = bcount & 0x3ff;
403 }
404 }
405 }
406 }
407#ifdef HAVE_TIMES
408 tu += proc_tu;
409 ts += proc_ts;
410 tcu += proc_tcu;
411 tcs += proc_tcs;
412#endif
413 pid_buffer[i] = ps_record->pid;
414 }
415
416 /* up_time in seconds */
420
421 if (!short_report) {
423 "<html><head>\n"
424 "<title>Apache Status</title>\n"
425 "</head><body>\n"
426 "<h1>Apache Server Status for ", r);
428 " (via ", r->connection->local_ip,
429 ")</h1>\n\n", NULL);
430 ap_rvputs(r, "<dl><dt>Server Version: ",
431 ap_get_server_description(), "</dt>\n", NULL);
432 ap_rvputs(r, "<dt>Server MPM: ",
433 ap_show_mpm(), "</dt>\n", NULL);
434 ap_rvputs(r, "<dt>Server Built: ",
435 ap_get_server_built(), "\n</dt></dl><hr /><dl>\n", NULL);
436 ap_rvputs(r, "<dt>Current Time: ",
438 "</dt>\n", NULL);
439 ap_rvputs(r, "<dt>Restart Time: ",
443 "</dt>\n", NULL);
444 ap_rprintf(r, "<dt>Parent Server Config. Generation: %d</dt>\n",
446 ap_rprintf(r, "<dt>Parent Server MPM Generation: %d</dt>\n",
447 (int)mpm_generation);
448 ap_rputs("<dt>Server uptime: ", r);
450 ap_rputs("</dt>\n", r);
451 ap_rprintf(r, "<dt>Server load: %.2f %.2f %.2f</dt>\n",
452 t.loadavg, t.loadavg5, t.loadavg15);
453 }
454 else {
456 ap_rvputs(r, "ServerVersion: ",
458 ap_rvputs(r, "ServerMPM: ",
459 ap_show_mpm(), "\n", NULL);
460 ap_rvputs(r, "Server Built: ",
461 ap_get_server_built(), "\n", NULL);
462 ap_rvputs(r, "CurrentTime: ",
464 "\n", NULL);
465 ap_rvputs(r, "RestartTime: ",
469 "\n", NULL);
470 ap_rprintf(r, "ParentServerConfigGeneration: %d\n",
472 ap_rprintf(r, "ParentServerMPMGeneration: %d\n",
473 (int)mpm_generation);
474 ap_rprintf(r, "ServerUptimeSeconds: %u\n",
475 up_time);
476 ap_rputs("ServerUptime:", r);
478 ap_rputs("\n", r);
479 ap_rprintf(r, "Load1: %.2f\nLoad5: %.2f\nLoad15: %.2f\n",
480 t.loadavg, t.loadavg5, t.loadavg15);
481 }
482
483 if (ap_extended_status) {
484 clock_t cpu = gu + gs + gcu + gcs + tu + ts + tcu + tcs;
485 if (short_report) {
486 ap_rprintf(r, "Total Accesses: %lu\nTotal kBytes: %"
487 APR_OFF_T_FMT "\nTotal Duration: %"
488 APR_TIME_T_FMT "\n",
490
491#ifdef HAVE_TIMES
492 /* Allow for OS/2 not having CPU stats */
493 ap_rprintf(r, "CPUUser: %g\nCPUSystem: %g\nCPUChildrenUser: %g\nCPUChildrenSystem: %g\n",
494 (gu + tu) / tick, (gs + ts) / tick, (gcu + tcu) / tick, (gcs + tcs) / tick);
495
496 if (cpu)
497 ap_rprintf(r, "CPULoad: %g\n",
498 cpu / tick / up_time * 100.);
499#endif
500
501 ap_rprintf(r, "Uptime: %ld\n", (long) (up_time));
502 if (up_time > 0) {
503 ap_rprintf(r, "ReqPerSec: %g\n",
504 (float) count / (float) up_time);
505
506 ap_rprintf(r, "BytesPerSec: %g\n",
507 KBYTE * (float) kbcount / (float) up_time);
508 }
509 if (count > 0) {
510 ap_rprintf(r, "BytesPerReq: %g\n",
511 KBYTE * (float) kbcount / (float) count);
512 ap_rprintf(r, "DurationPerReq: %g\n",
513 (float) apr_time_as_msec(duration_global) / (float) count);
514 }
515 }
516 else { /* !short_report */
517 ap_rprintf(r, "<dt>Total accesses: %lu - Total Traffic: ", count);
519 ap_rprintf(r, " - Total Duration: %" APR_TIME_T_FMT "</dt>\n",
521
522#ifdef HAVE_TIMES
523 /* Allow for OS/2 not having CPU stats */
524 ap_rprintf(r, "<dt>CPU Usage: u%g s%g cu%g cs%g",
525 (gu + tu) / tick, (gs + ts) / tick, (gcu + tcu) / tick, (gcs + tcs) / tick);
526
527 if (cpu)
528 ap_rprintf(r, " - %.3g%% CPU load</dt>\n",
529 cpu / tick / up_time * 100.);
530 else
531 ap_rputs("</dt>\n", r);
532#endif
533
534 ap_rputs("<dt>", r);
535 if (up_time > 0) {
536 ap_rprintf(r, "%.3g requests/sec - ",
537 (float) count / (float) up_time);
538
539 format_byte_out(r, (unsigned long)(KBYTE * (float) kbcount
540 / (float) up_time));
541 ap_rputs("/second", r);
542 }
543
544 if (count > 0) {
545 if (up_time > 0)
546 ap_rputs(" - ", r);
547 format_byte_out(r, (unsigned long)(KBYTE * (float) kbcount
548 / (float) count));
549 ap_rprintf(r, "/request - %g ms/request",
550 (float) apr_time_as_msec(duration_global) / (float) count);
551 }
552
553 ap_rputs("</dt>\n", r);
554 } /* short_report */
555 } /* ap_extended_status */
556
557 if (!short_report)
558 ap_rprintf(r, "<dt>%d requests currently being processed, %d workers gracefully restarting, "
559 "%d idle workers</dt>\n", busy, graceful, idle);
560 else
561 ap_rprintf(r, "BusyWorkers: %d\nGracefulWorkers: %d\nIdleWorkers: %d\n", busy, graceful, idle);
562
563 if (!short_report)
564 ap_rputs("</dl>", r);
565
566 if (is_async) {
567 int write_completion = 0, lingering_close = 0, keep_alive = 0,
568 connections = 0, stopping = 0, procs = 0;
569 if (!short_report)
570 ap_rputs("\n\n<table rules=\"all\" cellpadding=\"1%\">\n"
571 "<tr><th rowspan=\"2\">Slot</th>"
572 "<th rowspan=\"2\">PID</th>"
573 "<th rowspan=\"2\">Stopping</th>"
574 "<th colspan=\"2\">Connections</th>\n"
575 "<th colspan=\"2\">Threads</th>"
576 "<th colspan=\"3\">Async connections</th></tr>\n"
577 "<tr><th>total</th><th>accepting</th>"
578 "<th>busy</th><th>graceful</th><th>idle</th>"
579 "<th>writing</th><th>keep-alive</th><th>closing</th></tr>\n", r);
580 for (i = 0; i < server_limit; ++i) {
582 if (ps_record->pid) {
583 connections += ps_record->connections;
584 write_completion += ps_record->write_completion;
585 keep_alive += ps_record->keep_alive;
586 lingering_close += ps_record->lingering_close;
587 procs++;
588 if (ps_record->quiescing) {
589 stopping++;
590 }
591 if (!short_report) {
592 const char *dying = "no";
593 const char *old = "";
594 if (ps_record->quiescing) {
595 dying = "yes";
596 }
597 if (ps_record->generation != mpm_generation)
598 old = " (old gen)";
599 ap_rprintf(r, "<tr><td>%u</td><td>%" APR_PID_T_FMT "</td>"
600 "<td>%s%s</td>"
601 "<td>%u</td><td>%s</td>"
602 "<td>%u</td><td>%u</td><td>%u</td>"
603 "<td>%u</td><td>%u</td><td>%u</td>"
604 "</tr>\n",
605 i, ps_record->pid,
606 dying, old,
607 ps_record->connections,
608 ps_record->not_accepting ? "no" : "yes",
612 ps_record->write_completion,
613 ps_record->keep_alive,
614 ps_record->lingering_close);
615 }
616 }
617 }
618 if (!short_report) {
619 ap_rprintf(r, "<tr><td>Sum</td>"
620 "<td>%d</td><td>%d</td>"
621 "<td>%d</td><td>&nbsp;</td>"
622 "<td>%d</td><td>%d</td><td>%d</td>"
623 "<td>%d</td><td>%d</td><td>%d</td>"
624 "</tr>\n</table>\n",
626 connections,
627 busy, graceful, idle,
628 write_completion, keep_alive, lingering_close);
629 }
630 else {
631 ap_rprintf(r, "Processes: %d\n"
632 "Stopping: %d\n"
633 "ConnsTotal: %d\n"
634 "ConnsAsyncWriting: %d\n"
635 "ConnsAsyncKeepAlive: %d\n"
636 "ConnsAsyncClosing: %d\n",
638 connections,
639 write_completion, keep_alive, lingering_close);
640 }
641 }
642
643 /* send the scoreboard 'table' out */
644 if (!short_report)
645 ap_rputs("<pre>", r);
646 else
647 ap_rputs("Scoreboard: ", r);
648
649 written = 0;
650 for (i = 0; i < server_limit; ++i) {
651 for (j = 0; j < thread_limit; ++j) {
652 int indx = (i * thread_limit) + j;
655 if ((written % STATUS_MAXLINE == (STATUS_MAXLINE - 1))
656 && !short_report)
657 ap_rputs("\n", r);
658 written++;
659 }
660 }
661 }
662
663
664 if (short_report)
665 ap_rputs("\n", r);
666 else {
667 ap_rputs("</pre>\n"
668 "<p>Scoreboard Key:<br />\n"
669 "\"<b><code>_</code></b>\" Waiting for Connection, \n"
670 "\"<b><code>S</code></b>\" Starting up, \n"
671 "\"<b><code>R</code></b>\" Reading Request,<br />\n"
672 "\"<b><code>W</code></b>\" Sending Reply, \n"
673 "\"<b><code>K</code></b>\" Keepalive (read), \n"
674 "\"<b><code>D</code></b>\" DNS Lookup,<br />\n"
675 "\"<b><code>C</code></b>\" Closing connection, \n"
676 "\"<b><code>L</code></b>\" Logging, \n"
677 "\"<b><code>G</code></b>\" Gracefully finishing,<br /> \n"
678 "\"<b><code>I</code></b>\" Idle cleanup of worker, \n"
679 "\"<b><code>.</code></b>\" Open slot with no current process<br />\n"
680 "</p>\n", r);
681 if (!ap_extended_status) {
682 int j;
683 int k = 0;
684 ap_rputs("PID Key: <br />\n"
685 "<pre>\n", r);
686 for (i = 0; i < server_limit; ++i) {
687 for (j = 0; j < thread_limit; ++j) {
688 int indx = (i * thread_limit) + j;
689
690 if (stat_buffer[indx] != '.') {
692 " in state: %c ", pid_buffer[i],
694
695 if (++k >= 3) {
696 ap_rputs("\n", r);
697 k = 0;
698 } else
699 ap_rputs(",", r);
700 }
701 }
702 }
703
704 ap_rputs("\n"
705 "</pre>\n", r);
706 }
707 }
708
710 if (no_table_report)
711 ap_rputs("<hr /><h2>Server Details</h2>\n\n", r);
712 else
713 ap_rputs("\n\n<table border=\"0\"><tr>"
714 "<th>Srv</th><th>PID</th><th>Acc</th>"
715 "<th>M</th>"
717 "<th>CPU\n</th>"
718#endif
719 "<th>SS</th><th>Req</th><th>Dur</th>"
720 "<th>Conn</th><th>Child</th><th>Slot</th>"
721 "<th>Client</th><th>Protocol</th><th>VHost</th>"
722 "<th>Request</th></tr>\n\n", r);
723
724 for (i = 0; i < server_limit; ++i) {
725 for (j = 0; j < thread_limit; ++j) {
727
728 if (ws_record->access_count == 0 &&
729 (ws_record->status == SERVER_READY ||
730 ws_record->status == SERVER_DEAD)) {
731 continue;
732 }
733
735
736 if (ws_record->start_time == 0L)
737 req_time = 0L;
738 else
739 req_time = (long)
740 apr_time_as_msec(ws_record->stop_time -
741 ws_record->start_time);
742 if (req_time < 0L)
743 req_time = 0L;
744
745 lres = ws_record->access_count;
746 my_lres = ws_record->my_access_count;
747 conn_lres = ws_record->conn_count;
748 bytes = ws_record->bytes_served;
749 my_bytes = ws_record->my_bytes_served;
750 conn_bytes = ws_record->conn_bytes;
751 duration_slot = ws_record->duration;
752 if (ws_record->pid) { /* MPM sets per-worker pid and generation */
753 worker_pid = ws_record->pid;
754 worker_generation = ws_record->generation;
755 }
756 else {
757 worker_pid = ps_record->pid;
758 worker_generation = ps_record->generation;
759 }
760
761 if (no_table_report) {
762 if (ws_record->status == SERVER_DEAD)
764 "<b>Server %d-%d</b> (-): %d|%lu|%lu [",
765 i, (int)worker_generation,
766 (int)conn_lres, my_lres, lres);
767 else
769 "<b>Server %d-%d</b> (%"
770 APR_PID_T_FMT "): %d|%lu|%lu [",
771 i, (int) worker_generation,
773 (int)conn_lres, my_lres, lres);
774
775 switch (ws_record->status) {
776 case SERVER_READY:
777 ap_rputs("Ready", r);
778 break;
779 case SERVER_STARTING:
780 ap_rputs("Starting", r);
781 break;
782 case SERVER_BUSY_READ:
783 ap_rputs("<b>Read</b>", r);
784 break;
786 ap_rputs("<b>Write</b>", r);
787 break;
789 ap_rputs("<b>Keepalive</b>", r);
790 break;
791 case SERVER_BUSY_LOG:
792 ap_rputs("<b>Logging</b>", r);
793 break;
794 case SERVER_BUSY_DNS:
795 ap_rputs("<b>DNS lookup</b>", r);
796 break;
797 case SERVER_CLOSING:
798 ap_rputs("<b>Closing</b>", r);
799 break;
800 case SERVER_DEAD:
801 ap_rputs("Dead", r);
802 break;
803 case SERVER_GRACEFUL:
804 ap_rputs("Graceful", r);
805 break;
806 case SERVER_IDLE_KILL:
807 ap_rputs("Dying", r);
808 break;
809 default:
810 ap_rputs("?STATE?", r);
811 break;
812 }
813
814 ap_rprintf(r, "] "
816 "u%g s%g cu%g cs%g"
817#endif
818 "\n %ld %ld %" APR_TIME_T_FMT "(",
820 ws_record->times.tms_utime / tick,
821 ws_record->times.tms_stime / tick,
822 ws_record->times.tms_cutime / tick,
823 ws_record->times.tms_cstime / tick,
824#endif
825 (long)apr_time_sec(nowtime -
826 ws_record->last_used),
828
829 format_byte_out(r, conn_bytes);
830 ap_rputs("|", r);
832 ap_rputs("|", r);
834 ap_rputs(")\n", r);
836 " <i>%s {%s}</i> <i>(%s)</i> <b>[%s]</b><br />\n\n",
838 ws_record->client64),
841 ws_record->request)),
843 ws_record->protocol),
845 ws_record->vhost));
846 }
847 else { /* !no_table_report */
848 if (ws_record->status == SERVER_DEAD)
850 "<tr><td><b>%d-%d</b></td><td>-</td><td>%d/%lu/%lu",
851 i, (int)worker_generation,
852 (int)conn_lres, my_lres, lres);
853 else
855 "<tr><td><b>%d-%d</b></td><td>%"
857 "</td><td>%d/%lu/%lu",
858 i, (int)worker_generation,
860 (int)conn_lres,
861 my_lres, lres);
862
863 switch (ws_record->status) {
864 case SERVER_READY:
865 ap_rputs("</td><td>_", r);
866 break;
867 case SERVER_STARTING:
868 ap_rputs("</td><td><b>S</b>", r);
869 break;
870 case SERVER_BUSY_READ:
871 ap_rputs("</td><td><b>R</b>", r);
872 break;
874 ap_rputs("</td><td><b>W</b>", r);
875 break;
877 ap_rputs("</td><td><b>K</b>", r);
878 break;
879 case SERVER_BUSY_LOG:
880 ap_rputs("</td><td><b>L</b>", r);
881 break;
882 case SERVER_BUSY_DNS:
883 ap_rputs("</td><td><b>D</b>", r);
884 break;
885 case SERVER_CLOSING:
886 ap_rputs("</td><td><b>C</b>", r);
887 break;
888 case SERVER_DEAD:
889 ap_rputs("</td><td>.", r);
890 break;
891 case SERVER_GRACEFUL:
892 ap_rputs("</td><td>G", r);
893 break;
894 case SERVER_IDLE_KILL:
895 ap_rputs("</td><td>I", r);
896 break;
897 default:
898 ap_rputs("</td><td>?", r);
899 break;
900 }
901
903 "\n</td>"
905 "<td>%.2f</td>"
906#endif
907 "<td>%ld</td><td>%ld</td><td>%" APR_TIME_T_FMT,
909 (ws_record->times.tms_utime +
910 ws_record->times.tms_stime +
911 ws_record->times.tms_cutime +
912 ws_record->times.tms_cstime) / tick,
913#endif
914 (long)apr_time_sec(nowtime -
915 ws_record->last_used),
917
918 ap_rprintf(r, "</td><td>%-1.1f</td><td>%-2.2f</td><td>%-2.2f\n",
919 (float)conn_bytes / KBYTE, (float) my_bytes / MBYTE,
920 (float)bytes / MBYTE);
921
922 ap_rprintf(r, "</td><td>%s</td><td>%s</td><td nowrap>%s</td>"
923 "<td nowrap>%s</td></tr>\n\n",
925 ws_record->client64),
927 ws_record->protocol),
929 ws_record->vhost),
932 ws_record->request)));
933 } /* no_table_report */
934 } /* for (j...) */
935 } /* for (i...) */
936
937 if (!no_table_report) {
938 ap_rputs("</table>\n \
939<hr /> \
940<table>\n \
941<tr><th>Srv</th><td>Child Server number - generation</td></tr>\n \
942<tr><th>PID</th><td>OS process ID</td></tr>\n \
943<tr><th>Acc</th><td>Number of accesses this connection / this child / this slot</td></tr>\n \
944<tr><th>M</th><td>Mode of operation</td></tr>\n"
945
947"<tr><th>CPU</th><td>CPU usage, number of seconds</td></tr>\n"
948#endif
949
950"<tr><th>SS</th><td>Seconds since beginning of most recent request</td></tr>\n \
951<tr><th>Req</th><td>Milliseconds required to process most recent request</td></tr>\n \
952<tr><th>Dur</th><td>Sum of milliseconds required to process all requests</td></tr>\n \
953<tr><th>Conn</th><td>Kilobytes transferred this connection</td></tr>\n \
954<tr><th>Child</th><td>Megabytes transferred this child</td></tr>\n \
955<tr><th>Slot</th><td>Total megabytes transferred this slot</td></tr>\n \
956</table>\n", r);
957 }
958 } /* if (ap_extended_status && !short_report) */
959 else {
960
961 if (!short_report) {
962 ap_rputs("<hr />To obtain a full report with current status "
963 "information you need to use the "
964 "<code>ExtendedStatus On</code> directive.\n", r);
965 }
966 }
967
968 {
969 /* Run extension hooks to insert extra content. */
970 int flags =
974
976 }
977
978 if (!short_report) {
979 ap_rputs(ap_psignature("<hr />\n",r), r);
980 ap_rputs("</body></html>\n", r);
981 }
982
983 return 0;
984}
985
987{
988 /* When mod_status is loaded, default our ExtendedStatus to 'on'
989 * other modules which prefer verbose scoreboards may play a similar game.
990 * If left to their own requirements, mpm modules can make do with simple
991 * scoreboard entries.
992 */
994 return OK;
995}
996
998 server_rec *s)
999{
1000 status_flags[SERVER_DEAD] = '.'; /* We don't want to assume these are in */
1001 status_flags[SERVER_READY] = '_'; /* any particular order in scoreboard.h */
1015 /* work around buggy MPMs */
1016 if (threads_per_child == 0)
1020 return OK;
1021}
1022
1023#ifdef HAVE_TIMES
1025{
1026 child_pid = getpid();
1027}
1028#endif
1029
1039
1041{
1043 NULL, /* dir config creater */
1044 NULL, /* dir merger --- default is to override */
1045 NULL, /* server config */
1046 NULL, /* merge server config */
1047 NULL, /* command table */
1048 register_hooks /* register_hooks */
1049};
Apache Multi-Processing Module library.
const char apr_size_t len
Definition ap_regex.h:187
APR Strings library.
APR Standard Headers Support.
static volatile int dying
Definition event.c:174
void ap_hook_post_config(ap_HOOK_post_config_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:105
#define AP_DECLARE_MODULE(foo)
void ap_hook_handler(ap_HOOK_handler_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:170
void ap_hook_pre_config(ap_HOOK_pre_config_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:91
request_rec * r
void ap_hook_child_init(ap_HOOK_child_init_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:167
const char * ap_show_mpm(void)
Definition mpm_common.c:548
const char * ap_get_server_built(void)
Definition buildmark.c:26
#define DOCTYPE_HTML_3_2
Definition httpd.h:238
const char * ap_get_server_description(void)
Definition core.c:3587
#define DECLINED
Definition httpd.h:457
#define OK
Definition httpd.h:456
int ap_state_query(int query_code)
Definition core.c:5378
const char * ap_get_server_name(request_rec *r)
Definition core.c:1145
#define AP_SQ_CONFIG_GEN
Definition http_core.h:1034
#define APLOGNO(n)
Definition http_log.h:117
#define ap_log_rerror
Definition http_log.h:454
#define APLOG_ERR
Definition http_log.h:67
#define APLOG_MARK
Definition http_log.h:283
int ap_rvputs(request_rec *r,...)
Definition protocol.c:2220
int ap_rprintf(request_rec *r, const char *fmt,...) __attribute__((format(printf
static APR_INLINE int ap_rputs(const char *str, request_rec *r)
int ap_rputc(int c, request_rec *r)
Definition protocol.c:2117
void ap_set_content_type_ex(request_rec *r, const char *ct, int trusted)
unsigned int count
Definition apr_md5.h:152
apr_pool_t apr_dbd_t apr_dbd_results_t ** res
Definition apr_dbd.h:287
const char apr_ssize_t int flags
Definition apr_encode.h:168
#define APR_HOOK_LAST
Definition apr_hooks.h:305
#define APR_HOOK_MIDDLE
Definition apr_hooks.h:303
#define APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ns, link, ret, name, args_decl, args_use, ok, decline)
#define HTTP_INTERNAL_SERVER_ERROR
Definition httpd.h:535
#define AP_STATUS_SHORT
Definition mod_status.h:32
#define AP_STATUS_EXTENDED
Definition mod_status.h:34
int ap_run_status_hook(request_rec *r, int flags)
Definition mod_status.c:96
#define AP_STATUS_NOTABLE
Definition mod_status.h:33
#define AP_METHOD_BIT
Definition httpd.h:629
#define M_GET
Definition httpd.h:592
#define STANDARD20_MODULE_STUFF
const char * ap_psignature(const char *prefix, request_rec *r)
Definition core.c:3516
void ap_get_loadavg(ap_loadavg_t *ld)
Definition util.c:3360
char * ap_escape_logitem(apr_pool_t *p, const char *str)
Definition util.c:2183
#define ap_strstr_c(s, c)
Definition httpd.h:2361
char * ap_ht_time(apr_pool_t *p, apr_time_t t, const char *fmt, int gmt)
Definition util.c:109
#define ap_escape_html(p, s)
Definition httpd.h:1860
apr_size_t size
apr_vformatter_buff_t const char va_list ap
Definition apr_lib.h:176
apr_interval_time_t t
const void apr_size_t bytes
Definition apr_random.h:91
const char * s
Definition apr_strings.h:95
int int status
#define apr_time_as_msec(time)
Definition apr_time.h:72
#define APR_TIME_T_FMT
Definition apr_time.h:52
apr_int64_t apr_time_t
Definition apr_time.h:45
#define apr_time_sec(time)
Definition apr_time.h:63
apr_status_t ap_mpm_query(int query_code, int *result)
Definition mpm_common.c:421
#define AP_MPMQ_IS_ASYNC
Definition ap_mpm.h:176
#define AP_MPMQ_HARD_LIMIT_THREADS
Definition ap_mpm.h:158
#define AP_MPMQ_MAX_THREADS
Definition ap_mpm.h:160
#define AP_MPMQ_GENERATION
Definition ap_mpm.h:178
#define AP_MPMQ_MAX_DAEMONS
Definition ap_mpm.h:172
#define AP_MPMQ_HARD_LIMIT_DAEMONS
Definition ap_mpm.h:156
Apache Configuration.
CORE HTTP Daemon.
Apache Logging library.
Command line options.
HTTP protocol handling.
HTTP Daemon routines.
apr_pool_t * p
Definition md_event.c:32
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
#define DEFAULT_TIME_FORMAT
Definition mod_status.c:82
static int server_limit
Definition mod_status.c:89
#define STATUS_MAXLINE
Definition mod_status.c:75
#define SERVER_DISABLED
Definition mod_status.c:177
static char status_flags[(11+1)]
Definition mod_status.c:180
#define MBYTE
Definition mod_status.c:78
static void format_kbyte_out(request_rec *r, apr_off_t kbytes)
Definition mod_status.c:119
static int max_servers
Definition mod_status.c:89
static void show_time(request_rec *r, apr_uint32_t tsecs)
Definition mod_status.c:129
static const struct stat_opt status_options[]
Definition mod_status.c:168
#define MOD_STATUS_NUM_STATUS
Definition mod_status.c:178
#define STAT_OPT_AUTO
Definition mod_status.c:160
#define KBYTE
Definition mod_status.c:77
static void register_hooks(apr_pool_t *p)
static int thread_limit
Definition mod_status.c:89
#define STAT_OPT_END
Definition mod_status.c:157
static int is_async
Definition mod_status.c:90
static int status_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
Definition mod_status.c:986
#define STATUS_MAGIC_TYPE
Definition mod_status.c:85
static void format_byte_out(request_rec *r, apr_off_t bytes)
Definition mod_status.c:107
#define STAT_OPT_REFRESH
Definition mod_status.c:158
#define GBYTE
Definition mod_status.c:79
static int threads_per_child
Definition mod_status.c:89
static int status_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
Definition mod_status.c:997
static int status_handler(request_rec *r)
Definition mod_status.c:182
#define STAT_OPT_NOTABLE
Definition mod_status.c:159
Status Report Extension Module to Apache.
Apache scoreboard library.
#define SERVER_STARTING
Definition scoreboard.h:57
#define SERVER_CLOSING
Definition scoreboard.h:64
#define SERVER_BUSY_LOG
Definition scoreboard.h:62
int ap_generation_t
Definition scoreboard.h:78
#define SERVER_BUSY_WRITE
Definition scoreboard.h:60
#define SERVER_BUSY_READ
Definition scoreboard.h:59
scoreboard * ap_scoreboard_image
Definition scoreboard.c:44
void ap_copy_scoreboard_worker(worker_score *dest, int child_num, int thread_num)
Definition scoreboard.c:685
int ap_exists_scoreboard_image(void)
Definition scoreboard.c:362
int ap_extended_status
Definition scoreboard.c:61
#define SERVER_GRACEFUL
Definition scoreboard.h:65
#define SERVER_DEAD
Definition scoreboard.h:56
#define SERVER_IDLE_KILL
Definition scoreboard.h:66
#define SERVER_BUSY_KEEPALIVE
Definition scoreboard.h:61
#define SERVER_READY
Definition scoreboard.h:58
global_score * ap_get_scoreboard_global(void)
Definition scoreboard.c:710
#define SERVER_BUSY_DNS
Definition scoreboard.h:63
process_score * ap_get_scoreboard_process(int x)
Definition scoreboard.c:702
A structure to hold various server loadavg.
Definition httpd.h:1427
char * local_ip
Definition httpd.h:1181
apr_time_t restart_time
Definition scoreboard.h:129
A structure that represents the current request.
Definition httpd.h:845
const char * handler
Definition httpd.h:994
int method_number
Definition httpd.h:898
apr_pool_t * pool
Definition httpd.h:847
conn_rec * connection
Definition httpd.h:849
apr_int64_t allowed
Definition httpd.h:922
char * args
Definition httpd.h:1026
apr_table_t * headers_out
Definition httpd.h:978
global_score * global
Definition scoreboard.h:161
A structure to store information for each virtual server.
Definition httpd.h:1322
const char * form_data_str
Definition mod_status.c:164
const char * hdr_out_str
Definition mod_status.c:165
Apache script tools.
typedef int(WSAAPI *apr_winapi_fpt_WSAPoll)(IN OUT LPWSAPOLLFD fdArray