From a6964cfb4f3e5ec2c4f880111e7b76baa3bf7f6f Mon Sep 17 00:00:00 2001 From: William Lallemand Date: Mon, 3 Jul 2023 11:28:43 +0200 Subject: [PATCH] MINOR: sample: implement the T* timer tags from the log-format as fetches This commit implements the following timer tags available in the log format as sample fetches: req.timer.idle (%Ti) req.timer.tq (%Tq) req.timer.hdr (%TR) req.timer.queue (%Tw) res.timer.hdr (%Tr) res.timer.user (%Tu) txn.timer.total (%Ta) txn.timer.data (%Td) bc.timer.connect (%Tc) fc.timer.handshake (%Th) fc.timer.total (%Tt) --- src/sample.c | 187 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) diff --git a/src/sample.c b/src/sample.c index 2fd7b357a..bbb17d39f 100644 --- a/src/sample.c +++ b/src/sample.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -4739,6 +4740,192 @@ static int smp_fetch_quic_enabled(const struct arg *args, struct sample *smp, co return smp->data.u.sint; } +/* Timing events re{q,s}.timer. */ +static int smp_fetch_reX_timers(const struct arg *args, struct sample *smp, const char *kw, void *private) +{ + struct strm_logs *logs; + int t_request = -1; + + if (!smp->strm) + return 0; + + smp->data.type = SMP_T_SINT; + smp->flags = 0; + + logs = &smp->strm->logs; + + + if ((llong)(logs->request_ts - logs->accept_ts) >= 0) + t_request = ns_to_ms(logs->request_ts - logs->accept_ts); + + /* req.timer. */ + if (kw[2] == 'q') { + + switch (kw[10]) { + + /* req.timer.idle (%Ti) */ + case 'i': + smp->data.u.sint = logs->t_idle; + break; + + /* req.timer.tq (%Tq) */ + case 't': + smp->data.u.sint = t_request; + break; + + /* req.timer.hdr (%TR) */ + case 'h': + smp->data.u.sint = (t_request >= 0) ? t_request - logs->t_idle - logs->t_handshake : -1; + break; + + /* req.timer.queue (%Tw) */ + case 'q': + smp->data.u.sint = (logs->t_queue >= 0) ? logs->t_queue - t_request : -1; + break; + + default: + goto error; + + } + } else { + /* res.timer. */ + switch (kw[10]) { + /* res.timer.hdr (%Tr) */ + case 'h': + smp->data.u.sint = (logs->t_data >= 0) ? logs->t_data - logs->t_connect : -1; + break; + + /* res.timer.data (%Td) */ + case 'd': + smp->data.u.sint = (logs->t_data >= 0) ? logs->t_close - logs->t_data : -1; + break; + + default: + goto error; + + } + + } + + return 1; +error: + + return 0; + } + + +/* Timing events txn. */ +static int smp_fetch_txn_timers(const struct arg *args, struct sample *smp, const char *kw, void *private) +{ + struct strm_logs *logs; + + if (!smp->strm) + return 0; + + smp->data.type = SMP_T_SINT; + smp->flags = 0; + + logs = &smp->strm->logs; + + /* txn.timer. */ + switch (kw[10]) { + + /* txn.timer.total (%Ta) */ + case 't': + smp->data.u.sint = logs->t_close - (logs->t_idle >= 0 ? logs->t_idle + logs->t_handshake : 0); + break; + + + /* txn.timer.user (%Tu) */ + case 'u': + smp->data.u.sint = logs->t_close - (logs->t_idle >= 0 ? logs->t_idle : 0); + break; + + default: + goto error; + + } + + return 1; +error: + + return 0; +} + +/* Timing events {f,bc}.timer. */ +static int smp_fetch_conn_timers(const struct arg *args, struct sample *smp, const char *kw, void *private) +{ + struct strm_logs *logs; + + if (!smp->strm) + return 0; + + smp->data.type = SMP_T_SINT; + smp->flags = 0; + + logs = &smp->strm->logs; + + if (kw[0] == 'b') { + /* fc.timer. */ + switch (kw[9]) { + + /* bc.timer.connect (%Tc) */ + case 'c': + smp->data.u.sint = (logs->t_connect >= 0) ? logs->t_connect - logs->t_queue : -1; + break; + + default: + goto error; + } + + } else { + + /* fc.timer. */ + switch (kw[9]) { + + /* fc.timer.handshake (%Th) */ + case 'h': + smp->data.u.sint = logs->t_handshake; + break; + + /* fc,timer.total (%Tt) */ + case 't': + smp->data.u.sint = logs->t_close; + break; + + default: + goto error; + } + + } + + return 1; +error: + + return 0; +} + + + +static struct sample_fetch_kw_list smp_logs_kws = {ILH, { + { "txn.timer.total", smp_fetch_txn_timers, 0, NULL, SMP_T_SINT, SMP_USE_TXFIN }, /* "Ta" */ + { "txn.timer.user", smp_fetch_txn_timers, 0, NULL, SMP_T_SINT, SMP_USE_TXFIN }, /* "Tu" */ + + { "bc.timer.connect", smp_fetch_conn_timers, 0, NULL, SMP_T_SINT, SMP_USE_L4SRV }, /* "Tc" */ + { "fc.timer.handshake", smp_fetch_conn_timers, 0, NULL, SMP_T_SINT, SMP_USE_L4CLI }, /* "Th" */ + { "fc.timer.total", smp_fetch_conn_timers, 0, NULL, SMP_T_SINT, SMP_USE_SSFIN }, /* "Tt" */ + + { "req.timer.idle", smp_fetch_reX_timers, 0, NULL, SMP_T_SINT, SMP_USE_HRQHV }, /* "Ti" */ + { "req.timer.tq", smp_fetch_reX_timers, 0, NULL, SMP_T_SINT, SMP_USE_HRQHV }, /* "Tq" */ + { "req.timer.hdr", smp_fetch_reX_timers, 0, NULL, SMP_T_SINT, SMP_USE_HRQHV }, /* "TR" */ + { "req.timer.queue", smp_fetch_reX_timers, 0, NULL, SMP_T_SINT, SMP_USE_L4SRV }, /* "Tw" */ + { "res.timer.data", smp_fetch_reX_timers, 0, NULL, SMP_T_SINT, SMP_USE_RSFIN }, /* "Td" */ + { "res.timer.hdr", smp_fetch_reX_timers, 0, NULL, SMP_T_SINT, SMP_USE_HRSHV }, /* "Tr" */ + { /* END */ }, +}}; + +INITCALL1(STG_REGISTER, sample_register_fetches, &smp_logs_kws); + /* Note: must not be declared as its list will be overwritten. * Note: fetches that may return multiple types should be declared using the * appropriate pseudo-type. If not available it must be declared as the lowest