From 51c778e62fb362c59b6b316fa9fadd258755a4f8 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Sat, 4 Oct 2025 12:43:59 +0000 Subject: [PATCH] sources: Add PSI for CPU Signed-off-by: Michael Tremer --- Makefile.am | 2 + src/daemon/proc.c | 64 +++++++++++++++++++++++++++++++ src/daemon/proc.h | 14 +++++++ src/daemon/sources.c | 2 + src/daemon/sources/pressure-cpu.c | 62 ++++++++++++++++++++++++++++++ src/daemon/sources/pressure-cpu.h | 28 ++++++++++++++ 6 files changed, 172 insertions(+) create mode 100644 src/daemon/sources/pressure-cpu.c create mode 100644 src/daemon/sources/pressure-cpu.h diff --git a/Makefile.am b/Makefile.am index 17da441..6fc22a5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -132,6 +132,8 @@ dist_collectyd_SOURCES = \ src/daemon/sources/contextswitches.h \ src/daemon/sources/loadavg.c \ src/daemon/sources/loadavg.h \ + src/daemon/sources/pressure-cpu.c \ + src/daemon/sources/pressure-cpu.h \ src/daemon/sources/processor.c \ src/daemon/sources/processor.h \ src/daemon/util.c \ diff --git a/src/daemon/proc.c b/src/daemon/proc.c index cf27c0e..e22f6ef 100644 --- a/src/daemon/proc.c +++ b/src/daemon/proc.c @@ -117,3 +117,67 @@ ERROR: return r; } + +static int collecty_proc_read_pressure_line(collecty_ctx* ctx, + const char* line, collecty_pressure_stats* stats) { + int r; + + // Try parsing the some line + r = sscanf(line, "some avg10=%lf avg60=%lf avg300=%lf total=%lu\n", + &stats->some.avg10, &stats->some.avg60, &stats->some.avg300, &stats->some.total); + if (r) + return r; + + // Try parsing the full line + r = sscanf(line, "full avg10=%lf avg60=%lf avg300=%lf total=%lu\n", + &stats->full.avg10, &stats->full.avg60, &stats->full.avg300, &stats->full.total); + if (r) + return r; + + return 0; +} + +int collecty_proc_read_pressure(collecty_ctx* ctx, + const char* what, collecty_pressure_stats* stats) { + char path[PATH_MAX]; + char* line = NULL; + size_t length = 0; + FILE* f = NULL; + int r; + + // Make the path + r = snprintf(path, sizeof(path), "/proc/pressure/%s", what); + if (r < 0) + return -errno; + + // Open the file + f = fopen(path, "r"); + if (!f) { + ERROR(ctx, "Failed to open %s: %m\n", path); + r = -errno; + goto ERROR; + } + + // Walk through all lines + for (;;) { + r = getline(&line, &length, f); + if (r < 0) + break; + + // Process the line + r = collecty_proc_read_pressure_line(ctx, line, stats); + if (r < 0) + goto ERROR; + } + + // Reset r + r = 0; + +ERROR: + if (line) + free(line); + if (f) + fclose(f); + + return r; +} diff --git a/src/daemon/proc.h b/src/daemon/proc.h index 8d08f87..e3f6aae 100644 --- a/src/daemon/proc.h +++ b/src/daemon/proc.h @@ -28,4 +28,18 @@ int collecty_proc_read_stat(collecty_ctx* ctx, const char* tag, unsigned long* fields, size_t max_fields); +typedef struct collecty_pressure_stats { + struct collecty_pressure_stats_values { + double avg10; + double avg60; + double avg300; + unsigned long total; + } some; + + struct collecty_pressure_stats_values full; +} collecty_pressure_stats; + +int collecty_proc_read_pressure(collecty_ctx* ctx, + const char* what, collecty_pressure_stats* stats); + #endif /* COLLECTY_PROC_H */ diff --git a/src/daemon/sources.c b/src/daemon/sources.c index 4f6631c..7065584 100644 --- a/src/daemon/sources.c +++ b/src/daemon/sources.c @@ -31,6 +31,7 @@ #include "sources/conntrack.h" #include "sources/contextswitches.h" #include "sources/loadavg.h" +#include "sources/pressure-cpu.h" #include "sources/processor.h" // Register all sources @@ -38,6 +39,7 @@ static const collecty_source_impl* source_impls[] = { &conntrack_source, &contextswitches_source, &loadavg_source, + &pressure_cpu_source, &processor_source, NULL, }; diff --git a/src/daemon/sources/pressure-cpu.c b/src/daemon/sources/pressure-cpu.c new file mode 100644 index 0000000..8bcbcca --- /dev/null +++ b/src/daemon/sources/pressure-cpu.c @@ -0,0 +1,62 @@ +/*############################################################################# +# # +# collecty - A system statistics collection daemon for IPFire # +# Copyright (C) 2025 IPFire Development Team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +#############################################################################*/ + +#include "../ctx.h" +#include "../proc.h" +#include "../source.h" +#include "pressure-cpu.h" + +static int pressure_cpu_collect(collecty_ctx* ctx, collecty_source* source) { + collecty_pressure_stats stats = {}; + int r; + + // Read all values from /proc/pressure/cpu + r = collecty_proc_read_pressure(ctx, "cpu", &stats); + if (r < 0) + return r; + + // Submit the values + return collecty_source_submit(source, NULL, "%.2f:%.2f:%.2f:%lu:%.2f:%.2f:%.2f:%lu", + stats.some.avg10, stats.some.avg60, stats.some.avg300, stats.some.total, + stats.full.avg10, stats.full.avg60, stats.full.avg300, stats.full.total); +} + +const collecty_source_impl pressure_cpu_source = { + .name = "pressure-cpu", + + // RRD Data Sources + .rrd_dss = { + // some + { "some_avg10", "GAUGE", 0, 100, }, + { "some_avg60", "GAUGE", 0, 100, }, + { "some_avg300", "GAUGE", 0, 100, }, + { "some_total", "DERIVE", 0, -1, }, + + // full + { "full_avg10", "GAUGE", 0, 100, }, + { "full_avg60", "GAUGE", 0, 100, }, + { "full_avg300", "GAUGE", 0, 100, }, + { "full_total", "DERIVE", 0, -1, }, + { NULL }, + }, + + // Methods + .collect = pressure_cpu_collect, +}; diff --git a/src/daemon/sources/pressure-cpu.h b/src/daemon/sources/pressure-cpu.h new file mode 100644 index 0000000..17db195 --- /dev/null +++ b/src/daemon/sources/pressure-cpu.h @@ -0,0 +1,28 @@ +/*############################################################################# +# # +# collecty - A system statistics collection daemon for IPFire # +# Copyright (C) 2025 IPFire Development Team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +#############################################################################*/ + +#ifndef COLLECTY_SOURCE_PRESSURE_CPU_H +#define COLLECTY_SOURCE_PRESSURE_CPU_H + +#include "../source.h" + +extern const collecty_source_impl pressure_cpu_source; + +#endif /* COLLECTY_SOURCE_PRESSURE_CPU_H */ -- 2.47.3