/* * * Copyright 2023 Oleg Borodin * */ #include #include #include #include #include #define CLOCK_SOURCE CLOCK_MONOTONIC #define MAX_TS_LEN 256 static pthread_mutex_t logmutex = NULL; static pthread_mutexattr_t logmutex_attrs; void log_init(void) { pthread_mutexattr_init(&logmutex_attrs); pthread_mutexattr_setpshared(&logmutex_attrs, PTHREAD_PROCESS_SHARED); pthread_mutex_init(&logmutex, &logmutex_attrs); } void log_destroy(void) { pthread_mutex_destroy(&logmutex); pthread_mutexattr_destroy(&logmutex_attrs); } void static set_timestamp(char* buffer) { time_t now = time(NULL); if (now < 0) { return; } struct tm* ptm = localtime(&now); if (ptm == NULL) { return; } struct timespec tv; clock_gettime(CLOCK_SOURCE, &tv); memset(buffer, '\0', MAX_TS_LEN); sprintf(buffer, "%04d-%02d-%02dT%02d:%02d:%02d.%ld+%s", ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, tv.tv_nsec, ptm->tm_zone); } void log_error(const char* format, ...) { char timestamp[MAX_TS_LEN]; set_timestamp(timestamp); pthread_mutex_lock(&logmutex); va_list args; fprintf(stderr, "%s error: ", timestamp); va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); pthread_mutex_unlock(&logmutex); } void log_warning(const char* format, ...) { char timestamp[MAX_TS_LEN]; set_timestamp(timestamp); pthread_mutex_lock(&logmutex); va_list args; fprintf(stderr, "%s warning: ", timestamp); va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); pthread_mutex_unlock(&logmutex); } void log_debug(const char* format, ...) { char timestamp[MAX_TS_LEN]; set_timestamp(timestamp); pthread_mutex_lock(&logmutex); va_list args; fprintf(stderr, "%s debug: ", timestamp); va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); pthread_mutex_unlock(&logmutex); }