#include "log.h" #ifdef APPLOG_ENABLED #include #include #include #include #include #ifdef LOG_FILE_LOCATION #include static pthread_mutex_t fmtx = PTHREAD_MUTEX_INITIALIZER; #endif static pthread_mutex_t cmtx = PTHREAD_MUTEX_INITIALIZER; /* Replicates pFname: strips return type and parameters from __PRETTY_FUNCTION__ * "void myFunc(int x)" → "myFunc" * "int other_func(void)" → "other_func" */ static void fmt_funcname(const char *pretty, char *out, size_t outsz) { const char *start = pretty; const char *space = strchr(pretty, ' '); if (space) start = space + 1; const char *paren = strrchr(start, '('); size_t len = paren ? (size_t)(paren - start) : strlen(start); if (len >= outsz) len = outsz - 1; memcpy(out, start, len); out[len] = '\0'; } void log_write(const log_level_t level, const char *func, const char *fmt, ...) { static const char *reset = "\033[0m"; const char *color; switch (level) { case LOG_INF: color = "\033[1;32m"; break; /* bold green */ case LOG_WRN: color = "\033[1;33m"; break; /* bold yellow */ case LOG_ERR: color = "\033[1;31m"; break; /* bold red */ case LOG_DBG: color = ""; break; case LOG_START: color = "\033[1;3;36m"; break; /* bold italic cyan */ default: color = ""; break; } char funcname[128]; fmt_funcname(func, funcname, sizeof(funcname)); /* ── console ─────────────────────────────────────────────────────── */ { va_list ap; va_start(ap, fmt); pthread_mutex_lock(&cmtx); fprintf(stderr, "[%s%s%s] ", color, funcname, reset); vfprintf(stderr, fmt, ap); fputc('\n', stderr); pthread_mutex_unlock(&cmtx); va_end(ap); } #ifdef LOG_FILE_LOCATION /* ── file ────────────────────────────────────────────────────────── */ { char timebuf[32]; struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); struct tm tm_info; localtime_r(&ts.tv_sec, &tm_info); strftime(timebuf, sizeof(timebuf), "%x %H:%M:%S", &tm_info); char msgbuf[1024]; va_list ap; va_start(ap, fmt); int offset = snprintf(msgbuf, sizeof(msgbuf), "%s.%03ld [%s%s%s] ", timebuf, ts.tv_nsec / 1000000L, color, funcname, reset); vsnprintf(msgbuf + offset, sizeof(msgbuf) - offset, fmt, ap); va_end(ap); pthread_mutex_lock(&fmtx); gzFile file = gzopen(LOG_FILE_LOCATION, "ab"); if (file) { gzprintf(file, "%s\n", msgbuf); gzclose(file); } pthread_mutex_unlock(&fmtx); } #endif /* LOG_FILE_LOCATION */ } #endif /* APPLOG_ENABLED */