#include "logging.h"
#include "../platform/memory.h"
#include <string.h>
logger_t *g_logger = NULL;
struct logger {
FILE *file;
FILE *access_file;
log_level_t level;
mutex_t mutex;
char file_path[PATH_MAX];
size_t max_size;
int rotate_count;
};
static const char *level_names[] = {
"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"
};
logger_t *logger_create(const char *file_path, log_level_t level) {
logger_t *log = calloc(1, sizeof(logger_t));
if (!log) return NULL;
log->level = level;
log->max_size = 100 * 1024 * 1024;
log->rotate_count = 10;
if (pal_mutex_init(&log->mutex) != NWEDAV_OK) {
free(log);
return NULL;
}
if (file_path && file_path[0]) {
strncpy(log->file_path, file_path, sizeof(log->file_path) - 1);
log->file = fopen(file_path, "a");
}
if (!log->file) {
log->file = stderr;
}
return log;
}
void logger_destroy(logger_t *log) {
if (!log) return;
pal_mutex_lock(&log->mutex);
if (log->file && log->file != stderr && log->file != stdout) {
fclose(log->file);
}
if (log->access_file && log->access_file != stderr && log->access_file != stdout) {
fclose(log->access_file);
}
pal_mutex_unlock(&log->mutex);
pal_mutex_destroy(&log->mutex);
free(log);
}
void logger_set_level(logger_t *log, log_level_t level) {
if (log) {
log->level = level;
}
}
void logger_log(logger_t *log, log_level_t level, const char *file, int line, const char *fmt, ...) {
if (!log || level < log->level) return;
pal_mutex_lock(&log->mutex);
time_t now = time(NULL);
struct tm *tm = localtime(&now);
char timestamp[32];
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", tm);
const char *basename = file;
const char *p = strrchr(file, '/');
if (p) basename = p + 1;
#ifdef _WIN32
p = strrchr(basename, '\\');
if (p) basename = p + 1;
#endif
fprintf(log->file, "[%s] [%s] [%s:%d] ",
timestamp, level_names[level], basename, line);
va_list ap;
va_start(ap, fmt);
vfprintf(log->file, fmt, ap);
va_end(ap);
fprintf(log->file, "\n");
fflush(log->file);
pal_mutex_unlock(&log->mutex);
}
void logger_access(logger_t *log, const char *client_ip, const char *method,
const char *uri, int status, size_t bytes, const char *user_agent) {
if (!log) return;
FILE *out = log->access_file ? log->access_file : log->file;
pal_mutex_lock(&log->mutex);
time_t now = time(NULL);
struct tm *tm = localtime(&now);
char timestamp[64];
strftime(timestamp, sizeof(timestamp), "%d/%b/%Y:%H:%M:%S %z", tm);
fprintf(out, "%s - - [%s] \"%s %s HTTP/1.1\" %d %zu \"-\" \"%s\"\n",
client_ip ? client_ip : "-",
timestamp,
method ? method : "-",
uri ? uri : "-",
status,
bytes,
user_agent ? user_agent : "-");
fflush(out);
pal_mutex_unlock(&log->mutex);
}