diff options
Diffstat (limited to 'common/log.c')
-rw-r--r-- | common/log.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/common/log.c b/common/log.c new file mode 100644 index 0000000..1474dcc --- /dev/null +++ b/common/log.c @@ -0,0 +1,80 @@ +#include <errno.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> + +#include "log.h" + +const long NSEC_PER_SEC = 1000000000; + +static enum libseat_log_level current_log_level; +static struct timespec start_time = {-1, -1}; +static bool colored = false; + +static const char *verbosity_colors[] = { + [LIBSEAT_SILENT] = "", + [LIBSEAT_ERROR] = "\x1B[1;31m", + [LIBSEAT_INFO] = "\x1B[1;34m", + [LIBSEAT_DEBUG] = "\x1B[1;90m", +}; + +static const char *verbosity_headers[] = { + [LIBSEAT_SILENT] = "", + [LIBSEAT_ERROR] = "[ERROR]", + [LIBSEAT_INFO] = "[INFO]", + [LIBSEAT_DEBUG] = "[DEBUG]", +}; + +static void timespec_sub(struct timespec *r, const struct timespec *a, const struct timespec *b) { + r->tv_sec = a->tv_sec - b->tv_sec; + r->tv_nsec = a->tv_nsec - b->tv_nsec; + if (r->tv_nsec < 0) { + r->tv_sec--; + r->tv_nsec += NSEC_PER_SEC; + } +} + +void libseat_log_init(enum libseat_log_level level) { + if (start_time.tv_sec >= 0) { + return; + } + clock_gettime(CLOCK_MONOTONIC, &start_time); + current_log_level = level; + colored = isatty(STDERR_FILENO); +} + +void _libseat_logf(enum libseat_log_level level, const char *fmt, ...) { + int stored_errno = errno; + va_list args; + if (level < current_log_level) { + return; + } + + struct timespec ts = {0}; + clock_gettime(CLOCK_MONOTONIC, &ts); + timespec_sub(&ts, &ts, &start_time); + unsigned c = (level < LIBSEAT_LOG_LEVEL_LAST) ? level : LIBSEAT_LOG_LEVEL_LAST - 1; + + const char *prefix, *postfix; + + if (colored) { + prefix = verbosity_colors[c]; + postfix = "\x1B[0m\n"; + } else { + prefix = verbosity_headers[c]; + postfix = "\n"; + } + + fprintf(stderr, "%02d:%02d:%02d.%03ld %s ", (int)(ts.tv_sec / 60 / 60), + (int)(ts.tv_sec / 60 % 60), (int)(ts.tv_sec % 60), ts.tv_nsec / 1000000, prefix); + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + + fprintf(stderr, "%s", postfix); + errno = stored_errno; +} |