feat: add logging system and debug audio routing
Co-authored-by: aider (deepseek/deepseek-coder) <aider@aider.chat>
This commit is contained in:
96
logging.c
96
logging.c
@@ -0,0 +1,96 @@
|
||||
#include "logging.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static struct {
|
||||
FILE *file;
|
||||
LogLevel level;
|
||||
pthread_mutex_t mutex;
|
||||
bool initialized;
|
||||
} logger = { .file = NULL, .level = LOG_LEVEL_INFO, .initialized = false };
|
||||
|
||||
static const char* level_to_string(LogLevel level) {
|
||||
switch (level) {
|
||||
case LOG_LEVEL_ERROR: return "ERROR";
|
||||
case LOG_LEVEL_WARN: return "WARN";
|
||||
case LOG_LEVEL_INFO: return "INFO";
|
||||
case LOG_LEVEL_DEBUG: return "DEBUG";
|
||||
case LOG_LEVEL_TRACE: return "TRACE";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
void log_init(const char *filename, LogLevel level) {
|
||||
pthread_mutex_init(&logger.mutex, NULL);
|
||||
logger.level = level;
|
||||
|
||||
if (filename) {
|
||||
logger.file = fopen(filename, "w");
|
||||
if (!logger.file) {
|
||||
fprintf(stderr, "Failed to open log file %s, logging to stderr\n", filename);
|
||||
logger.file = stderr;
|
||||
}
|
||||
} else {
|
||||
logger.file = stderr;
|
||||
}
|
||||
|
||||
logger.initialized = true;
|
||||
|
||||
// Log header
|
||||
time_t now = time(NULL);
|
||||
struct tm *tm = localtime(&now);
|
||||
char timebuf[64];
|
||||
strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S", tm);
|
||||
fprintf(logger.file, "=== Log started at %s ===\n", timebuf);
|
||||
fprintf(logger.file, "Log level: %s\n\n", level_to_string(level));
|
||||
fflush(logger.file);
|
||||
}
|
||||
|
||||
void log_cleanup(void) {
|
||||
if (logger.initialized) {
|
||||
if (logger.file && logger.file != stderr) {
|
||||
fclose(logger.file);
|
||||
}
|
||||
logger.file = NULL;
|
||||
logger.initialized = false;
|
||||
pthread_mutex_destroy(&logger.mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void log_set_level(LogLevel level) {
|
||||
logger.level = level;
|
||||
}
|
||||
|
||||
void log_message(LogLevel level, const char *file, int line, const char *func, const char *format, ...) {
|
||||
if (!logger.initialized || level > logger.level) return;
|
||||
|
||||
pthread_mutex_lock(&logger.mutex);
|
||||
|
||||
// Timestamp
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
struct tm *tm = localtime(&ts.tv_sec);
|
||||
char timebuf[32];
|
||||
strftime(timebuf, sizeof(timebuf), "%H:%M:%S", tm);
|
||||
|
||||
// Print header
|
||||
fprintf(logger.file, "[%s.%03ld] [%s] [%s:%d %s] ",
|
||||
timebuf, ts.tv_nsec / 1000000,
|
||||
level_to_string(level),
|
||||
file, line, func);
|
||||
|
||||
// Print message
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vfprintf(logger.file, format, args);
|
||||
va_end(args);
|
||||
|
||||
fprintf(logger.file, "\n");
|
||||
fflush(logger.file);
|
||||
|
||||
pthread_mutex_unlock(&logger.mutex);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user