From: Stephan Bosch Date: Tue, 28 Mar 2017 23:25:21 +0000 (+0200) Subject: lib-http: client: Implemented means to obtain request statistics. X-Git-Tag: 2.2.29.rc1~34 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c8379b41835b3605e293ba9d2dd6b54c9b0d5edd;p=thirdparty%2Fdovecot%2Fcore.git lib-http: client: Implemented means to obtain request statistics. --- diff --git a/src/lib-http/http-client-connection.c b/src/lib-http/http-client-connection.c index a79e70c717..91238c1e56 100644 --- a/src/lib-http/http-client-connection.c +++ b/src/lib-http/http-client-connection.c @@ -222,40 +222,14 @@ static const char * http_client_connection_get_timing_info(struct http_client_connection *conn) { struct http_client_request *const *requestp; - unsigned int sent_msecs, total_msecs, connected_msecs; + unsigned int connected_msecs; string_t *str = t_str_new(64); if (array_count(&conn->request_wait_list) > 0) { requestp = array_idx(&conn->request_wait_list, 0); - sent_msecs = timeval_diff_msecs(&ioloop_timeval, &(*requestp)->sent_time); - total_msecs = timeval_diff_msecs(&ioloop_timeval, &(*requestp)->submit_time); - - str_printfa(str, "Request sent %u.%03u secs ago", - sent_msecs/1000, sent_msecs%1000); - if ((*requestp)->attempts > 0) { - str_printfa(str, ", %u attempts in %u.%03u secs", - (*requestp)->attempts + 1, - total_msecs/1000, total_msecs%1000); - } - int other_ioloop_msecs = (ioloop_global_wait_usecs - - (*requestp)->sent_global_ioloop_usecs + 999) / 1000; - if (conn->client->ioloop != NULL) { - int http_ioloop_msecs = - (io_wait_timer_get_usecs(conn->io_wait_timer) - - (*requestp)->sent_http_ioloop_usecs + 999) / 1000; - other_ioloop_msecs -= http_ioloop_msecs; - str_printfa(str, ", %d.%03d in http ioloop", - http_ioloop_msecs/1000, http_ioloop_msecs%1000); - } - str_printfa(str, ", %d.%03d in other ioloops", - other_ioloop_msecs/1000, other_ioloop_msecs%1000); - - int lock_msecs = (file_lock_wait_get_total_usecs() - - (*requestp)->sent_lock_usecs + 999) / 1000; - if (lock_msecs > 0) { - str_printfa(str, ", %d.%03d in locks", - lock_msecs/1000, lock_msecs%1000); - } + + str_append(str, "Request "); + http_client_request_append_stats_text(*requestp, str); } else { str_append(str, "No requests"); if (conn->conn.last_input != 0) { diff --git a/src/lib-http/http-client-request.c b/src/lib-http/http-client-request.c index 43b9acea3c..88fb90db80 100644 --- a/src/lib-http/http-client-request.c +++ b/src/lib-http/http-client-request.c @@ -582,6 +582,93 @@ http_client_request_get_state(const struct http_client_request *req) return req->state; } +void http_client_request_get_stats(struct http_client_request *req, + struct http_client_request_stats *stats_r) +{ + struct http_client *client = req->client; + int diff_msecs; + uint64_t wait_usecs; + + i_zero(stats_r); + if (!req->submitted) + return; + + /* total elapsed time since message was submitted */ + diff_msecs = timeval_diff_msecs(&ioloop_timeval, &req->submit_time); + stats_r->total_msecs = (unsigned int)I_MAX(diff_msecs, 0); + + /* elapsed time since message was last sent */ + if (req->sent_time.tv_sec > 0) { + diff_msecs = timeval_diff_msecs(&ioloop_timeval, &req->sent_time); + stats_r->sent_msecs = (unsigned int)I_MAX(diff_msecs, 0); + } + + if (req->conn != NULL) { + /* time spent in other ioloops */ + i_assert(ioloop_global_wait_usecs >= req->sent_global_ioloop_usecs); + stats_r->other_ioloop_msecs = (unsigned int) + (ioloop_global_wait_usecs - req->sent_global_ioloop_usecs + 999) / 1000; + + /* time spent in the http-client's own ioloop */ + if (client->ioloop != NULL) { + wait_usecs = io_wait_timer_get_usecs(req->conn->io_wait_timer); + i_assert(wait_usecs >= req->sent_http_ioloop_usecs); + stats_r->http_ioloop_msecs = (unsigned int) + (wait_usecs - req->sent_http_ioloop_usecs + 999) / 1000; + + i_assert(stats_r->other_ioloop_msecs >= stats_r->http_ioloop_msecs); + stats_r->other_ioloop_msecs -= stats_r->http_ioloop_msecs; + } + } + + /* total time spent on waiting for file locks */ + wait_usecs = file_lock_wait_get_total_usecs(); + i_assert(wait_usecs >= req->sent_lock_usecs); + stats_r->lock_msecs = (unsigned int) + (wait_usecs - req->sent_lock_usecs + 999) / 1000; + + /* number of attempts for this request */ + stats_r->attempts = req->attempts; + +} + +void http_client_request_append_stats_text(struct http_client_request *req, + string_t *str) +{ + struct http_client_request_stats stats; + + if (!req->submitted) { + str_append(str, "not yet submitted"); + return; + } + + http_client_request_get_stats(req, &stats); + + if (stats.sent_msecs > 0) { + str_printfa(str, "sent %u.%03u secs ago", + stats.sent_msecs/1000, stats.sent_msecs%1000); + } else { + str_append(str, "not yet sent"); + } + if (stats.attempts > 0) { + str_printfa(str, ", %u attempts in %u.%03u secs", + stats.attempts + 1, + stats.total_msecs/1000, stats.total_msecs%1000); + } + if (stats.http_ioloop_msecs > 0) { + str_printfa(str, ", %u.%03u in http ioloop", + stats.http_ioloop_msecs/1000, + stats.http_ioloop_msecs%1000); + } + str_printfa(str, ", %u.%03u in other ioloops", + stats.other_ioloop_msecs/1000, stats.other_ioloop_msecs%1000); + + if (stats.lock_msecs > 0) { + str_printfa(str, ", %u.%03u in locks", + stats.lock_msecs/1000, stats.lock_msecs%1000); + } +} + enum http_response_payload_type http_client_request_get_payload_type(struct http_client_request *req) { diff --git a/src/lib-http/http-client.h b/src/lib-http/http-client.h index 44a36ca74c..0a04b3441c 100644 --- a/src/lib-http/http-client.h +++ b/src/lib-http/http-client.h @@ -183,6 +183,23 @@ struct http_client_tunnel { struct ostream *output; }; +struct http_client_request_stats { + /* Total elapsed time since message was submitted */ + unsigned int total_msecs; + /* Elapsed time since message was last sent */ + unsigned int sent_msecs; + + /* Time spent in other ioloops */ + unsigned int other_ioloop_msecs; + /* Time spent in the http-client's own ioloop */ + unsigned int http_ioloop_msecs; + /* Total time spent on waiting for file locks */ + unsigned int lock_msecs; + + /* Number of attempts for this request */ + unsigned int attempts; +}; + typedef void http_client_request_callback_t(const struct http_response *response, void *context); @@ -347,6 +364,13 @@ enum http_request_state http_client_request_get_state(const struct http_client_request *req) ATTR_PURE; +/* get statistics for the request */ +void http_client_request_get_stats(struct http_client_request *req, + struct http_client_request_stats *stats); +/* append text with request statistics to provided string buffer */ +void http_client_request_append_stats_text(struct http_client_request *req, + string_t *str); + /* submit the request. It is queued for transmission to the service */ void http_client_request_submit(struct http_client_request *req);