From: Michael Tremer Date: Fri, 27 Mar 2026 14:28:32 +0000 (+0000) Subject: sensors: Generalize processing all sensors X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8f21df2e77a680176355e0e5e05f6958b01518db;p=telemetry.git sensors: Generalize processing all sensors Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index 3dd97fe..52ce538 100644 --- a/Makefile.am +++ b/Makefile.am @@ -174,6 +174,8 @@ dist_telemetryd_SOURCES = \ src/daemon/proto.h \ src/daemon/queue.c \ src/daemon/queue.h \ + src/daemon/sensors.c \ + src/daemon/sensors.h \ src/daemon/source.c \ src/daemon/source.h \ src/daemon/sources.c \ diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c index 2210033..21f11f7 100644 --- a/src/daemon/daemon.c +++ b/src/daemon/daemon.c @@ -40,6 +40,7 @@ #include "graph-bus.h" #include "metrics.h" #include "queue.h" +#include "sensors.h" #include "source.h" #include "sources.h" @@ -105,6 +106,13 @@ static int td_daemon_init(sd_event_source* source, void* data) { if (r < 0) return r; +#ifdef HAVE_SENSORS + // Initialize sensors + r = td_sensors_init(self->ctx); + if (r < 0) + return r; +#endif /* HAVE_SENSORS */ + return 0; } @@ -113,6 +121,11 @@ static int td_daemon_on_exit(sd_event_source* source, void* data) { DEBUG(self->ctx, "Cleaning up daemon...\n"); +#ifdef HAVE_SENSORS + // Cleanup sensors + td_sensors_cleanup(self->ctx); +#endif /* HAVE_SENSORS */ + // Free all graphs if (self->graphs) { td_graphs_unref(self->graphs); diff --git a/src/daemon/sensors.c b/src/daemon/sensors.c new file mode 100644 index 0000000..ea16eca --- /dev/null +++ b/src/daemon/sensors.c @@ -0,0 +1,162 @@ +/*############################################################################# +# # +# telemetryd - The IPFire Telemetry Collection Service # +# Copyright (C) 2026 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 . # +# # +#############################################################################*/ + +#ifdef HAVE_SENSORS + +#include + +#include +#include + +#include "ctx.h" +#include "sensors.h" +#include "source.h" +#include "string.h" + +static int sensors_initialized = 0; + +int td_sensors_init(td_ctx* ctx) { + int r = 0; + + // Initialize sensors if not already done + if (!sensors_initialized) { + r = sensors_init(NULL); + if (r) { + ERROR(ctx, "Failed to initialize sensors: %s\n", sensors_strerror(r)); + return -ENOTSUP; + } + + // We are now initialized + sensors_initialized = 1; + } + + return r; +} + +int td_sensors_cleanup(td_ctx* ctx) { + if (sensors_initialized) + sensors_cleanup(); + + return 0; +} + +static int td_sensors_join_name(char* name, size_t length, + const char* chip, const char* label) { + int r; + + // Copy everything info the buffer + r = __td_string_format(name, length, "%s-%s", chip, label); + if (r < 0) + return r; + + // Sanitize the name + for (char* p = name; *p; p++) { + // Convert everything to lower-case + if (isupper(*p)) { + *p = tolower(*p); + continue; + + // Replace whitespace with dashes + } else if (isspace(*p)) { + *p = '-'; + continue; + } + + // Replace a couple of special characters, too + switch (*p) { + case '/': + case ':': + *p = '-'; + break; + + default: + break; + } + } + + return 0; +} + +int __td_sensors_name(char* name, size_t length, + const sensors_chip_name* chip, const sensors_feature* feature) { + char chip_name[NAME_MAX]; + const char* label = NULL; + int r; + + // Make the chip name + r = sensors_snprintf_chip_name(chip_name, sizeof(chip_name), chip); + if (r < 0) + return r; + + // Fetch the label of the feature + label = sensors_get_label(chip, feature); + if (!label) + return -ENOTSUP; + + // Put everything together + return td_sensors_join_name(name, length, chip_name, label); +} + +int td_sensors_walk(td_ctx* ctx, td_source* source, + sensors_feature_type type, td_sensors_walk_callback callback, void* data) { + const sensors_feature* feature = NULL; + const sensors_chip_name* chip = NULL; + int feature_index = 0; + int chip_index = 0; + int r; + + // Initialize sensors + r = td_sensors_init(ctx); + if (r < 0) + return r; + + // Iterate over all chips + for (;;) { + chip = sensors_get_detected_chips(NULL, &chip_index); + if (!chip) + break; + + // Reset the feature index + feature_index = 0; + + // Reset r + r = 0; + + // Iterate over all features + for (;;) { + feature = sensors_get_features(chip, &feature_index); + if (!feature) + break; + + // Skip anything that does not match + if (feature->type != type) + continue; + + // Read the values + r = callback(ctx, source, type, chip, feature, data); + if (r < 0) + return r; + } + } + + return 0; +} + +#endif /* HAVE_SENSORS */ diff --git a/src/daemon/sensors.h b/src/daemon/sensors.h new file mode 100644 index 0000000..fbfe8d2 --- /dev/null +++ b/src/daemon/sensors.h @@ -0,0 +1,49 @@ +/*############################################################################# +# # +# telemetryd - The IPFire Telemetry Collection Service # +# Copyright (C) 2026 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 TELEMETRY_SENSORS_H +#define TELEMETRY_SENSORS_H + +#ifdef HAVE_SENSORS + +#include "ctx.h" +#include "source.h" + +#include + +int td_sensors_init(td_ctx* ctx); +int td_sensors_cleanup(td_ctx* ctx); + +#define td_sensors_name(name, chip, feature) \ + __td_sensors_name(name, sizeof(name), chip, feature) + +int __td_sensors_name(char* name, size_t length, + const sensors_chip_name* chip, const sensors_feature* feature); + +typedef int (*td_sensors_walk_callback)(td_ctx* ctx, td_source* source, + const sensors_feature_type type, const sensors_chip_name* chip, + const sensors_feature* feature, void* data); + +int td_sensors_walk(td_ctx* ctx, td_source* source, sensors_feature_type type, + td_sensors_walk_callback callback, void* data); + +#endif /* HAVE_SENSORS */ + +#endif /* TELEMETRY_SENSORS_H */ diff --git a/src/daemon/sources/sensors.c b/src/daemon/sources/sensors.c index be3483b..a3fd0ae 100644 --- a/src/daemon/sources/sensors.c +++ b/src/daemon/sources/sensors.c @@ -20,7 +20,6 @@ #ifdef BUILD_SOURCE_SENSORS -#include #include #include @@ -28,49 +27,10 @@ #include "../ctx.h" #include "../metrics.h" +#include "../sensors.h" #include "../source.h" -#include "../string.h" #include "sensors.h" -#define sensors_make_name(name, chip, label) \ - __sensors_make_name(name, sizeof(name), chip, label) - -static int __sensors_make_name(char* name, size_t length, const char* chip, const char* label) { - int r; - - // Copy everything info the buffer - r = __td_string_format(name, length, "%s-%s", chip, label); - if (r < 0) - return r; - - // Sanitize the name - for (char* p = name; *p; p++) { - // Convert everything to lower-case - if (isupper(*p)) { - *p = tolower(*p); - continue; - - // Replace whitespace with dashes - } else if (isspace(*p)) { - *p = '-'; - continue; - } - - // Replace a couple of special characters, too - switch (*p) { - case '/': - case ':': - *p = '-'; - break; - - default: - break; - } - } - - return 0; -} - typedef struct sensors_value { // Field const char* field; @@ -144,87 +104,37 @@ static int read_values(td_ctx* ctx, const sensors_chip_name* chip, return 0; } -static int read_sensors(td_ctx* ctx, td_source* source, - sensors_feature_type type, const sensors_value* values) { - const sensors_feature* feature = NULL; - const sensors_chip_name* chip = NULL; +static int read_sensor(td_ctx* ctx, td_source* source, + const sensors_feature_type type, const sensors_chip_name* chip, + const sensors_feature* feature, void* data) { + const sensors_value* values = data; td_metrics* metrics = NULL; - const char* label = NULL; - char chip_name[NAME_MAX]; char name[NAME_MAX]; - int feature_index = 0; - int chip_index = 0; int r; - // Initialize sensors - r = sensors_init(NULL); - if (r) { - ERROR(ctx, "Failed to initialize sensors: %s\n", sensors_strerror(r)); - return -ENOTSUP; - } - - // Iterate over all chips - for (;;) { - chip = sensors_get_detected_chips(NULL, &chip_index); - if (!chip) - break; - - // Make the chip name - r = sensors_snprintf_chip_name(chip_name, sizeof(chip_name), chip); - if (r < 0) - goto ERROR; - - // Reset the feature index - feature_index = 0; + // Fetch the name + r = td_sensors_name(name, chip, feature); + if (r < 0) + goto ERROR; - // Reset r - r = 0; + // Create metrics + r = td_source_create_metrics(source, &metrics, name); + if (r < 0) + goto ERROR; - // Iterate over all features - for (;;) { - feature = sensors_get_features(chip, &feature_index); - if (!feature) - break; + // Read the values + r = read_values(ctx, chip, feature, metrics, values); + if (r < 0) + goto ERROR; - // Skip anything that does not match - if (feature->type != type) - continue; - - // Fetch the label of the chip - label = sensors_get_label(chip, feature); - - // Format the whole name - r = sensors_make_name(name, chip_name, label); - if (r < 0) - goto ERROR; - - // Create metrics - r = td_source_create_metrics(source, &metrics, name); - if (r < 0) - goto ERROR; - - // Read the values - r = read_values(ctx, chip, feature, metrics, values); - if (r < 0) - goto ERROR; - - // Submit the metrics - r = td_source_submit_metrics(source, metrics); - if (r < 0) - goto ERROR; - - // Free the metrics - if (metrics) { - td_metrics_unref(metrics); - metrics = NULL; - } - } - } + // Submit the metrics + r = td_source_submit_metrics(source, metrics); + if (r < 0) + goto ERROR; ERROR: if (metrics) td_metrics_unref(metrics); - sensors_cleanup(); return r; } @@ -233,7 +143,7 @@ ERROR: (Voltage) Input */ static int sensors_input_heartbeat(td_ctx* ctx, td_source* source) { - const sensors_value values[] = { + sensors_value values[] = { { "current", SENSORS_SUBFEATURE_IN_INPUT }, { "min", SENSORS_SUBFEATURE_IN_MIN }, { "max", SENSORS_SUBFEATURE_IN_MAX }, @@ -251,7 +161,7 @@ static int sensors_input_heartbeat(td_ctx* ctx, td_source* source) { { NULL }, }; - return read_sensors(ctx, source, SENSORS_FEATURE_IN, values); + return td_sensors_walk(ctx, source, SENSORS_FEATURE_IN, read_sensor, values); } const td_source_impl sensors_input_source = { @@ -284,7 +194,7 @@ const td_source_impl sensors_input_source = { Fan */ static int sensors_fan_heartbeat(td_ctx* ctx, td_source* source) { - const sensors_value values[] = { + sensors_value values[] = { { "current", SENSORS_SUBFEATURE_FAN_INPUT }, { "min", SENSORS_SUBFEATURE_FAN_MIN }, { "max", SENSORS_SUBFEATURE_FAN_MAX }, @@ -298,7 +208,7 @@ static int sensors_fan_heartbeat(td_ctx* ctx, td_source* source) { { NULL }, }; - return read_sensors(ctx, source, SENSORS_FEATURE_FAN, values); + return td_sensors_walk(ctx, source, SENSORS_FEATURE_FAN, read_sensor, values); } const td_source_impl sensors_fan_source = { @@ -353,7 +263,7 @@ static int sensors_temp_heartbeat(td_ctx* ctx, td_source* source) { { NULL }, }; - return read_sensors(ctx, source, SENSORS_FEATURE_TEMP, values); + return td_sensors_walk(ctx, source, SENSORS_FEATURE_TEMP, read_sensor, values); } const td_source_impl sensors_temp_source = { @@ -416,7 +326,7 @@ static int sensors_power_heartbeat(td_ctx* ctx, td_source* source) { { NULL }, }; - return read_sensors(ctx, source, SENSORS_FEATURE_POWER, values); + return td_sensors_walk(ctx, source, SENSORS_FEATURE_POWER, read_sensor, values); } const td_source_impl sensors_power_source = { @@ -459,7 +369,7 @@ static int sensors_energy_heartbeat(td_ctx* ctx, td_source* source) { { NULL }, }; - return read_sensors(ctx, source, SENSORS_FEATURE_ENERGY, values); + return td_sensors_walk(ctx, source, SENSORS_FEATURE_ENERGY, read_sensor, values); } const td_source_impl sensors_energy_source = { @@ -497,7 +407,7 @@ static int sensors_current_heartbeat(td_ctx* ctx, td_source* source) { { NULL }, }; - return read_sensors(ctx, source, SENSORS_FEATURE_CURR, values); + return td_sensors_walk(ctx, source, SENSORS_FEATURE_CURR, read_sensor, values); } const td_source_impl sensors_current_source = {