libmemalloc  v3.5.00
Modern Memory Allocator
Loading...
Searching...
No Matches
logs.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2024-2025 Rafael V. Volkmer
3 * SPDX-FileCopyrightText: <rafael.v.volkmer@gmail.com>
4 * SPDX-License-Identifier: MIT
5 */
6
25#pragma once
26
27/* < C++ Compatibility > */
28#ifdef __cplusplus
29extern "C"
30{
31#endif
32
48#if !defined(_WIN32) && !defined(_WIN64)
49 #if defined(__STDC_HOSTED__) && (__STDC_HOSTED__ == 1)
50 #ifndef _GNU_SOURCE
51 #define _GNU_SOURCE
52 #endif
53 #endif
54#endif
55
63#if !defined(_WIN32) && !defined(_WIN64)
64 #if defined(__STDC_HOSTED__) && (__STDC_HOSTED__ == 1)
65 #if defined(__unix__) || defined(__unix) || defined(__APPLE__) \
66 || defined(__linux__)
67 #ifndef _POSIX_C_SOURCE
68 #define _POSIX_C_SOURCE 200809UL
69 #endif
70 #endif
71 #endif
72#endif
73
88#ifndef LOG_LEVEL
89 #define LOG_LEVEL LOG_LEVEL_DEBUG
90#endif
91
96/*< Dependencies >*/
97#include <errno.h>
98#include <pthread.h>
99#include <stdarg.h>
100#include <stdint.h>
101#include <stdio.h>
102#include <stdlib.h>
103#include <string.h>
104#include <time.h>
105#include <unistd.h>
106
124typedef enum LogLevel
126 LOG_LEVEL_NONE = (uint8_t)(0u),
127 LOG_LEVEL_ERROR = (uint8_t)(1u),
128 LOG_LEVEL_WARNING = (uint8_t)(2u),
129 LOG_LEVEL_INFO = (uint8_t)(3u),
130 LOG_LEVEL_DEBUG = (uint8_t)(4u)
132
146#if defined(__has_builtin)
147 #if __has_builtin(__builtin_fprintf)
148 #define LOG_PRINTF(...) __builtin_fprintf(__VA_ARGS__)
149 #else
150 #define LOG_PRINTF(...) fprintf(__VA_ARGS__)
151 #endif
152#else
153 #if defined(__GNUC__)
154 #define LOG_PRINTF(...) __builtin_fprintf(__VA_ARGS__)
155 #else
156 #define LOG_PRINTF(...) fprintf(__VA_ARGS__)
157 #endif
158#endif
159
169#if defined(__has_builtin)
170 #if __has_builtin(__builtin_vfprintf)
171 #define LOG_VPRINTF(...) __builtin_vfprintf(__VA_ARGS__)
172 #else
173 #define LOG_VPRINTF(...) vfprintf(__VA_ARGS__)
174 #endif
175#else
176 #if defined(__GNUC__)
177 #define LOG_VPRINTF(...) __builtin_vfprintf(__VA_ARGS__)
178 #else
179 #define LOG_VPRINTF(...) vfprintf(__VA_ARGS__)
180 #endif
181#endif
182
187#define PREFIX_ERROR "[ERROR]"
188#define PREFIX_WARNING "[WARNING]"
189#define PREFIX_INFO "[INFO]"
190#define PREFIX_DEBUG "[DEBUG]"
191
197#define COLOR_RED "\033[0;31m"
198#define COLOR_YELLOW "\033[0;33m"
199#define COLOR_BLUE "\033[0;34m"
200#define COLOR_GREEN "\033[0;32m"
201#define COLOR_RESET "\033[0m"
202
211#ifndef ATTR_PRINTF
212 #if defined(__has_attribute)
213 #if __has_attribute(format)
214 #define ATTR_PRINTF(fmt_idx, var_idx) \
215 __attribute__((format(printf, fmt_idx, var_idx)))
216 #else
217 #define ATTR_PRINTF(fmt_idx, var_idx)
218 #endif
219 #elif defined(__GNUC__)
220 #define ATTR_PRINTF(fmt_idx, var_idx) \
221 __attribute__((format(printf, fmt_idx, var_idx)))
222 #else
223 #define ATTR_PRINTF(fmt_idx, var_idx)
224 #endif
225#endif
226
263static inline int LOG_output(log_level_t level,
264 const char *color,
265 const char *prefix,
266 const char *file,
267 const char *func,
268 int line,
269 const char *fmt,
270 ...) ATTR_PRINTF(7, 8);
271
304static inline int LOG_output(log_level_t level,
305 const char *color,
306 const char *prefix,
307 const char *file,
308 const char *func,
309 int line,
310 const char *fmt,
311 ...)
312{
313 int ret = EXIT_SUCCESS;
314
315 FILE *out = (FILE *)NULL;
316
317 static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
318
319 struct timespec ts;
320 struct tm tm_buf;
321 struct tm *ptm = (struct tm *)NULL;
322
323 time_t now = 0;
324
325 long msec = 0u;
326
327 if (level > LOG_LEVEL)
328 {
329 ret = -EIO;
330 goto function_output;
331 }
332
333 pthread_mutex_lock(&log_mutex);
334
335 memset(&ts, 0, sizeof(ts));
336
337 clock_gettime(CLOCK_REALTIME, &ts);
338
339 now = ts.tv_sec;
340 memset(&tm_buf, 0, sizeof(tm_buf));
341
342#if defined(_WIN32) || defined(_WIN64)
343 if (localtime_s(&tm_buf, &now) != 0)
344 memset(&tm_buf, 0, sizeof(tm_buf));
345#else
346 if (localtime_r(&now, &tm_buf) == NULL)
347 memset(&tm_buf, 0, sizeof(tm_buf));
348#endif
349
350 ptm = &tm_buf;
351
352 out = (level <= LOG_LEVEL_WARNING) ? stderr : stdout;
353 msec = ts.tv_nsec / 1000000L;
354
355 LOG_PRINTF(out,
356 "[%02d:%02d:%02d.%03ld] ",
357 ptm->tm_hour,
358 ptm->tm_min,
359 ptm->tm_sec,
360 msec);
361
362 if (isatty(fileno(out)))
363 LOG_PRINTF(out, "%s%s%s ", color, prefix, COLOR_RESET);
364 else
365 LOG_PRINTF(out, "%s ", prefix);
366
367 va_list args;
368 va_start(args, fmt);
369 LOG_VPRINTF(out, fmt, args);
370 va_end(args);
371
372 LOG_PRINTF(out, " (at %s:%d:%s())\n", file, line, func);
373 pthread_mutex_unlock(&log_mutex);
374
375function_output:
376 return ret;
377}
378
387#define LOG_ERROR(...) \
388 LOG_output(LOG_LEVEL_ERROR, \
389 COLOR_RED, \
390 PREFIX_ERROR, \
391 __FILE__, \
392 __func__, \
393 __LINE__, \
394 __VA_ARGS__)
395
400#define LOG_WARNING(...) \
401 LOG_output(LOG_LEVEL_WARNING, \
402 COLOR_YELLOW, \
403 PREFIX_WARNING, \
404 __FILE__, \
405 __func__, \
406 __LINE__, \
407 __VA_ARGS__)
408
413#define LOG_INFO(...) \
414 LOG_output(LOG_LEVEL_INFO, \
415 COLOR_BLUE, \
416 PREFIX_INFO, \
417 __FILE__, \
418 __func__, \
419 __LINE__, \
420 __VA_ARGS__)
421
426#define LOG_DEBUG(...) \
427 LOG_output(LOG_LEVEL_DEBUG, \
428 COLOR_GREEN, \
429 PREFIX_DEBUG, \
430 __FILE__, \
431 __func__, \
432 __LINE__, \
433 __VA_ARGS__)
434
435/* < C++ Compatibility End > */
436#ifdef __cplusplus
437}
438#endif
439
441/* < End of header file > */
#define LOG_LEVEL
Logging verbosity threshold for this module.
Definition logs.h:89
#define COLOR_RESET
Definition logs.h:198
#define ATTR_PRINTF(fmt_idx, var_idx)
Macro to apply printf-style format checking on custom functions when supported by the compiler.
Definition logs.h:220
#define LOG_PRINTF(...)
Compiler-specific printf abstraction (variadic).
Definition logs.h:153
log_level_t
Defines log levels for the logging system.
Definition logs.h:123
static int LOG_output(log_level_t level, const char *color, const char *prefix, const char *file, const char *func, int line, const char *fmt,...)
Internal logging implementation: thread‐safe, prints timestamp, optional ANSI color,...
Definition logs.h:300
#define LOG_VPRINTF(...)
Compiler-specific vprintf abstraction.
Definition logs.h:176
@ LOG_LEVEL_DEBUG
Definition logs.h:128
@ LOG_LEVEL_ERROR
Definition logs.h:125
@ LOG_LEVEL_WARNING
Definition logs.h:126
@ LOG_LEVEL_NONE
Definition logs.h:124
@ LOG_LEVEL_INFO
Definition logs.h:127