You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Ian Holsman <ia...@cnet.com> on 2001/09/13 07:15:43 UTC

[PATCH] -- xml output for mod-status

new option for mod status server-status/?xml
it has the same data as the standard HTML (and obeys the 'extended' as does the html version)

the only difference is that it doesn't output the '.' (Open Slot for no current processes)

..Ian

Index: mod_status.c
===================================================================
RCS file: /home/cvs/httpd-2.0/modules/generators/mod_status.c,v
retrieving revision 1.46
diff -u -r1.46 mod_status.c
--- mod_status.c	2001/08/11 04:04:13	1.46
+++ mod_status.c	2001/09/13 04:59:29
@@ -206,10 +206,11 @@

  /* ID values for command table */

-#define STAT_OPT_END		-1
-#define STAT_OPT_REFRESH	0
-#define STAT_OPT_NOTABLE	1
-#define STAT_OPT_AUTO		2
+#define STAT_OPT_END       -1
+#define STAT_OPT_REFRESH    0
+#define STAT_OPT_NOTABLE    1
+#define STAT_OPT_AUTO       2
+#define STAT_OPT_XML        3

  struct stat_opt {
      int id;
@@ -222,6 +223,7 @@
      {STAT_OPT_REFRESH, "refresh", "Refresh"},
      {STAT_OPT_NOTABLE, "notable", NULL},
      {STAT_OPT_AUTO, "auto", NULL},
+    {STAT_OPT_XML, "xml", NULL},
      {STAT_OPT_END, NULL, NULL}
  };

@@ -251,6 +253,8 @@
  #endif
      int short_report = 0;
      int no_table_report = 0;
+    int xml_report = 0;
+    int html_report =0;
      worker_score ws_record;
      process_score ps_record;
      char stat_buffer[HARD_SERVER_LIMIT * HARD_THREAD_LIMIT];
@@ -275,6 +279,7 @@
  	return DECLINED;

      r->content_type = "text/html";
+    html_report =1;

      /*
       * Simple table-driven form data set parser that lets you alter the header
@@ -302,7 +307,14 @@
  		case STAT_OPT_AUTO:
  		    r->content_type = "text/plain";
  		    short_report = 1;
+            html_report =0;
  		    break;
+      case STAT_OPT_XML:
+            r->content_type = "text/xml";
+            xml_report = 1;
+            html_report =0;
+            break;
+
  		}
  	    }
  	    i++;
@@ -357,25 +369,37 @@
      /* up_time in seconds */
      up_time = (apr_uint32_t) ((nowtime - ap_restart_time)/APR_USEC_PER_SEC);

