From: Jim Jagielski Date: Mon, 24 Sep 2012 16:56:58 +0000 (+0000) Subject: Would be nice to have some sort of canonical definition X-Git-Tag: 2.5.0-alpha~6275 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1134cfb81d14d5c8d7b486a9f0b3400f35f8444d;p=apache Would be nice to have some sort of canonical definition of server loading for Apache. So create a struct that holds some useful data. The hope is that for those platforms that lack getloadavg(), people will write replacements. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1389481 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/configure.in b/configure.in index 2cce0404b2..1b0cee14d3 100644 --- a/configure.in +++ b/configure.in @@ -483,7 +483,8 @@ bindprocessor \ prctl \ timegm \ getpgid \ -fopen64 +fopen64 \ +getloadavg ) dnl confirm that a void pointer is large enough to store a long integer diff --git a/include/httpd.h b/include/httpd.h index 9f3fea9bb6..a012505520 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -1298,6 +1298,24 @@ struct server_rec { void *context; }; +/** + * @struct server_load_rec + * @brief A structure to hold various server load params + */ +typedef struct ap_sload_t ap_sload_t; +struct ap_sload_t { + /* 1 min loadavg, ala getloadavg() */ + float loadavg1; + /* 5 min loadavg */ + float loadavg5; + /* 15 min loadavg */ + float loadavg15; + /* percentage of process/threads ready/idle (0->100)*/ + int idle; + /* percentage of process/threads busy (0->100) */ + int busy; +}; + /** * Get the context_document_root for a request. This is a generalization of * the document root, which is too limited in the presence of mappers like @@ -2187,6 +2205,11 @@ AP_DECLARE(void *) ap_realloc(void *ptr, size_t size) AP_FN_ATTR_WARN_UNUSED_RESULT AP_FN_ATTR_ALLOC_SIZE(2); +/** + * Get server load params + * @param ld struct to populate: -1 in fields means error + */ +AP_DECLARE(void) ap_get_sload(ap_sload_t *ld); #define AP_NORESTART APR_OS_START_USEERR + 1 diff --git a/modules/generators/mod_status.c b/modules/generators/mod_status.c index 50bcb27297..bbd2d5d07a 100644 --- a/modules/generators/mod_status.c +++ b/modules/generators/mod_status.c @@ -393,6 +393,8 @@ static int status_handler(request_rec *r) ap_scoreboard_image->global->restart_time); if (!short_report) { + ap_sload_t t; + ap_rputs(DOCTYPE_HTML_3_2 "\n" "Apache Status\n" @@ -419,6 +421,9 @@ static int status_handler(request_rec *r) ap_rputs("
Server uptime: ", r); show_time(r, up_time); ap_rputs("
\n", r); + ap_get_sload(&t); + ap_rprintf(r, "
Server load: %.2f %.2f %.2f [%d:%d]
\n", + t.loadavg1, t.loadavg5, t.loadavg15, t.idle, t.busy); } if (ap_extended_status) { diff --git a/server/util.c b/server/util.c index 24d3a22ed3..d518eadef1 100644 --- a/server/util.c +++ b/server/util.c @@ -63,6 +63,8 @@ #include #endif +#include "ap_mpm.h" + /* A bunch of functions in util.c scan strings looking for certain characters. * To make that more efficient we encode a lookup table. The test_char_table * is generated automatically by gen_test_char.c. @@ -2788,3 +2790,63 @@ AP_DECLARE(void *) ap_realloc(void *ptr, size_t size) ap_abort_on_oom(); return p; } + +AP_DECLARE(void) ap_get_sload(ap_sload_t *ld) +{ + double la[3]; + int i, j, num, server_limit, thread_limit; + int ready = 0; + int busy = 0; + int total; + ap_generation_t mpm_generation; + + /* preload errored fields, we overwrite */ + ld->loadavg1 = -1.0; + ld->loadavg5 = -1.0; + ld->loadavg15 = -1.0; + ld->idle = -1; + ld->busy = -1; + +#if HAVE_GETLOADAVG + num = getloadavg(la, 3); + if (num > 0) { + ld->loadavg1 = (float)la[0]; + } + if (num > 1) { + ld->loadavg5 = (float)la[1]; + } + if (num > 2) { + ld->loadavg15 = (float)la[2]; + } +#endif + ap_mpm_query(AP_MPMQ_GENERATION, &mpm_generation); + ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit); + ap_mpm_query(AP_MPMQ_HARD_LIMIT_DAEMONS, &server_limit); + + for (i = 0; i < server_limit; i++) { + process_score *ps; + ps = ap_get_scoreboard_process(i); + + for (j = 0; j < thread_limit; j++) { + int res; + worker_score *ws = NULL; + ws = &ap_scoreboard_image->servers[i][j]; + res = ws->status; + + if (res == SERVER_READY && ps->generation == mpm_generation) { + ready++; + } + else if (res != SERVER_DEAD && + res != SERVER_STARTING && res != SERVER_IDLE_KILL && + ps->generation == mpm_generation) { + busy++; + } + } + } + total = busy + ready; + if (total) { + ld->idle = ready * 100 / total; + ld->busy = busy * 100 / total; + } + +}