feat(logging)!: add enhanced logging system

BREAKING CHANGE: stk_log() signature changed to require log level

- Add log levels (ERROR, WARN, INFO, DEBUG) with runtime filtering
- Add timestamps (yyyy-mm-dd HH:MM:SS.mmm format)
- Add stk_set_log_output(), stk_set_log_prefix(), stk_set_log_level()
- Platform-specific timestamp: GetLocalTime (Windows), gettimeofday (POSIX)
- Consolidate duplicate platform includes into POSIX common block
- Setting log output to NULL disables logging.

Default: INFO level, "stk" prefix, stdout output. All internal messages
use appropriate severity levels. Single byte flag controls enable/disable.
This commit is contained in:
2026-02-14 16:59:56 +01:00
parent 26fb19a7f5
commit 110b7ffca8
5 changed files with 135 additions and 29 deletions
+77 -5
View File
@@ -1,14 +1,86 @@
#include "stk_log.h"
#include "stk.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
void stk_log(FILE *fp, const char *fmt, ...)
#define STK_LOG_TIMESTAMP_BUFFER 32
extern unsigned char stk_flags;
void platform_get_timestamp(char *buffer, size_t size);
static FILE *log_output = NULL;
static char log_prefix[STK_LOG_PREFIX_BUFFER] = "stk";
static stk_log_level_t min_log_level = STK_LOG_INFO;
static const char *get_level_string(stk_log_level_t level)
{
va_list args;
va_start(args, fmt);
char *level_str = "";
switch (level) {
case STK_LOG_ERROR:
level_str = "ERROR";
break;
case STK_LOG_WARN:
level_str = "WARN";
break;
case STK_LOG_INFO:
level_str = "INFO";
break;
case STK_LOG_DEBUG:
level_str = "DEBUG";
break;
}
vfprintf(fp, fmt, args);
fputc('\n', fp);
return level_str;
}
void stk_set_log_output(FILE *fp)
{
if (fp == NULL)
stk_flags &= ~STK_FLAG_LOGGING_ENABLED;
log_output = fp;
}
void stk_set_log_prefix(const char *prefix)
{
if (!prefix) {
log_prefix[0] = '\0';
return;
}
strncpy(log_prefix, prefix, STK_LOG_PREFIX_BUFFER - 1);
log_prefix[STK_LOG_PREFIX_BUFFER - 1] = '\0';
}
void stk_set_log_level(stk_log_level_t level) { min_log_level = level; }
void stk_log(stk_log_level_t level, const char *fmt, ...)
{
FILE *output;
const char *level_str;
char timestamp[STK_LOG_TIMESTAMP_BUFFER];
va_list args;
if (!(stk_flags & STK_FLAG_LOGGING_ENABLED))
return;
if (level < min_log_level)
return;
output = log_output ? log_output : stdout;
level_str = get_level_string(level);
platform_get_timestamp(timestamp, sizeof(timestamp));
if (log_prefix[0] != '\0')
fprintf(output, "%s [%s] [%s] ", timestamp, log_prefix,
level_str);
else
fprintf(output, "%s [%s] ", timestamp, level_str);
va_start(args, fmt);
vfprintf(output, fmt, args);
va_end(args);
fputc('\n', output);
}