libmemalloc  v3.0.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
37/*< Dependencies >*/
38#include <errno.h>
39#include <pthread.h>
40#include <stdarg.h>
41#include <stdint.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45#include <time.h>
46#include <unistd.h>
47
65typedef enum LogLevel
67 LOG_LEVEL_NONE = (uint8_t)(0u),
68 LOG_LEVEL_ERROR = (uint8_t)(1u),
69 LOG_LEVEL_WARNING = (uint8_t)(2u),
70 LOG_LEVEL_INFO = (uint8_t)(3u),
71 LOG_LEVEL_DEBUG = (uint8_t)(4u)
73
82#ifndef LOG_LEVEL
83 #define LOG_LEVEL LOG_LEVEL_DEBUG
84#endif
85
93#ifndef _POSIX_C_SOURCE
94 #define _POSIX_C_SOURCE 200809UL
95#endif
96
106#if defined(__has_builtin)
107 #if __has_builtin(__builtin_fprintf)
108 #define LOG_PRINTF(...) __builtin_fprintf(__VA_ARGS__)
109 #else
110 #define LOG_PRINTF(...) fprintf(__VA_ARGS__)
111 #endif
112#else
113 #if defined(__GNUC__)
114 #define LOG_PRINTF(...) __builtin_fprintf(__VA_ARGS__)
115 #else
116 #define LOG_PRINTF(...) fprintf(__VA_ARGS__)
117 #endif
118#endif
119
129#if defined(__has_builtin)
130 #if __has_builtin(__builtin_vfprintf)
131 #define LOG_VPRINTF(...) __builtin_vfprintf(__VA_ARGS__)
132 #else
133 #define LOG_VPRINTF(...) vfprintf(__VA_ARGS__)
134 #endif
135#else
136 #if defined(__GNUC__)
137 #define LOG_VPRINTF(...) __builtin_vfprintf(__VA_ARGS__)
138 #else
139 #define LOG_VPRINTF(...) vfprintf(__VA_ARGS__)
140 #endif
141#endif
142
147#define PREFIX_ERROR "[ERROR]"
148#define PREFIX_WARNING "[WARNING]"
149#define PREFIX_INFO "[INFO]"
150#define PREFIX_DEBUG "[DEBUG]"
151
157#define COLOR_RED "\033[0;31m"
158#define COLOR_YELLOW "\033[0;33m"
159#define COLOR_BLUE "\033[0;34m"
160#define COLOR_GREEN "\033[0;32m"
161#define COLOR_RESET "\033[0m"
162
171#ifndef ATTR_PRINTF
172 #if defined(__has_attribute)
173 #if __has_attribute(format)
174 #define ATTR_PRINTF(fmt_idx, var_idx) \
175 __attribute__((format(printf, fmt_idx, var_idx)))
176 #else
177 #define ATTR_PRINTF(fmt_idx, var_idx)
178 #endif
179 #elif defined(__GNUC__)
180 #define ATTR_PRINTF(fmt_idx, var_idx) \
181 __attribute__((format(printf, fmt_idx, var_idx)))
182 #else
183 #define ATTR_PRINTF(fmt_idx, var_idx)
184 #endif
185#endif
186
223static inline int LOG_output(log_level_t level,
224 const char *color,
225 const char *prefix,
226 const char *file,
227 const char *func,
228 int line,
229 const char *fmt,
230 ...) ATTR_PRINTF(7, 8);
231
264static inline int LOG_output(log_level_t level,
265 const char *color,
266 const char *prefix,
267 const char *file,
268 const char *func,
269 int line,
270 const char *fmt,
271 ...)
272{
273 int ret = EXIT_SUCCESS;
274
275 FILE *out = (FILE *)NULL;
276
277 static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
278
279 struct timespec ts;
280 struct tm *ptm = (struct tm *)NULL;
281
282 time_t now = 0;
283
284 long msec = 0u;
285
286 if (level > LOG_LEVEL)
287 {
288 ret = -EIO;
289 goto function_output;
290 }
291
292 pthread_mutex_lock(&log_mutex);
293
294 memset(&ts, 0, sizeof(ts));
295
296 clock_gettime(CLOCK_REALTIME, &ts);
297
298 now = ts.tv_sec;
299 ptm = localtime(&now);
300
301 out = (level <= LOG_LEVEL_WARNING) ? stderr : stdout;
302 msec = ts.tv_nsec / 1000000L;
303
304 LOG_PRINTF(out,
305 "[%02d:%02d:%02d.%03ld] ",
306 ptm->tm_hour,
307 ptm->tm_min,
308 ptm->tm_sec,
309 msec);
310
311 if (isatty(fileno(out)))
312 LOG_PRINTF(out, "%s%s%s ", color, prefix, COLOR_RESET);
313 else
314 LOG_PRINTF(out, "%s ", prefix);
315
316 va_list args;
317 va_start(args, fmt);
318 LOG_VPRINTF(out, fmt, args);
319 va_end(args);
320
321 LOG_PRINTF(out, " (at %s:%d:%s())\n", file, line, func);
322 pthread_mutex_unlock(&log_mutex);
323
324function_output:
325 return ret;
326}
327
336#define LOG_ERROR(...) \
337 LOG_output(LOG_LEVEL_ERROR, \
338 COLOR_RED, \
339 PREFIX_ERROR, \
340 __FILE__, \
341 __func__, \
342 __LINE__, \
343 __VA_ARGS__)
344
349#define LOG_WARNING(...) \
350 LOG_output(LOG_LEVEL_WARNING, \
351 COLOR_YELLOW, \
352 PREFIX_WARNING, \
353 __FILE__, \
354 __func__, \
355 __LINE__, \
356 __VA_ARGS__)
357
362#define LOG_INFO(...) \
363 LOG_output(LOG_LEVEL_INFO, \
364 COLOR_BLUE, \
365 PREFIX_INFO, \
366 __FILE__, \
367 __func__, \
368 __LINE__, \
369 __VA_ARGS__)
370
375#define LOG_DEBUG(...) \
376 LOG_output(LOG_LEVEL_DEBUG, \
377 COLOR_GREEN, \
378 PREFIX_DEBUG, \
379 __FILE__, \
380 __func__, \
381 __LINE__, \
382 __VA_ARGS__)
383
384/* < C++ Compatibility End > */
385#ifdef __cplusplus
386}
387#endif
388
390/* < End of header file > */
#define LOG_LEVEL
Default log level if not defined.
Definition logs.h:80
#define COLOR_RESET
Definition logs.h:158
#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:180
#define LOG_PRINTF(...)
Compiler-specific printf abstraction (variadic).
Definition logs.h:113
log_level_t
Defines log levels for the logging system.
Definition logs.h:64
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:260
#define LOG_VPRINTF(...)
Compiler-specific vprintf abstraction.
Definition logs.h:136
@ LOG_LEVEL_DEBUG
Definition logs.h:69
@ LOG_LEVEL_ERROR
Definition logs.h:66
@ LOG_LEVEL_WARNING
Definition logs.h:67
@ LOG_LEVEL_NONE
Definition logs.h:65
@ LOG_LEVEL_INFO
Definition logs.h:68