MINOR: sample: add new sample fetch functions reporting current CPU usage
Some checks are pending
Contrib / dev/flags/ (push) Waiting to run
Contrib / dev/haring/ (push) Waiting to run
Contrib / dev/hpack/ (push) Waiting to run
Contrib / dev/poll/ (push) Waiting to run
VTest / Generate Build Matrix (push) Waiting to run
VTest / (push) Blocked by required conditions
VTest / Alpine+musl, gcc (push) Waiting to run
Windows / Windows, gcc, all features (push) Waiting to run

Some features can automatically turn on or off depending on CPU usage,
but it's not easy to measure it. Let's provide 3 new sample fetch functions
reporting the CPU usage as measured inside haproxy during the previous
polling loop, and reported in "idle" stats header / "show info", or used
by tune.glitches.kill.cpu-usage, or maxcompcpuusage:

  - cpu_usage_thr: CPU usage between 0 and 100 of the current thread, used
    by functions above
  - cpu_usage_grp: CPU usage between 0 and 100, averaged over all threads of
    the same group as the current one.
  - cpu_usage_proc: CPU usage between 0 and 100, averaged over all threads
    of the current process

Note that the value will fluctuate since it only covers a few tens to
hundreds of requests of the last polling loop, but it reports what is
being used to take decisions.

It could also be used to disable some non-essential debugging/processing
under too high loads for example.
This commit is contained in:
Willy Tarreau 2026-04-14 17:42:36 +02:00
parent 630ef96f92
commit 90e8ccd9c2
2 changed files with 64 additions and 0 deletions

View file

@ -23672,6 +23672,30 @@ cpu_ns_tot : integer
high cpu_calls count, for example when processing many HTTP chunks, and for
this reason it is often preferred to log cpu_ns_avg instead.
cpu_usage_grp : integer
Returns the measured CPU usage over the last polling loop, between 0 and 100,
averaged over all threads of the current thread group. This can be used for
troubleshooting and for logging. The measure is extremely volatile but will
remain accurate for sustained loads as each thread measures it over a few
tens to hundreds of requests.
cpu_usage_proc : integer
Returns the measured CPU usage over the last polling loop, between 0 and 100,
averaged over all running threads. This can be used for troubleshooting and
for logging. The measure is extremely volatile but will remain accurate for
sustained loads as each thread measures it over a few tens to hundreds of
requests. This is 100 minus the value reported in the idle ratio in the stats
page and in "show info".
cpu_usage_thr : integer
Returns the measured CPU usage over the last polling loop, between 0 and 100,
for the calling thread. This can be used for troubleshooting and for logging.
The measure is extremely volatile but will remain accurate for sustained
loads as it is measured over a few tens to hundreds of requests. This is the
same value as used to decide to enable connection killing on too high
glitches, or to disable compression. See also "tune.glitches.kill.cpu-usage"
and "maxcomcpuusage".
date([<offset>[,<unit>]]) : integer
Returns the current date as the epoch (number of seconds since 01/01/1970).

View file

@ -5089,6 +5089,43 @@ smp_fetch_tgroup(const struct arg *args, struct sample *smp, const char *kw, voi
return 1;
}
/* returns the last known CPU usage of the current thread */
static int
smp_fetch_cpu_usage_thr(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
smp->data.type = SMP_T_SINT;
smp->data.u.sint = 100 - th_ctx->idle_pct;
return 1;
}
/* returns the last known CPU usage of the current thread group */
static int
smp_fetch_cpu_usage_grp(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
uint thr, tot = 0;
for (thr = 0; thr < ha_tgroup_info[tgid - 1].count; thr++)
tot += 100 - ha_thread_ctx[ha_tgroup_info[tgid - 1].base + thr].idle_pct;
smp->data.type = SMP_T_SINT;
smp->data.u.sint = (tot + thr / 2) / thr;
return 1;
}
/* returns the last known CPU usage of the whole process */
static int
smp_fetch_cpu_usage_proc(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
int thr, tot = 0;
for (thr = 0; thr < global.nbthread; thr++)
tot += 100 - ha_thread_ctx[thr].idle_pct;
smp->data.type = SMP_T_SINT;
smp->data.u.sint = (tot + thr / 2) / thr;
return 1;
}
/* generate a random 32-bit integer for whatever purpose, with an optional
* range specified in argument.
*/
@ -5677,6 +5714,9 @@ static struct sample_fetch_kw_list smp_kws = {ILH, {
{ "cpu_calls", smp_fetch_cpu_calls, 0, NULL, SMP_T_SINT, SMP_USE_INTRN },
{ "cpu_ns_avg", smp_fetch_cpu_ns_avg, 0, NULL, SMP_T_SINT, SMP_USE_INTRN },
{ "cpu_ns_tot", smp_fetch_cpu_ns_tot, 0, NULL, SMP_T_SINT, SMP_USE_INTRN },
{ "cpu_usage_grp", smp_fetch_cpu_usage_grp, 0, NULL, SMP_T_SINT, SMP_USE_INTRN },
{ "cpu_usage_proc",smp_fetch_cpu_usage_proc, 0, NULL, SMP_T_SINT, SMP_USE_INTRN },
{ "cpu_usage_thr", smp_fetch_cpu_usage_thr, 0, NULL, SMP_T_SINT, SMP_USE_INTRN },
{ "lat_ns_avg", smp_fetch_lat_ns_avg, 0, NULL, SMP_T_SINT, SMP_USE_INTRN },
{ "lat_ns_tot", smp_fetch_lat_ns_tot, 0, NULL, SMP_T_SINT, SMP_USE_INTRN },