#include "logging.h" #include #include #include #include #include #include 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); }