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 = \
#include <errno.h>
#include <stdlib.h>
+#include <syslog.h>
#include "ctx.h"
+#include "logging.h"
struct collecty_ctx {
int nrefs;
// 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));
// 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) {
/*
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);
+}
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 */
--- /dev/null
+/*#############################################################################
+# #
+# 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 <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <systemd/sd-journal.h>
+
+#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);
+}
--- /dev/null
+/*#############################################################################
+# #
+# 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 <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#ifndef COLLECTY_LOGGING_H
+#define COLLECTY_LOGGING_H
+
+#include <stdarg.h>
+
+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 */
#include <syslog.h>
#include "ctx.h"
+#include "logging.h"
const char* argp_program_version = PACKAGE_VERSION;
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;
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);