150 lines
4.6 KiB
C
Executable File
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 */ |