11/*
22 * Logger.h
3+ * Dual-mode logger: console or syslog
4+ *
35 * Author: Milan M.
46 * Copyright (c) 2025 AMSOFTSWITCH LTD. All rights reserved.
57 */
911
1012#include < cstdio>
1113#include < cstring>
14+ #include < syslog.h>
15+ #include < unistd.h>
16+ #include < sys/time.h>
17+ #include < ctime>
1218
13- void log_debug (const char * message);
14- void log_error (const char * message);
19+ /* *
20+ * \brief Determines if logs should go to syslog (non-interactive) or console.
21+ */
22+ inline bool logger_use_syslog () {
23+ static bool initialized = false ;
24+ static bool use_syslog = false ;
25+ if (!initialized) {
26+ initialized = true ;
27+ use_syslog = !isatty (STDOUT_FILENO);
28+ if (use_syslog) openlog (nullptr , LOG_PID, LOG_DAEMON);
29+ }
30+ return use_syslog;
31+ }
32+
33+ /* *
34+ * \brief Fill buf with current timestamp "YYYY-MM-DD HH:MM:SS.mmm".
35+ */
36+ inline void current_timestamp (char * buf, size_t len) {
37+ struct timeval tv;
38+ gettimeofday (&tv, nullptr );
39+ struct tm tm_info;
40+ localtime_r (&tv.tv_sec , &tm_info);
41+ int ms = tv.tv_usec / 1000 ;
42+ strftime (buf, len, " %Y-%m-%d %H:%M:%S" , &tm_info);
43+ size_t sl = strlen (buf);
44+ snprintf (buf + sl, len - sl, " .%03d" , ms);
45+ }
46+
47+ /* *
48+ * \brief Internal debug logger: writes to stdout or syslog.
49+ */
50+ inline void log_debug_impl (const char * message) {
51+ #ifdef LIBWSC_USE_DEBUG
52+ char ts[32 ]; current_timestamp (ts, sizeof (ts));
53+ if (logger_use_syslog ()) {
54+ syslog (LOG_DEBUG, " %s" , message);
55+ } else {
56+ fprintf (stdout, " [DEBUG %s] %s\n " , ts, message);
57+ fflush (stdout);
58+ }
59+ #else
60+ (void )message;
61+ #endif
62+ }
63+
64+ /* *
65+ * \brief Internal error logger: writes to stderr or syslog.
66+ */
67+ inline void log_error_impl (const char * message) {
68+ char ts[32 ]; current_timestamp (ts, sizeof (ts));
69+ if (logger_use_syslog ()) {
70+ syslog (LOG_ERR, " %s" , message);
71+ } else {
72+ fprintf (stderr, " [ERROR %s] %s\n " , ts, message);
73+ fflush (stderr);
74+ }
75+ }
1576
16- inline void log_debug_fmt (const char * message) {
17- log_debug (message);
77+ // Zero-arg overloads to avoid format-security warnings
78+ inline void log_debug_fmt_impl (const char * fmt) {
79+ log_debug_impl (fmt);
1880}
19- inline void log_error_fmt (const char * message ) {
20- log_error (message );
81+ inline void log_error_fmt_impl (const char * fmt ) {
82+ log_error_impl (fmt );
2183}
2284
85+ // Templated overloads for formatting
2386template <typename ... Args>
24- inline void log_debug_fmt (const char * fmt, Args... args) {
87+ inline void log_debug_fmt_impl (const char * fmt, Args... args) {
2588 char buf[256 ];
2689 snprintf (buf, sizeof (buf), fmt, args...);
27- log_debug (buf);
90+ log_debug_impl (buf);
2891}
2992
3093template <typename ... Args>
31- inline void log_error_fmt (const char * fmt, Args... args) {
94+ inline void log_error_fmt_impl (const char * fmt, Args... args) {
3295 char buf[256 ];
3396 snprintf (buf, sizeof (buf), fmt, args...);
34- log_error (buf);
97+ log_error_impl (buf);
3598}
3699
37- #ifdef USE_DEBUG
38- #define LOG_DEBUG (...) log_debug_fmt(__VA_ARGS__)
100+ // Public macros
101+ #ifdef LIBWSC_USE_DEBUG
102+ #define log_debug (...) log_debug_fmt_impl(__VA_ARGS__)
39103#else
40- #define LOG_DEBUG (...) ((void )0 )
104+ #define log_debug (...) ((void )0 )
41105#endif
42106
43- #define LOG_ERROR (...) log_error_fmt (__VA_ARGS__)
107+ #define log_error (...) log_error_fmt_impl (__VA_ARGS__)
44108
45109#endif // LOGGER_H
0 commit comments