diff options
| author | Graham Dumpleton <Graham.Dumpleton@gmail.com> | 2020-09-02 14:10:16 +1000 |
|---|---|---|
| committer | Graham Dumpleton <Graham.Dumpleton@gmail.com> | 2020-09-02 14:10:16 +1000 |
| commit | 660d79bf780e475fddf080d5d62bc30bd0134552 (patch) | |
| tree | f8df7ef867e06329dc373412f582dd2972e6da07 /src/server | |
| parent | 0dce98f4613f7a0673e15510d73e583f89a1a5ce (diff) | |
| download | mod_wsgi-660d79bf780e475fddf080d5d62bc30bd0134552.tar.gz | |
Add function for getting request metrics measured over a period.
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/wsgi_interp.c | 3 | ||||
| -rw-r--r-- | src/server/wsgi_metrics.c | 163 | ||||
| -rw-r--r-- | src/server/wsgi_metrics.h | 2 |
3 files changed, 149 insertions, 19 deletions
diff --git a/src/server/wsgi_interp.c b/src/server/wsgi_interp.c index bdfef88..607bcfc 100644 --- a/src/server/wsgi_interp.c +++ b/src/server/wsgi_interp.c @@ -1276,6 +1276,9 @@ InterpreterObject *newInterpreterObject(const char *name) PyModule_AddObject(module, "process_metrics", PyCFunction_New( &wsgi_process_metrics_method[0], NULL)); + PyModule_AddObject(module, "request_metrics", PyCFunction_New( + &wsgi_request_metrics_method[0], NULL)); + PyModule_AddObject(module, "subscribe_events", PyCFunction_New( &wsgi_process_events_method[0], NULL)); diff --git a/src/server/wsgi_metrics.c b/src/server/wsgi_metrics.c index b147d54..8bb47b4 100644 --- a/src/server/wsgi_metrics.c +++ b/src/server/wsgi_metrics.c @@ -195,6 +195,11 @@ WSGI_STATIC_INTERNED_STRING(active_requests); WSGI_STATIC_INTERNED_STRING(threads); WSGI_STATIC_INTERNED_STRING(thread_id); +WSGI_STATIC_INTERNED_STRING(max_threads); +WSGI_STATIC_INTERNED_STRING(time_interval); +WSGI_STATIC_INTERNED_STRING(utilization); +WSGI_STATIC_INTERNED_STRING(requests_per_sec); + static PyObject *wsgi_status_flags[SERVER_NUM_STATUS]; #define WSGI_CREATE_STATUS_FLAG(name, val) \ @@ -239,6 +244,11 @@ static void wsgi_initialize_interned_strings(void) WSGI_CREATE_INTERNED_STRING_ID(threads); WSGI_CREATE_INTERNED_STRING_ID(thread_id); + WSGI_CREATE_INTERNED_STRING_ID(max_threads); + WSGI_CREATE_INTERNED_STRING_ID(time_interval); + WSGI_CREATE_INTERNED_STRING_ID(utilization); + WSGI_CREATE_INTERNED_STRING_ID(requests_per_sec); + WSGI_CREATE_STATUS_FLAG(SERVER_DEAD, "."); WSGI_CREATE_STATUS_FLAG(SERVER_READY, "_"); WSGI_CREATE_STATUS_FLAG(SERVER_STARTING, "S"); @@ -257,6 +267,140 @@ static void wsgi_initialize_interned_strings(void) /* ------------------------------------------------------------------------- */ +static PyObject *wsgi_request_metrics(void) +{ + PyObject *result = NULL; + + PyObject *object = NULL; + + apr_time_t stop_time; + double stop_request_busy_time = 0.0; + apr_uint64_t stop_request_count = 0.0; + + double request_busy_time = 0.0; + double capacity_utilization = 0.0; + + static double start_time = 0.0; + static double start_request_busy_time = 0.0; + static apr_uint64_t start_request_count = 0; + + double time_interval = 0.0; + apr_uint64_t request_count = 0; + double requests_per_sec = 0.0; + + static int max_threads = 0; + + if (!wsgi_interns_initialized) + wsgi_initialize_interned_strings(); + + if (!max_threads) { + int is_threaded = 0; + +#if defined(MOD_WSGI_WITH_DAEMONS) + if (wsgi_daemon_process) { + max_threads = wsgi_daemon_process->group->threads; + } + else { + ap_mpm_query(AP_MPMQ_IS_THREADED, &is_threaded); + if (is_threaded != AP_MPMQ_NOT_SUPPORTED) { + ap_mpm_query(AP_MPMQ_MAX_THREADS, &max_threads); + } + } +#else + ap_mpm_query(AP_MPMQ_IS_THREADED, &is_threaded); + if (is_threaded != AP_MPMQ_NOT_SUPPORTED) { + ap_mpm_query(AP_MPMQ_MAX_THREADS, &max_threads); + } +#endif + + max_threads = (max_threads <= 0) ? 1 : max_threads; + } + + + result = PyDict_New(); + + stop_time = apr_time_now(); + stop_request_busy_time = wsgi_utilization_time(0); + stop_request_count = wsgi_total_requests; + + if (!start_time) { + start_time = stop_time; + start_request_busy_time = stop_request_busy_time; + start_request_count = stop_request_count; + + return result; + } + + object = PyFloat_FromDouble(apr_time_sec((double)start_time)); + PyDict_SetItem(result, + WSGI_INTERNED_STRING(start_time), object); + Py_DECREF(object); + + object = PyFloat_FromDouble(apr_time_sec((double)stop_time)); + PyDict_SetItem(result, + WSGI_INTERNED_STRING(stop_time), object); + Py_DECREF(object); + + time_interval = (apr_time_sec((double)stop_time) - + apr_time_sec((double)start_time)); + + object = PyFloat_FromDouble(time_interval); + PyDict_SetItem(result, + WSGI_INTERNED_STRING(time_interval), object); + Py_DECREF(object); + + object = wsgi_PyInt_FromLong(max_threads); + PyDict_SetItem(result, + WSGI_INTERNED_STRING(max_threads), object); + Py_DECREF(object); + + object = wsgi_PyInt_FromLong(wsgi_request_threads); + PyDict_SetItem(result, + WSGI_INTERNED_STRING(request_threads), object); + Py_DECREF(object); + + object = wsgi_PyInt_FromLong(wsgi_active_requests); + PyDict_SetItem(result, + WSGI_INTERNED_STRING(active_requests), object); + Py_DECREF(object); + + request_busy_time = stop_request_busy_time - start_request_busy_time; + capacity_utilization = (request_busy_time / wsgi_request_threads); + + object = PyFloat_FromDouble(capacity_utilization); + PyDict_SetItem(result, + WSGI_INTERNED_STRING(utilization), object); + Py_DECREF(object); + + request_count = stop_request_count - start_request_count; + + object = wsgi_PyInt_FromLongLong(request_count); + PyDict_SetItem(result, + WSGI_INTERNED_STRING(request_count), object); + Py_DECREF(object); + + requests_per_sec = time_interval ? request_count / time_interval : 0; + + object = PyFloat_FromDouble(requests_per_sec); + PyDict_SetItem(result, + WSGI_INTERNED_STRING(requests_per_sec), object); + Py_DECREF(object); + + start_time = stop_time; + start_request_busy_time = stop_request_busy_time; + start_request_count = stop_request_count; + + return result; +} + +PyMethodDef wsgi_request_metrics_method[] = { + { "request_metrics", (PyCFunction)wsgi_request_metrics, + METH_NOARGS, 0 }, + { NULL }, +}; + +/* ------------------------------------------------------------------------- */ + static PyObject *wsgi_process_metrics(void) { PyObject *result = NULL; @@ -279,25 +423,6 @@ static PyObject *wsgi_process_metrics(void) if (!wsgi_interns_initialized) wsgi_initialize_interned_strings(); -#if 0 - if (!wsgi_daemon_pool) { - if (!wsgi_server_config->server_metrics) { - Py_INCREF(Py_None); - - return Py_None; - } - } -#if defined(MOD_WSGI_WITH_DAEMONS) - else { - if (!wsgi_daemon_process->group->server_metrics) { - Py_INCREF(Py_None); - - return Py_None; - } - } -#endif -#endif - result = PyDict_New(); object = wsgi_PyInt_FromLong(getpid()); diff --git a/src/server/wsgi_metrics.h b/src/server/wsgi_metrics.h index 9d69806..90dd64a 100644 --- a/src/server/wsgi_metrics.h +++ b/src/server/wsgi_metrics.h @@ -33,6 +33,8 @@ extern int wsgi_active_requests; extern apr_thread_mutex_t* wsgi_monitor_lock; +extern PyMethodDef wsgi_request_metrics_method[]; + extern PyMethodDef wsgi_process_metrics_method[]; extern WSGIThreadInfo *wsgi_start_request(request_rec *r); |
