Bug 26835 - [PATCH] Mod_status Readability & Browser Side Table Sorting enhancements
Summary: [PATCH] Mod_status Readability & Browser Side Table Sorting enhancements
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: mod_status (show other bugs)
Version: 2.0.48
Hardware: All All
: P3 enhancement (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
Keywords: MassUpdate, PatchAvailable
Depends on:
Reported: 2004-02-10 18:33 UTC by Francois Cartegnie
Modified: 2018-11-07 21:08 UTC (History)
3 users (show)

screenshot (61.16 KB, image/png)
2008-04-01 09:23 UTC, Olivier Grange-Labat
patch adding ExtendedStatusCssUrl and ExtendedStatusJsUrl (11.74 KB, patch)
2008-04-02 04:26 UTC, Olivier Grange-Labat
Details | Diff
sample css for extended status page (500 bytes, text/css)
2008-04-02 04:32 UTC, Olivier Grange-Labat

Note You need to log in before you can comment on or make changes to this bug.
Description Francois Cartegnie 2004-02-10 18:33:32 UTC
This patch :
-adds some readability enhancements.
-On table display, it also adds simple ecmascript code (MSIE, Mozilla verified) for
browser side table sorting.
-status page is now valid HTML 4.01T

diff -u httpd-2.0.48/modules/generators/mod_status.c
--- httpd-2.0.48/modules/generators/mod_status.c	2003-02-03 18:31:40.000000000 +0100
+++ httpd-2.0.48_perso/modules/generators/mod_status.c	2004-02-10
19:27:01.000000000 +0100
@@ -94,6 +94,8 @@
  *          extended STATUS is enabled) [George Burgyan/Jim J.]
  * 10.8.98  Allow for extended status info at runtime (no more STATUS)
  *          [Jim J.]
