From: Willy Tarreau Date: Tue, 17 Jun 2014 10:19:18 +0000 (+0200) Subject: MEDIUM: session: maintain per-backend and per-server time statistics X-Git-Tag: v1.5.0~18 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4bfc580dd36e97b95bc747a93e4819d600b091c1;p=thirdparty%2Fhaproxy.git MEDIUM: session: maintain per-backend and per-server time statistics Using the last rate counters, we now compute the queue, connect, response and total times per server and per backend with a 95% accuracy over the last 1024 samples. The operation is cheap so we don't need to condition it. --- diff --git a/include/common/defaults.h b/include/common/defaults.h index bdd75cf90b..8d5d62a6fe 100644 --- a/include/common/defaults.h +++ b/include/common/defaults.h @@ -219,4 +219,15 @@ #define SSL_DEFAULT_DH_PARAM 0 #endif +/* Number of samples used to compute the times reported in stats. A power of + * two is highly recommended, and this value multiplied by the largest response + * time must not overflow and unsigned int. See freq_ctr.h for more information. + * We consider that values are accurate to 95% with two batches of samples below, + * so in order to advertise accurate times across 1k samples, we effectively + * measure over 512. + */ +#ifndef TIME_STATS_SAMPLES +#define TIME_STATS_SAMPLES 512 +#endif + #endif /* _COMMON_DEFAULTS_H */ diff --git a/include/proto/session.h b/include/proto/session.h index fc83989f2d..c835bf0778 100644 --- a/include/proto/session.h +++ b/include/proto/session.h @@ -50,6 +50,9 @@ int parse_track_counters(char **args, int *arg, struct track_ctr_prm *prm, struct proxy *defpx, char **err); +/* Update the session's backend and server time stats */ +void session_update_time_stats(struct session *s); + /* returns the session from a void *owner */ static inline struct session *session_from_task(struct task *t) { diff --git a/include/types/counters.h b/include/types/counters.h index ecdc7cb958..172f8a6413 100644 --- a/include/types/counters.h +++ b/include/types/counters.h @@ -3,7 +3,7 @@ * This file contains structure declarations for statistics counters. * * Copyright 2008-2009 Krzysztof Piotr Oledzki - * Copyright 2011 Willy Tarreau + * Copyright 2011-2014 Willy Tarreau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -55,6 +55,8 @@ struct pxcounters { long long redispatches; /* retried and redispatched connections (BE only) */ long long intercepted_req; /* number of monitoring or stats requests intercepted by the frontend */ + unsigned int q_time, c_time, d_time, t_time; /* sums of conn_time, queue_time, data_time, total_time */ + union { struct { long long cum_req; /* cumulated number of processed HTTP requests */ @@ -96,6 +98,8 @@ struct srvcounters { long long retries, redispatches; /* retried and redispatched connections */ long long failed_secu; /* blocked responses because of security concerns */ + unsigned int q_time, c_time, d_time, t_time; /* sums of conn_time, queue_time, data_time, total_time */ + union { struct { long long rsp[6]; /* http response codes */ diff --git a/src/proto_http.c b/src/proto_http.c index 082f1616de..48dbc43cc7 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -4714,6 +4714,8 @@ void http_end_txn_clean_session(struct session *s) s->do_log(s); } + session_update_time_stats(s); + s->logs.accept_date = date; /* user-visible date for logging */ s->logs.tv_accept = now; /* corrected date for internal use */ tv_zero(&s->logs.tv_request); diff --git a/src/session.c b/src/session.c index 4412125ba4..f828d9c2e0 100644 --- a/src/session.c +++ b/src/session.c @@ -2600,6 +2600,9 @@ struct task *process_session(struct task *t) s->do_log(s); } + /* update time stats for this session */ + session_update_time_stats(s); + /* the task MUST not be in the run queue anymore */ session_free(s); task_delete(t); @@ -2607,6 +2610,48 @@ struct task *process_session(struct task *t) return NULL; } +/* Update the session's backend and server time stats */ +void session_update_time_stats(struct session *s) +{ + int t_request; + int t_queue; + int t_connect; + int t_data; + int t_close; + struct server *srv; + + t_request = 0; + t_queue = s->logs.t_queue; + t_connect = s->logs.t_connect; + t_close = s->logs.t_close; + t_data = s->logs.t_data; + + if (s->be->mode != PR_MODE_HTTP) + t_data = t_connect; + + if (t_connect < 0 || t_data < 0) + return; + + if (tv_isge(&s->logs.tv_request, &s->logs.tv_accept)) + t_request = tv_ms_elapsed(&s->logs.tv_accept, &s->logs.tv_request); + + t_data -= t_connect; + t_connect -= t_queue; + t_queue -= t_request; + + srv = objt_server(s->target); + if (srv) { + swrate_add(&srv->counters.q_time, TIME_STATS_SAMPLES, t_queue); + swrate_add(&srv->counters.c_time, TIME_STATS_SAMPLES, t_connect); + swrate_add(&srv->counters.d_time, TIME_STATS_SAMPLES, t_data); + swrate_add(&srv->counters.t_time, TIME_STATS_SAMPLES, t_close); + } + swrate_add(&s->be->be_counters.q_time, TIME_STATS_SAMPLES, t_queue); + swrate_add(&s->be->be_counters.c_time, TIME_STATS_SAMPLES, t_connect); + swrate_add(&s->be->be_counters.d_time, TIME_STATS_SAMPLES, t_data); + swrate_add(&s->be->be_counters.t_time, TIME_STATS_SAMPLES, t_close); +} + /* * This function adjusts sess->srv_conn and maintains the previous and new * server's served session counts. Setting newsrv to NULL is enough to release