OreBolt-OS/include/log_manager.h

150 lines
4.6 KiB
C
Executable File

/*
* log_manager.h -- OreBolt OS logging subsystem
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* Combines a flash-safe timed coalescer with a structured
* log level interface. Provides both:
* - LOG_INF/DBG/ERR macros (structured, leveled logging)
* - timed_log_* functions (RAM-buffered, windowed disk flush)
*
* Structured logs: /data/vault/syslog.log (rotating, 64 KB max)
* Failure records: /data/vault/failures.dat (binary, append-only)
*/
#ifndef LOG_MANAGER_H
#define LOG_MANAGER_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include <unistd.h>
#include <time.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ================================================================== */
/* Structured Log Level Interface */
/* ================================================================== */
typedef enum {
LOG_TRACE = 0,
LOG_DEBUG,
LOG_INFO,
LOG_WARN,
LOG_ERROR,
LOG_FATAL
} log_level_t;
int log_init(const char *path);
void log_close(void);
void log_write(log_level_t lvl, const char *module, const char *fmt, ...);
/* Failure logging -- binary, durable, used by panic_purge_api.h. */
int log_failure_record(uint32_t code, const void *blob, size_t len);
#define LOG_TRC(fmt, ...) log_write(LOG_TRACE, __func__, fmt, ##__VA_ARGS__)
#define LOG_DBG(fmt, ...) log_write(LOG_DEBUG, __func__, fmt, ##__VA_ARGS__)
#define LOG_INF(fmt, ...) log_write(LOG_INFO, __func__, fmt, ##__VA_ARGS__)
#define LOG_WRN(fmt, ...) log_write(LOG_WARN, __func__, fmt, ##__VA_ARGS__)
#define LOG_ERR(fmt, ...) log_write(LOG_ERROR, __func__, fmt, ##__VA_ARGS__)
#define LOG_FTL(fmt, ...) log_write(LOG_FATAL, __func__, fmt, ##__VA_ARGS__)
/* ================================================================== */
/* Flash-Safe Timed Coalescer (v1.3) */
/* ================================================================== */
typedef enum {
WINDOW_30S = 30,
WINDOW_1M = 60,
WINDOW_2M = 120,
WINDOW_5M = 300,
WINDOW_10M = 600
} log_window_t;
#define RAM_CHUNK_LIMIT (64 * 1024)
typedef struct {
char *ram_pool;
size_t pool_idx;
time_t window_start;
uint32_t window_duration;
FILE *file_handle;
char base_path[128];
} timed_logger_t;
static inline timed_logger_t* timed_log_init(const char *filepath, log_window_t window) {
static const log_window_t valid_windows[] = {
WINDOW_30S, WINDOW_1M, WINDOW_2M, WINDOW_5M, WINDOW_10M
};
int valid = 0;
for (size_t i = 0; i < sizeof(valid_windows) / sizeof(valid_windows[0]); i++) {
if (window == valid_windows[i]) { valid = 1; break; }
}
if (!valid) return NULL;
timed_logger_t *logger = malloc(sizeof(timed_logger_t));
if (!logger) return NULL;
logger->ram_pool = malloc(RAM_CHUNK_LIMIT);
if (!logger->ram_pool) {
free(logger);
return NULL;
}
strncpy(logger->base_path, filepath, sizeof(logger->base_path) - 1);
logger->base_path[sizeof(logger->base_path) - 1] = '\0';
memset(logger->ram_pool, 0, RAM_CHUNK_LIMIT);
logger->pool_idx = 0;
logger->window_duration = (uint32_t)window;
logger->window_start = time(NULL);
logger->file_handle = NULL;
return logger;
}
static inline void timed_log_flush_to_media(timed_logger_t *logger) {
if (!logger || logger->pool_idx == 0) return;
logger->file_handle = fopen(logger->base_path, "a");
if (!logger->file_handle) return;
(void)fwrite(logger->ram_pool, 1, logger->pool_idx, logger->file_handle);
int fd = fileno(logger->file_handle);
if (fd >= 0) fdatasync(fd);
fclose(logger->file_handle);
logger->file_handle = NULL;
memset(logger->ram_pool, 0, RAM_CHUNK_LIMIT);
logger->pool_idx = 0;
logger->window_start = time(NULL);
}
static inline void timed_log_write(timed_logger_t *logger, const char *data) {
if (!logger || !data) return;
size_t data_len = strlen(data);
if (data_len >= RAM_CHUNK_LIMIT) return;
if (logger->pool_idx + data_len >= RAM_CHUNK_LIMIT) {
timed_log_flush_to_media(logger);
}
memcpy(&logger->ram_pool[logger->pool_idx], data, data_len);
logger->pool_idx += data_len;
if (time(NULL) - logger->window_start >= logger->window_duration) {
timed_log_flush_to_media(logger);
}
}
static inline void timed_log_close(timed_logger_t *logger) {
if (!logger) return;
timed_log_flush_to_media(logger);
free(logger->ram_pool);
free(logger);
}
#ifdef __cplusplus
}
#endif
#endif /* LOG_MANAGER_H */