+ * 10.2.04  Readibility Enhancements, now HTML 4.01T, table sorting
+ *          [Francois Cartegnie]
@@ -388,10 +390,78 @@
     if (!short_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_rputs(DOCTYPE_HTML_4_0T
+		 "<html><head>\n<title>Apache Status for ", r);
+	ap_rvputs(r, ap_get_server_name(r), "</title>\n", NULL);
+	    if (!no_table_report) {
+		ap_rputs("<STYLE TYPE=\"text/css\"><!-- \n\
+			BODY,TD,TH,P{font-family: Verdana, Arial, Helvetica, sans-serif;font-size:
+			TD {background:#FFFFFF; padding:2px;}\n\
+			PRE {font-family: Courier, Courier New; letter-spacing:2pt;}\n\
+			TH.tab {text-align:center; text-decoration: underline; font-weight:
+			TH.tab:hover {text-decoration: none; cursor:pointer;}\n\
+			TABLE.stats {background:#F0F0F0; text-decoration: none; width:100%;}\n\
+			TD.numeric {text-align:right;}\n\
+			TD.centered {text-align:center;}\n\
+			//--></STYLE>\n",r);
+			ap_rputs("<script type=\"text/javascript\"><!--\n\
+			var _lastHeader = null;\n\
+			function container(cells, htmlContent) {\n\
+				this.cells = cells;\n\
+				this.htmlContent = htmlContent;\n\
+			}\n\
+			function textSortFunction(a,b) {\n\
+				var _toreturn;\n\
+				if (a.htmlContent.toUpperCase() < b.htmlContent.toUpperCase()) _toreturn =
+				else\n\
+				if (a.htmlContent.toUpperCase() > b.htmlContent.toUpperCase()) _toreturn =
+				else\n\
+				_toreturn = 0;\n\
+				\n\
+				if (_reverse) return (_toreturn * -1);\n\
+				else return _toreturn;\n\
+			}\n\
+			function numericSortFunction(a,b) {\n\
+				var _toreturn;\n\
+				if (parseFloat(a.htmlContent) < parseFloat(b.htmlContent)) _toreturn =  1;\n\
+				else\n\
+				if (parseFloat(a.htmlContent) > parseFloat(b.htmlContent)) _toreturn = -1;\n\
+				else\n\
+				_toreturn = 0;\n\
+				\n\
+				if (_reverse) return (_toreturn * -1);\n\
+				else return _toreturn;\n\
+			}\n\
+			function sortTable(target,sFunction) {\n\
+				var _table = target.parentNode.parentNode;\n\
+				var _containers = new Array(_table.rows.length-1);\n\
+				if (_lastHeader == target) _reverse = !( _reverse ); \n\
+				else {_reverse = false;}\n\
+				for (var i=1; i<(_table.rows.length); i++)\n\
+					_containers[i-1] = new container(_table.rows.item(i).cloneNode(true),\n\
+									_table.rows.item(i).cells.item(target.cellIndex).innerHTML);\n\
+				if (_table.rows.length >= 1) _containers.sort(sFunction);\n\
+				for (var i=0; i<(_table.rows.length-1); i++)\n\
+			\n\
+			}\n\
+			function numericSort(target) {\n\		
+				sortTable(target,numericSortFunction);\n\
+				_lastHeader=target;\n\	
+				return 0;\n\
+			}\n\
+			function textSort(target) {\n\
+				sortTable(target,textSortFunction);\n\				
+				_lastHeader=target;\n\
+				return 0;\n\
+			}\n\
+			//--></script>\n", r);
+	    }
+        ap_rputs("</head><body>\n<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);
@@ -544,16 +614,16 @@
         if (no_table_report)
             ap_rputs("<hr /><h2>Server Details</h2>\n\n", r);
-            ap_rputs("\n\n<table border=\"0\"><tr>"
-                     "<th>Srv</th><th>PID</th><th>Acc</th>"
-                     "<th>M</th>"
-#ifdef HAVE_TIMES
-                     "<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);
+            ap_rputs("\n\n<table class=\"stats\" border=\"0\"><tr>"
+                     "<th class=\"tab\" onClick=\"textSort(this);\">Srv</th><th
class=\"tab\" onClick=\"numericSort(this);\">PID</th><th class=\"tab\"
+                     "<th class=\"tab\" onClick=\"textSort(this);\">M</th>"
+#ifdef HAVE_TIMES
+                     "<th class=\"tab\" onClick=\"numericSort(this);\">CPU\n</th>"
+                     "<th class=\"tab\"
onClick=\"numericSort(this);\">SS</th><th class=\"tab\"
+                     "<th class=\"tab\"
onClick=\"numericSort(this);\">Conn</th><th class=\"tab\"
onClick=\"numericSort(this);\">Child</th><th class=\"tab\"
+                     "<th class=\"tab\"
onClick=\"textSort(this);\">Client</th><th class=\"tab\"
+                     "<th class=\"tab\"
onClick=\"textSort(this);\">Request</th></tr>\n\n", r);
         for (i = 0; i < server_limit; ++i) {
             for (j = 0; j < thread_limit; ++j) {
@@ -669,63 +739,63 @@
                 else { /* !no_table_report */
                     if (ws_record->status == SERVER_DEAD)
+                                   "<tr><td
class=\"numeric\"><b>%d-%d</b></td><td class=\"numeric\">-</td><td
                                    i, (int)ps_record->generation,
                                    (int)conn_lres, my_lres, lres);
-                                   "<tr><td><b>%d-%d</b></td><td>%"
+                                   "<tr><td
class=\"numeric\"><b>%d-%d</b></td><td class=\"numeric\">%"
-                                   "</td><td>%d/%lu/%lu",
+                                   "</td><td class=\"numeric\">%d/%lu/%lu",
                                    i, (int)ps_record->generation,
                                    ps_record->pid, (int)conn_lres,
                                    my_lres, lres);
                     switch (ws_record->status) {
                     case SERVER_READY:
-                        ap_rputs("</td><td>_", r);
+                        ap_rputs("</td><td class=\"centered\">_", r);
                     case SERVER_STARTING:
-                        ap_rputs("</td><td><b>S</b>", r);
+                        ap_rputs("</td><td class=\"centered\"><b>S</b>", r);
                     case SERVER_BUSY_READ:
-                        ap_rputs("</td><td><b>R</b>", r);
+                        ap_rputs("</td><td class=\"centered\"><b>R</b>", r);
                     case SERVER_BUSY_WRITE:
-                        ap_rputs("</td><td><b>W</b>", r);
+                        ap_rputs("</td><td class=\"centered\"><b>W</b>", r);
                     case SERVER_BUSY_KEEPALIVE:
-                        ap_rputs("</td><td><b>K</b>", r);
+                        ap_rputs("</td><td class=\"centered\"><b>K</b>", r);
                     case SERVER_BUSY_LOG:
-                        ap_rputs("</td><td><b>L</b>", r);
+                        ap_rputs("</td><td class=\"centered\"><b>L</b>", r);
                     case SERVER_BUSY_DNS:
-                        ap_rputs("</td><td><b>D</b>", r);
+                        ap_rputs("</td><td class=\"centered\"><b>D</b>", r);
                     case SERVER_CLOSING:
-                        ap_rputs("</td><td><b>C</b>", r);
+                        ap_rputs("</td><td class=\"centered\"><b>C</b>", r);
                     case SERVER_DEAD:
-                        ap_rputs("</td><td>.", r);
+                        ap_rputs("</td><td class=\"centered\">.", r);
                     case SERVER_GRACEFUL:
-                        ap_rputs("</td><td>G", r);
+                        ap_rputs("</td><td class=\"centered\">G", r);
                     case SERVER_IDLE_KILL:
-                        ap_rputs("</td><td>I", r);
+                        ap_rputs("</td><td class=\"centered\">I", r);
-                        ap_rputs("</td><td>?", r);
+                        ap_rputs("</td><td class=\"centered\">?", r);
 #ifdef HAVE_TIMES
-                               "<td>%.2f</td>"
+                               "<td class=\"numeric\">%.2f</td>"
-                               "<td>%ld</td><td>%ld",
+                               "<td class=\"numeric\">%ld</td><td
 #ifdef HAVE_TIMES
                                (ws_record->times.tms_utime +
                                 ws_record->times.tms_stime +
@@ -736,16 +806,16 @@
-                    ap_rprintf(r,
+                    ap_rprintf(r, "</td><td class=\"numeric\">%-1.1f</td><td
class=\"numeric\">%-2.2f</td><td class=\"numeric\">%-2.2f\n",
                                (float)conn_bytes / KBYTE, (float) my_bytes / MBYTE,
                                (float)bytes / MBYTE);
                     if (ws_record->status == SERVER_BUSY_READ)
-                                   "</td><td>?</td><td nowrap>?</td><td
nowrap>..reading.. </td></tr>\n\n");
+                                   "</td><td class=\"centered\">?</td><td
class=\"centered\" nowrap>?</td><td nowrap>..reading.. </td></tr>\n\n");
-                                   "</td><td>%s</td><td nowrap>%s</td><td
+                                   "</td><td class=\"centered\">%s</td><td
class=\"centered\" nowrap>%s</td><td nowrap>%s</td></tr>\n\n",
Comment 1 Paul Querna 2004-06-14 06:54:05 UTC
I don't like to embed CSS or JavaScript into C.  Perhaps it would be better if
the user could supply a directive to specify an external CSS or JavaScript file
to include?
Comment 2 Francois Cartegnie 2004-06-15 09:08:49 UTC
As server-status is an apache handler, it is not bound to any vhost.
The directive would be inclued in the handler section, which would cause
troubles with upgrades.

If we need to fix css or js, the user would need to upgrade manually in his vhost.
Comment 3 Olivier Grange-Labat 2008-04-01 09:23:21 UTC
Created attachment 21752 [details]
Comment 4 Olivier Grange-Labat 2008-04-01 09:25:37 UTC
I have such a patch if anyone is interested. 

It adds support for ExtendedStatusCssUrl and ExtendedStatusJsUrl which both take an URL for .css or .js to include in extended status page.

CSS allows for instance better highlighting of current requests.

See attached screenshot (running on my own Apache development server).
Comment 5 Takashi Sato 2008-04-01 12:16:17 UTC
I want to try your patch
Comment 6 Olivier Grange-Labat 2008-04-02 01:12:43 UTC
(In reply to comment #5)
> I want to try your patch

Against which branch?
Comment 7 Takashi Sato 2008-04-02 01:45:18 UTC
(In reply to comment #6)
> Against which branch?

I'm using 2.2
Comment 8 Olivier Grange-Labat 2008-04-02 04:26:24 UTC
Created attachment 21765 [details]
patch adding ExtendedStatusCssUrl and ExtendedStatusJsUrl


- adds ExtendedStatusCssUrl 
- adds ExtendedStatusJsUrl (I don't use it myself, but added it after reviewing this bug #)
- makes page HTML 4.0 Transitional valid
- corrects <title> to add server name (useful for bookmarks)

Quirk: I had to correct <dl>'s use for more powerful styling, which made degraded mode (without any css) different to what extended status used to look like. If anyone is interested in commiting this patch, I'd correct this.
Comment 9 Olivier Grange-Labat 2008-04-02 04:32:55 UTC
Created attachment 21766 [details]
sample css for extended status page

To use, save into your document root and use :

ExtendedStatusCssUrl /server-status.css
Comment 10 Francois Cartegnie 2008-04-02 05:08:21 UTC
(In reply to comment #9)
> Created an attachment (id=21766) [details]
> sample css for extended status page
> To use, save into your document root and use :
> ExtendedStatusCssUrl /server-status.css

Might be interesting to merge both patchs.
But again, i'm not a fan of adding an external document call to an engine only function.
Comment 11 Takashi Sato 2008-04-02 05:35:23 UTC
(In reply to comment #10)
> But again, i'm not a fan of adding an external document call to an engine only
> function.

There are precedents: DefaultIcon, AddIcon and AddIconByType.
Comment 12 Olivier Grange-Labat 2008-04-02 05:38:47 UTC
(In reply to comment #10)
> Might be interesting to merge both patchs.
> But again, i'm not a fan of adding an external document call to an engine only
> function.

Seems like the easiest way for the administrator to tweak the page to fit his
needs though.
Comment 13 William A. Rowe Jr. 2018-11-07 21:08:09 UTC
Please help us to refine our list of open and current defects; this is a mass update of old and inactive Bugzilla reports which reflect user error, already resolved defects, and still-existing defects in httpd.

As repeatedly announced, the Apache HTTP Server Project has discontinued all development and patch review of the 2.2.x series of releases. The final release 2.2.34 was published in July 2017, and no further evaluation of bug reports or security risks will be considered or published for 2.2.x releases. All reports older than 2.4.x have been updated to status RESOLVED/LATER; no further action is expected unless the report still applies to a current version of httpd.

If your report represented a question or confusion about how to use an httpd feature, an unexpected server behavior, problems building or installing httpd, or working with an external component (a third party module, browser etc.) we ask you to start by bringing your question to the User Support and Discussion mailing list, see [https://httpd.apache.org/lists.html#http-users] for details. Include a link to this Bugzilla report for completeness with your question.

If your report was clearly a defect in httpd or a feature request, we ask that you retest using a modern httpd release (2.4.33 or later) released in the past year. If it can be reproduced, please reopen this bug and change the Version field above to the httpd version you have reconfirmed with.

Your help in identifying defects or enhancements still applicable to the current httpd server software release is greatly appreciated.