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_perso/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] */ #define CORE_PRIVATE @@ -388,10 +390,78 @@ ap_scoreboard_image->global->restart_time); 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: 10pt;}\n\ + 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: bold;border:none;}\n\ + 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 = -1;\n\ + else\n\ + if (a.htmlContent.toUpperCase() > b.htmlContent.toUpperCase()) _toreturn = 1;\n\ + 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\ + _table.replaceChild(_containers[i].cells.cloneNode(true),_table.rows.item(i+1));\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); else - 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>" -#endif - "<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\" onClick=\"textSort(this);\">Acc</th>" + "<th class=\"tab\" onClick=\"textSort(this);\">M</th>" +#ifdef HAVE_TIMES + "<th class=\"tab\" onClick=\"numericSort(this);\">CPU\n</th>" +#endif + "<th class=\"tab\" onClick=\"numericSort(this);\">SS</th><th class=\"tab\" onClick=\"numericSort(this);\">Req</th>" + "<th class=\"tab\" onClick=\"numericSort(this);\">Conn</th><th class=\"tab\" onClick=\"numericSort(this);\">Child</th><th class=\"tab\" onClick=\"numericSort(this);\">Slot</th>" + "<th class=\"tab\" onClick=\"textSort(this);\">Client</th><th class=\"tab\" onClick=\"textSort(this);\">VHost</th>" + "<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) ap_rprintf(r, - "<tr><td><b>%d-%d</b></td><td>-</td><td>%d/%lu/%lu", + "<tr><td class=\"numeric\"><b>%d-%d</b></td><td class=\"numeric\">-</td><td class=\"numeric\">%d/%lu/%lu", i, (int)ps_record->generation, (int)conn_lres, my_lres, lres); else ap_rprintf(r, - "<tr><td><b>%d-%d</b></td><td>%" + "<tr><td class=\"numeric\"><b>%d-%d</b></td><td class=\"numeric\">%" APR_PID_T_FMT - "</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); break; case SERVER_STARTING: - ap_rputs("</td><td><b>S</b>", r); + ap_rputs("</td><td class=\"centered\"><b>S</b>", r); break; case SERVER_BUSY_READ: - ap_rputs("</td><td><b>R</b>", r); + ap_rputs("</td><td class=\"centered\"><b>R</b>", r); break; case SERVER_BUSY_WRITE: - ap_rputs("</td><td><b>W</b>", r); + ap_rputs("</td><td class=\"centered\"><b>W</b>", r); break; case SERVER_BUSY_KEEPALIVE: - ap_rputs("</td><td><b>K</b>", r); + ap_rputs("</td><td class=\"centered\"><b>K</b>", r); break; case SERVER_BUSY_LOG: - ap_rputs("</td><td><b>L</b>", r); + ap_rputs("</td><td class=\"centered\"><b>L</b>", r); break; case SERVER_BUSY_DNS: - ap_rputs("</td><td><b>D</b>", r); + ap_rputs("</td><td class=\"centered\"><b>D</b>", r); break; case SERVER_CLOSING: - ap_rputs("</td><td><b>C</b>", r); + ap_rputs("</td><td class=\"centered\"><b>C</b>", r); break; case SERVER_DEAD: - ap_rputs("</td><td>.", r); + ap_rputs("</td><td class=\"centered\">.", r); break; case SERVER_GRACEFUL: - ap_rputs("</td><td>G", r); + ap_rputs("</td><td class=\"centered\">G", r); break; case SERVER_IDLE_KILL: - ap_rputs("</td><td>I", r); + ap_rputs("</td><td class=\"centered\">I", r); break; default: - ap_rputs("</td><td>?", r); + ap_rputs("</td><td class=\"centered\">?", r); break; } ap_rprintf(r, "\n</td>" #ifdef HAVE_TIMES - "<td>%.2f</td>" + "<td class=\"numeric\">%.2f</td>" #endif - "<td>%ld</td><td>%ld", + "<td class=\"numeric\">%ld</td><td class=\"numeric\">%ld", #ifdef HAVE_TIMES (ws_record->times.tms_utime + ws_record->times.tms_stime + @@ -736,16 +806,16 @@ ws_record->last_used), (long)req_time); - ap_rprintf(r, "</td><td>%-1.1f</td><td>%-2.2f</td><td>%-2.2f\n", + 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) ap_rprintf(r, - "</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"); else ap_rprintf(r, - "</td><td>%s</td><td nowrap>%s</td><td nowrap>%s</td></tr>\n\n", + "</td><td class=\"centered\">%s</td><td class=\"centered\" nowrap>%s</td><td nowrap>%s</td></tr>\n\n", ap_escape_html(r->pool, ws_record->client), ap_escape_html(r->pool,
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?
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.
Created attachment 21752 [details] screenshot
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).
I want to try your patch
(In reply to comment #5) > I want to try your patch Against which branch?
(In reply to comment #6) > Against which branch? I'm using 2.2
Created attachment 21765 [details] patch adding ExtendedStatusCssUrl and ExtendedStatusJsUrl Patch: - 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.
Created attachment 21766 [details] sample css for extended status page To use, save into your document root and use : ExtendedStatusCssUrl /server-status.css
(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.
(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.
(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.
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.