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.
This commit is contained in:
Willy Tarreau 2014-06-17 12:19:18 +02:00
parent 2438f2b984
commit 4bfc580dd3
5 changed files with 66 additions and 1 deletions

View File

@ -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 */

View File

@ -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)
{

View File

@ -3,7 +3,7 @@
* This file contains structure declarations for statistics counters.
*
* Copyright 2008-2009 Krzysztof Piotr Oledzki <ole@ans.pl>
* Copyright 2011 Willy Tarreau <w@1wt.eu>
* Copyright 2011-2014 Willy Tarreau <w@1wt.eu>
*
* 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 */

View File

@ -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);

View File

@ -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