From: Michael Tremer Date: Sat, 27 Sep 2025 11:48:50 +0000 (+0000) Subject: daemon: Implement logging X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=89ec549bec1b569837e4a672d97c522c731395d1;p=collecty.git daemon: Implement logging Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index f99bcdc..3ba95af 100644 --- a/Makefile.am +++ b/Makefile.am @@ -91,6 +91,8 @@ bin_PROGRAMS += \ dist_collectyd_SOURCES = \ src/daemon/ctx.c \ src/daemon/ctx.h \ + src/daemon/logging.c \ + src/daemon/logging.h \ src/daemon/main.c collectyd_CPPFLAGS = \ diff --git a/src/daemon/ctx.c b/src/daemon/ctx.c index 72394e7..4f9296b 100644 --- a/src/daemon/ctx.c +++ b/src/daemon/ctx.c @@ -20,8 +20,10 @@ #include #include +#include #include "ctx.h" +#include "logging.h" struct collecty_ctx { int nrefs; @@ -29,15 +31,30 @@ struct collecty_ctx { // Logging struct { int level; + + // Callback + collecty_log_callback callback; + void* data; } log; }; +static int collecty_ctx_setup_logging(collecty_ctx* ctx) { + // Log informational messages + ctx->log.level = LOG_INFO; + + // Setup a logging callback + ctx->log.callback = collecty_log_syslog; + + return 0; +} + static void collecty_ctx_free(collecty_ctx* ctx) { return; } int collecty_ctx_create(collecty_ctx** ctx) { struct collecty_ctx* self = NULL; + int r; // Allocate some memory self = calloc(1, sizeof(*self)); @@ -47,10 +64,20 @@ int collecty_ctx_create(collecty_ctx** ctx) { // Initialize the reference counter self->nrefs = 1; + // Setup logging + r = collecty_ctx_setup_logging(self); + if (r < 0) + goto ERROR; + // Return the pointer *ctx = self; - return 0; + +ERROR: + if (self) + collecty_ctx_unref(self); + + return r; } collecty_ctx* collecty_ctx_ref(collecty_ctx* ctx) { @@ -70,6 +97,30 @@ collecty_ctx* collecty_ctx_unref(collecty_ctx* ctx) { /* Logging */ + +int collecty_ctx_get_log_level(collecty_ctx* ctx) { + return ctx->log.level; +} + void collecty_ctx_set_log_level(collecty_ctx* ctx, int level) { ctx->log.level = level; } + +void collecty_ctx_set_log_callback(collecty_ctx* ctx, + collecty_log_callback callback, void* data) { + ctx->log.callback = callback; + ctx->log.data = data; +} + +void collecty_ctx_log(collecty_ctx* self, int level, + const char* file, int line, const char* fn, const char* format, ...) { + va_list args; + + // Return if the callback hasn't been set + if (!self->log.callback) + return; + + va_start(args, format); + self->log.callback(self->log.data, level, file, line, fn, format, args); + va_end(args); +} diff --git a/src/daemon/ctx.h b/src/daemon/ctx.h index 5dedd7e..6638787 100644 --- a/src/daemon/ctx.h +++ b/src/daemon/ctx.h @@ -29,6 +29,15 @@ collecty_ctx* collecty_ctx_ref(collecty_ctx* ctx); collecty_ctx* collecty_ctx_unref(collecty_ctx* ctx); // Logging +#include "logging.h" + +int collecty_ctx_get_log_level(collecty_ctx* ctx); void collecty_ctx_set_log_level(collecty_ctx* ctx, int level); +void collecty_ctx_set_log_callback(collecty_ctx* ctx, + collecty_log_callback callback, void* data); + +void collecty_ctx_log(collecty_ctx* self, int level, + const char* file, int line, const char* fn, const char* format, ...); + #endif /* COLLECTY_CTX_H */ diff --git a/src/daemon/logging.c b/src/daemon/logging.c new file mode 100644 index 0000000..0a7118a --- /dev/null +++ b/src/daemon/logging.c @@ -0,0 +1,75 @@ +/*############################################################################# +# # +# 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 +#include +#include + +#include + +#include "ctx.h" +#include "logging.h" + +void collecty_log_stderr(void* data, int priority, const char* file, + int line, const char* fn, const char* format, va_list args) { + fprintf(stderr, PACKAGE_NAME ": "); + + // Optionally log the function name + if (fn) + fprintf(stderr, "%s: ", fn); + + vfprintf(stderr, format, args); +} + +void collecty_log_syslog(void* data, int priority, const char* file, + int line, const char* fn, const char* format, va_list args) { + char* buffer = NULL; + int r; + + // Format log message + r = vasprintf(&buffer, format, args); + if (r < 0) + return; + + // Send message to journald + r = sd_journal_send( + "MESSAGE=%s", buffer, + "PRIORITY=%d", priority, + + // Syslog compat + "SYSLOG_IDENTIFIER=" PACKAGE_NAME, + + // Debugging stuff + "ERRNO=%d", errno, + "CODE_FILE=%s", file, + "CODE_LINE=%d", line, + "CODE_FUNC=%s", fn, + + NULL + ); + + // Fall back to standard output + if (r) + sd_journal_perror(buffer); + + // Cleanup + if (buffer) + free(buffer); +} diff --git a/src/daemon/logging.h b/src/daemon/logging.h new file mode 100644 index 0000000..092bf51 --- /dev/null +++ b/src/daemon/logging.h @@ -0,0 +1,58 @@ +/*############################################################################# +# # +# 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_LOGGING_H +#define COLLECTY_LOGGING_H + +#include + +typedef void (*collecty_log_callback)(void* data, int priority, const char* file, + int line, const char* fn, const char* format, va_list args); + +#include "ctx.h" + +void collecty_log_stderr(void* data, int priority, const char* file, + int line, const char* fn, const char* format, va_list args) + __attribute__((format(printf, 6, 0))); +void collecty_log_syslog(void* data, int priority, const char* file, + int line, const char* fn, const char* format, va_list args) + __attribute__((format(printf, 6, 0))); + +#define collecty_ctx_log_condition(ctx, level, arg...) \ + do { \ + if (collecty_ctx_get_log_level(ctx) >= level) \ + collecty_ctx_log(ctx, level, __FILE__, __LINE__, __FUNCTION__, ## arg); \ + } while (0) + +#define INFO(ctx, arg...) collecty_ctx_log_condition(ctx, LOG_INFO, ## arg) +#define WARN(ctx, arg...) collecty_ctx_log_condition(ctx, LOG_WARNING, ## arg) +#define ERROR(ctx, arg...) collecty_ctx_log_condition(ctx, LOG_ERR, ## arg) + +// This function does absolutely nothing +static inline void __attribute__((always_inline, format(printf, 2, 3))) + collecty_ctx_log_null(collecty_ctx* ctx, const char *format, ...) {} + +#ifdef ENABLE_DEBUG +# define DEBUG(ctx, arg...) collecty_ctx_log_condition(ctx, LOG_DEBUG, ## arg) +#else +# define DEBUG collecty_ctx_log_null +#endif + +#endif /* COLLECTY_LOGGING_H */ diff --git a/src/daemon/main.c b/src/daemon/main.c index bf8246c..92dff8e 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -24,6 +24,7 @@ #include #include "ctx.h" +#include "logging.h" const char* argp_program_version = PACKAGE_VERSION; @@ -43,6 +44,10 @@ static error_t parse(int key, char* arg, struct argp_state* state) { switch (key) { case OPT_DEBUG: + // Log to stdout + collecty_ctx_set_log_callback(ctx, collecty_log_stderr, NULL); + + // Increase the log level collecty_ctx_set_log_level(ctx, LOG_DEBUG); break; @@ -69,10 +74,12 @@ int main(int argc, char* argv[]) { goto ERROR; // Parse command line arguments - r = argp_parse(&parser, argc, argv, ARGP_NO_ARGS, &arg_index, &ctx); + r = argp_parse(&parser, argc, argv, ARGP_NO_ARGS, &arg_index, ctx); if (r) goto ERROR; + INFO(ctx, "Daemon initialized\n"); + ERROR: if (ctx) collecty_ctx_unref(ctx);