-    if (!short_report) {
- 
ap_rputs(DOCTYPE_HTML_3_2
+    if (html_report) {
+        ap_rputs(DOCTYPE_HTML_3_2
  		 "<html><head>\n<title>Apache Status</title>\n</head><body>\n",
  		 r);
- 
ap_rputs("<h1>Apache Server Status for ", r);
- 
ap_rvputs(r, ap_get_server_name(r), "</h1>\n\n", NULL);
- 
ap_rvputs(r, "<dl><dt>Server Version: ",
- 
   ap_get_server_version(), "</dt>\n", NULL);
- 
ap_rvputs(r, "<dt>Server Built: ",
- 
   ap_get_server_built(), "\n</dt></dl><hr /><dl>\n", NULL);
- 
ap_rvputs(r, "<dt>Current Time: ",
- 
   ap_ht_time(r->pool, nowtime, DEFAULT_TIME_FORMAT, 0), "</dt>\n", NULL);
- 
ap_rvputs(r, "<dt>Restart Time: ",
- 
   ap_ht_time(r->pool, ap_restart_time, DEFAULT_TIME_FORMAT, 0),
- 
   "</dt>\n", NULL);
- 
ap_rprintf(r, "<dt>Parent Server Generation: %d</dt>\n", (int) ap_my_generation);
- 
ap_rputs("<dt>Server uptime: ", r);
- 
show_time(r, up_time);
- 
ap_rputs("</dt>\n", r);
+        ap_rputs("<h1>Apache Server Status for ", r);
+        ap_rvputs(r, ap_get_server_name(r), "</h1>\n\n", NULL);
+        ap_rvputs(r, "<dl><dt>Server Version: ",
+          ap_get_server_version(), "</dt>\n", NULL);
+        ap_rvputs(r, "<dt>Server Built: ",
+          ap_get_server_built(), "\n</dt></dl><hr /><dl>\n", NULL);
+        ap_rvputs(r, "<dt>Current Time: ",
+          ap_ht_time(r->pool, nowtime, DEFAULT_TIME_FORMAT, 0), "</dt>\n", NULL);
+        ap_rvputs(r, "<dt>Restart Time: ",
+          ap_ht_time(r->pool, ap_restart_time, DEFAULT_TIME_FORMAT, 0),
+          "</dt>\n", NULL);
+        ap_rprintf(r, "<dt>Parent Server Generation: %d</dt>\n", (int) ap_my_generation);
+        ap_rputs("<dt>Server uptime: ", r);
+        show_time(r, up_time);
+        ap_rputs("</dt>\n", r);
+    }
+    if (xml_report) {
+        ap_rputs("<?xml version='1.0' ?>\n",r);
+        ap_rprintf(r,"<status servername='%s'>\n",ap_get_server_name(r));
+        ap_rprintf(r,"<time><built>%s</built><current>%s</current><restart>%s</restart></time>\n",
+            ap_get_server_built(),
+            ap_ht_time(r->pool, nowtime, DEFAULT_TIME_FORMAT, 0),
+            ap_ht_time(r->pool, ap_restart_time, DEFAULT_TIME_FORMAT, 0));
+        ap_rprintf(r,"<generation number='%d' />\n",(int)ap_my_generation);
+        ap_rputs("<uptime>",r);
+        show_time(r,up_time);
+        ap_rputs("</uptime>\n",r);
      }

      if (ap_extended_status) {
@@ -403,81 +427,154 @@
  		ap_rprintf(r, "BytesPerReq: %g\n",
  		    KBYTE * (float) kbcount / (float) count);
  	}
- 
else {			/* !short_report */
- 
     ap_rprintf(r, "<dt>Total accesses: %lu - Total Traffic: ", count);
- 
     format_kbyte_out(r, kbcount);
- 
     ap_rputs("</dt>\n", r);
+    else { /* !short_report */
+        if (html_report) {
+           ap_rprintf(r, "<dt>Total accesses: %lu - Total Traffic: ", count);
+           format_kbyte_out(r, kbcount);
+           ap_rputs("</dt>\n", r);

  #ifdef HAVE_TIMES
- 
     /* Allow for OS/2 not having CPU stats */
- 
     ap_rprintf(r, "<dt>CPU Usage: u%g s%g cu%g cs%g",
- 
	    tu / tick, ts / tick, tcu / tick, tcs / tick);
+           /* Allow for OS/2 not having CPU stats */
+           ap_rprintf(r, "<dt>CPU Usage: u%g s%g cu%g cs%g",
+                          tu / tick, ts / tick, tcu / tick, tcs / tick);

- 
     if (ts || tu || tcu || tcs)
- 
	ap_rprintf(r, " - %.3g%% CPU load</dt>\n",
+           if (ts || tu || tcu || tcs)
+              ap_rprintf(r, " - %.3g%% CPU load</dt>\n",
  		    (tu + ts + tcu + tcs) / tick / up_time * 100.);
  #endif

- 
     if (up_time > 0)
- 
	ap_rprintf(r, "<dt>%.3g requests/sec - ",
- 
		(float) count / (float) up_time);
+            if (up_time > 0) {
+               ap_rprintf(r, "<dt>%.3g requests/sec - ",
+                              (float) count / (float) up_time);
+
+               format_byte_out(r, (unsigned long)(KBYTE * (float) kbcount
+                                            / (float) up_time));
+               ap_rputs("/second - ", r);
+            }

- 
     if (up_time > 0) {
- 
	format_byte_out(r, (unsigned long)(KBYTE * (float) kbcount
-                                                         / (float) up_time));
- 
	ap_rputs("/second - ", r);
- 
     }
+           if (count > 0) {
+              format_byte_out(r, (unsigned long)(KBYTE * (float) kbcount
+                                     / (float) count));
+              ap_rputs("/request", r);
+           }

- 
     if (count > 0) {
- 
	format_byte_out(r, (unsigned long)(KBYTE * (float) kbcount
-                                                         / (float) count));
- 
	ap_rputs("/request", r);
- 
     }
+           ap_rputs("</dt>\n", r);
+        } /* html_report */
+        else {
+            ap_rprintf(r, "<total accesses ='%lu' kb='%lu' />\n", count,kbcount);
+#ifdef HAVE_TIMES
+            ap_rprintf(r, "<cpu usr='%g' sys='%g' cuser='%g' csys='%g'",
+                    tu / tick, ts / tick, tcu / tick, tcs / tick );
+            if (ts || tu || tcu || tcs) {
+               ap_rprintf(r, " load='%.3g%%",
+                    (tu + ts + tcu + tcs) / tick / up_time * 100.);
+            }
+            ap_rputs("/>\n",r);
+#endif
+            if (up_time >0 ) {
+                ap_rprintf(r,"<reqspersec>%.3g</reqspersec>"
+                             "<bytespersec>%d</bytespersec>",
+                   (float) count / (float) up_time,
+                   (unsigned long)(KBYTE * (float)kbcount / (float)up_time));
+            }

- 
     ap_rputs("</dt>\n", r);
- 
} 
			/* short_report */
+        }               /* xml_report */
+    } /* short_report */
+
      }					/* ap_extended_status */

-    if (!short_report)
- 
ap_rprintf(r, "<dt>%d requests currently being processed, %d idle workers</dt>\n"
- 
	,busy, ready);
-    else
- 
ap_rprintf(r, "BusyWorkers: %d\nIdleWorkers: %d\n", busy, ready);
+    if (html_report) {
+        ap_rprintf(r, "<dt>%d requests currently being processed, %d ",busy);
+        ap_rprintf(r,"idle workers</dt>\n",ready);
+    }
+    else {
+        if (xml_report ) {
+            ap_rprintf(r,"<workers busy='%d' idle='%d' />\n",busy,ready);

+        }
+        else { /* short_report */
+            ap_rprintf(r, "BusyWorkers: %d\nIdleWorkers: %d\n", busy, ready);
+        }
+    }
+
      /* send the scoreboard 'table' out */

-    if (!short_report)
- 
ap_rputs("</dl><pre>", r);
-    else
- 
ap_rputs("Scoreboard: ", r);
+    if (html_report) {
+ 
     ap_rputs("</dl><pre>", r);
+    }
+    else {
+        if (xml_report) {
+            ap_rputs("<scoreboard>\n", r);
+        }
+        else {
+            ap_rputs("Scoreboard: ", r);
+        }
+    }
+ 


      for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
+        if (xml_report) {
+            ap_rprintf(r,"<server number='%d' pid='%"APR_OS_PROC_T_FMT "'>\n",
+                i,pid_buffer[i]);
+        }
          for (j = 0; j < HARD_THREAD_LIMIT; ++j) {
              int indx = (i * HARD_THREAD_LIMIT) + j;
- 
     ap_rputc(stat_buffer[indx], r);
- 
     if ((indx % STATUS_MAXLINE == (STATUS_MAXLINE - 1)) && !short_report)
- 
         ap_rputs("\n", r);
+            if (html_report) {
+                ap_rputc(stat_buffer[indx], r);
+                if ((indx % STATUS_MAXLINE ) == (STATUS_MAXLINE - 1))
+                    ap_rputs("\n",r);
+            }
+            else {
+                if (xml_report) {
+                    if (stat_buffer[indx] != '.' )
+                        ap_rprintf(r,"<thread number='%d' status='%c' />",j,stat_buffer[indx]);
+                }
+                else {
+                    ap_rputc(stat_buffer[indx], r);
+                }
+            }
+        } /* thread loop */
+        if (xml_report )
+            ap_rputs("</server>\n",r);
+    } /* server loop */
+
+    if (html_report) {
+        ap_rputs("</pre>\n", r);
+        ap_rputs("<p>Scoreboard Key:<br />\n", r);
+        ap_rputs("\"<b><code>_</code></b>\" Waiting for Connection, \n", r);
+        ap_rputs("\"<b><code>S</code></b>\" Starting up, \n", r);
+        ap_rputs("\"<b><code>R</code></b>\" Reading Request,<br />\n", r);
+        ap_rputs("\"<b><code>W</code></b>\" Sending Reply, \n", r);
+        ap_rputs("\"<b><code>K</code></b>\" Keepalive (read), \n", r);
+        ap_rputs("\"<b><code>D</code></b>\" DNS Lookup,<br />\n", r);
+        ap_rputs("\"<b><code>C</code></b>\" Closing connection, \n", r);
+        ap_rputs("\"<b><code>L</code></b>\" Logging, \n", r);
+        ap_rputs("\"<b><code>G</code></b>\" Gracefully finishing,<br /> \n", r);
+        ap_rputs("\"<b><code>I</code></b>\" Idle cleanup of worker, \n", r);
+        ap_rputs("\"<b><code>.</code></b>\" Open slot with no current process</p>\n", r);
+        ap_rputs("<p />\n", r);
+    }
+    else {
+        if (xml_report) {
+            ap_rputs("<statuslegend>\n", r);
+            ap_rputs("<status key='_' description='Waiting for Connection' />\n", r);
+            ap_rputs("<status key='S' description='Starting up' />\n", r);
+            ap_rputs("<status key='R' description='Reading Request' />\n", r);
+            ap_rputs("<status key='W' description='Sending Reply' />\n", r);
+            ap_rputs("<status key='K' description='Keepalive (read)' />\n", r);
+            ap_rputs("<status key='D' description='DNS Lookup' />\n", r);
+            ap_rputs("<status key='C' description='Closing connection' />\n", r);
+            ap_rputs("<status key='L' description='Logging' />\n", r);
+            ap_rputs("<status key='G' description='Gracefully finishing' />\n", r);
+            ap_rputs("<status key='I' description='Idle cleanup of worker' />\n", r);
+            ap_rputs("<status key='.' description='Open slot with no current process' />\n", r); 

+            ap_rputs("</statuslegend></scoreboard>\n", r);
+        }
+        else {
+            ap_rputs("\n", r);
          }
      }

-    if (short_report)
- 
ap_rputs("\n", r);
-    else {
- 
ap_rputs("</pre>\n", r);
- 
ap_rputs("<p>Scoreboard Key:<br />\n", r);
- 
ap_rputs("\"<b><code>_</code></b>\" Waiting for Connection, \n", r);
- 
ap_rputs("\"<b><code>S</code></b>\" Starting up, \n", r);
- 
ap_rputs("\"<b><code>R</code></b>\" Reading Request,<br />\n", r);
- 
ap_rputs("\"<b><code>W</code></b>\" Sending Reply, \n", r);
- 
ap_rputs("\"<b><code>K</code></b>\" Keepalive (read), \n", r);
- 
ap_rputs("\"<b><code>D</code></b>\" DNS Lookup,<br />\n", r);
- 
ap_rputs("\"<b><code>C</code></b>\" Closing connection, \n", r);
- 
ap_rputs("\"<b><code>L</code></b>\" Logging, \n", r);
- 
ap_rputs("\"<b><code>G</code></b>\" Gracefully finishing,<br /> \n", r);
-        ap_rputs("\"<b><code>I</code></b>\" Idle cleanup of worker, \n", r);
- 
ap_rputs("\"<b><code>.</code></b>\" Open slot with no current process</p>\n", r);
- 
ap_rputs("<p />\n", r);
- 
if (!ap_extended_status) {
+ 
if (!ap_extended_status && html_report) {
  	    int j;
              int k = 0;
  	    ap_rputs("PID Key: <br />\n", r);
@@ -501,20 +598,24 @@
  	    ap_rputs("\n", r);
  	    ap_rputs("</pre>\n", r);
  	}
-    }

      if (ap_extended_status) {
- 
if (!short_report) {
+ 
if (html_report) {
  	    if (no_table_report)
  		ap_rputs("<hr /><h2>Server Details</h2>\n\n", r);
  	    else
  #ifndef HAVE_TIMES
  		/* Allow for OS/2 not having CPU stats */
- 
	ap_rputs("\n\n<table 
border=\"0\"><tr><th>Srv</th><th>PID</th><th>Acc</th><th>M\n</th><th>SS</th><th>Req</th><th>Conn</th><th>Child</th><th>Slot</th><th>Client</th><th>VHost</th><th>Request</th></tr>\n\n", 
r);
+ 
     	ap_rputs("\n\n<table 
border=\"0\"><tr><th>Srv</th><th>PID</th><th>Acc</th><th>M\n</th><th>SS</th><th>Req</th><th>Conn</th><th>Child</th><th>Slot</th><th>Client</th><th>VHost</th><th>Request</th></tr>\n\n", 
r);
  #else
  		ap_rputs("\n\n<table 
border=\"0\"><tr><th>Srv</th><th>PID</th><th>Acc</th><th>M</th><th>CPU\n</th><th>SS</th><th>Req</th><th>Conn</th><th>Child</th><th>Slot</th><th>Client</th><th>VHost</th><th>Request</th></tr>\n\n", 
r);
  #endif
  	}
+    else {
+        if (xml_report) {
+            ap_rputs("<extended><slots>\n",r);
+        }
+    }

  	for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
  	for (j = 0; j < HARD_THREAD_LIMIT; ++j) {
@@ -556,7 +657,7 @@
  	    conn_bytes = ws_record.conn_bytes;
  	    if (lres != 0 || (ws_record.status != SERVER_READY
  	 
	      && ws_record.status != SERVER_DEAD)) {
- 
	if (!short_report) {
+ 
	if (html_report) {
  		    if (no_table_report) {
  	 
	if (ws_record.status == SERVER_DEAD)
  	 
	    ap_rprintf(r,
@@ -712,12 +813,59 @@
  	 
		vhost->server_hostname) : "(unavailable)",
  	 
	     ap_escape_html(r->pool, ws_record.request));
  		    }		/* no_table_report */
- 
	}			/* !short_report */
+ 
	}			/* !html_report */
+        else {
+            if (xml_report) {
+                ap_rprintf(r,"<slot id='%d' generation='%d' "
+                                "con='%d' my='%lu' lres='%lu' ",
+                                i, (int)ps_record.generation,
+                                (int)conn_lres,my_lres,lres);
+                if (ws_record.status != SERVER_DEAD)
+                    ap_rprintf(r," pid='%"APR_OS_PROC_T_FMT "' ", ps_record.pid);
+
+                ap_rprintf(r," status='%d' seconds_since_begining_recent_req='%.0f' "
+                    "milliseconds_required_most_recent_req='%ld' ",
+                    ws_record.status,
+                    (long)((nowtime - ws_record.last_used) / APR_USEC_PER_SEC),
+                    (long) req_time);
+#ifdef HAVE_TIMES
+ 
		    ap_rprintf(r, "usr='%g' sys='%g' cusr='%g' csys='%g' ",
+ 
		        ws_record.times.tms_utime / tick,
+ 
		        ws_record.times.tms_stime / tick,
+ 
		        ws_record.times.tms_cutime / tick,
+ 
		        ws_record.times.tms_cstime / tick);
+#endif
+                ap_rputs(">\n",r);
+                ap_rprintf(r,"<bytes conn='%ld' child='%ld' slot='%ld' />",
+                    conn_bytes,my_bytes, bytes);
+                ap_rprintf(r,"<client host='%s' vhost='%s' uri='%s' />",
+ 
		        ap_escape_html(r->pool, ws_record.client),
+                    vhost ? ap_escape_html(r->pool,
+    	    			    vhost->server_hostname) : "(unavailable)",
+                    ap_escape_html(r->pool, ws_record.request));
+                ap_rputs("</slot>\n",r);
+            }
+        }
  	    }			/* if (<active child>) */
  	} 
			/* for () */
  	}
+    if (xml_report) {
+        ap_rputs("</slots><statuslegend>\n",r);
+        ap_rprintf(r,"<status key='%d' desc='%s' />\n",SERVER_READY,"Ready");
+        ap_rprintf(r,"<status key='%d' desc='%s' />\n",SERVER_STARTING,"Starting");
+        ap_rprintf(r,"<status key='%d' desc='%s' />\n",SERVER_BUSY_READ,"Read");
+        ap_rprintf(r,"<status key='%d' desc='%s' />\n",SERVER_BUSY_WRITE,"Write");
+        ap_rprintf(r,"<status key='%d' desc='%s' />\n",SERVER_BUSY_KEEPALIVE,"Keepalive");
+        ap_rprintf(r,"<status key='%d' desc='%s' />\n",SERVER_BUSY_LOG,"Logging");
+        ap_rprintf(r,"<status key='%d' desc='%s' />\n",SERVER_BUSY_DNS,"DNS Lookup");
+        ap_rprintf(r,"<status key='%d' desc='%s' />\n",SERVER_CLOSING,"Closing");
+        ap_rprintf(r,"<status key='%d' desc='%s' />\n",SERVER_DEAD,"Dead");
+        ap_rprintf(r,"<status key='%d' desc='%s' />\n",SERVER_GRACEFUL,"Graceful");
+        ap_rprintf(r,"<status key='%d' desc='%s' />\n",SERVER_IDLE_KILL,"Dying");

- 
if (!(short_report || no_table_report)) {
+        ap_rputs("</statuslegend></extended>\n",r);
+    }
+ 
if (html_report && !no_table_report) {
  #ifndef HAVE_TIMES
  	    ap_rputs("</table>\n \
  <hr /> \
@@ -752,18 +900,22 @@

      } else {

- 
if (!short_report) {
+ 
if (html_report) {
  	    ap_rputs("<hr />To obtain a full report with current status information ", r);
  	    ap_rputs("you need to use the <code>ExtendedStatus On</code> directive. \n", r);
  	}

      }

-    if (!short_report) {
+    if (html_report) {
  	ap_rputs(ap_psignature("<hr />\n",r), r);
  	ap_rputs("</body></html>\n", r);
      }

+    if (xml_report)
+    {
+        ap_rputs("</status>\n", r);
+    }
      return 0;
  }