1 /*
2 bctoolobx
3 Copyright (C) 2016 Belledonne Communications, France, Grenoble
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 /**
21 * \file logging.h
22 * \brief Logging API.
23 *
24 **/
25
26 #ifndef BCTBX_LOGGING_H
27 #define BCTBX_LOGGING_H
28
29 #include <bctoolbox/port.h>
30 #include "bctoolbox/list.h"
31
32 #ifndef BCTBX_LOG_DOMAIN
33 #define BCTBX_LOG_DOMAIN NULL
34 #endif
35
36 #ifdef __cplusplus
37 extern "C"
38 {
39 #endif
40
41 typedef enum {
42 BCTBX_LOG_DEBUG=1,
43 BCTBX_LOG_TRACE=1<<1,
44 BCTBX_LOG_MESSAGE=1<<2,
45 BCTBX_LOG_WARNING=1<<3,
46 BCTBX_LOG_ERROR=1<<4,
47 BCTBX_LOG_FATAL=1<<5,
48 BCTBX_LOG_LOGLEV_END=1<<6
49 } BctbxLogLevel;
50
51 typedef struct _bctbx_log_handler_t bctbx_log_handler_t;
52
53 typedef void (*BctbxLogFunc)(const char *domain, BctbxLogLevel lev, const char *fmt, va_list args);
54 typedef void (*BctbxLogHandlerFunc)(void *info,const char *domain, BctbxLogLevel lev, const char *fmt, va_list args);
55 typedef void (*BctbxLogHandlerDestroyFunc)(bctbx_log_handler_t *handler);
56
57 /*
58 initialise logging functions, add default log handler for stdout output.
59 @param[in] bool_t create : whether or not the initialisation should create a default logger in stdout or not.
60 */
61 BCTBX_PUBLIC void bctbx_init_logger(bool_t create);
62
63 /*
64 free logging memory
65 */
66 BCTBX_PUBLIC void bctbx_uninit_logger(void);
67
68 /*
69 Default functions to free log handlers
70 @param[in] bctbx_log_handler_t* handler : the handler to free
71 */
72 BCTBX_PUBLIC void bctbx_logv_out_destroy(bctbx_log_handler_t *handler);
73 BCTBX_PUBLIC void bctbx_logv_file_destroy(bctbx_log_handler_t *handler);
74
75 /*
76 Function to create a log handler
77 @param[in] BctbxLogHandlerFunc func : the function to call to handle a new line of log
78 @param[in] BctbxLogHandlerDestroyFunc destroy : the function to call to free this handler particuler its user_info field
79 @param[in] void* user_info : complementary information to handle the logs if needed
80 @return a new bctbx_log_handler_t
81 */
82 BCTBX_PUBLIC bctbx_log_handler_t* bctbx_create_log_handler(BctbxLogHandlerFunc func, BctbxLogHandlerDestroyFunc destroy, void* user_info);
83
84 /*
85 Function to create a file log handler
86 @param[in] uint64_t max_size : the maximum size of the log file before rotating to a new one (if 0 then no rotation)
87 @param[in] const char* path : the path where to put the log files
88 @param[in] const char* name : the name of the log files
89 @param[in] FILE* f : the file where to write the logs
90 @return a new bctbx_log_handler_t
91 */
92 BCTBX_PUBLIC bctbx_log_handler_t* bctbx_create_file_log_handler(uint64_t max_size, const char* path, const char* name, FILE* f);
93
94 BCTBX_PUBLIC void bctbx_add_log_handler(bctbx_log_handler_t* handler);
95 BCTBX_PUBLIC BCTBX_DEPRECATED void bctbx_set_log_handler(BctbxLogFunc func);
96 BCTBX_PUBLIC BCTBX_DEPRECATED void bctbx_set_log_file(FILE* f);
97 BCTBX_PUBLIC bctbx_list_t* bctbx_get_log_handlers(void);
98
99 BCTBX_PUBLIC void bctbx_logv_out(void* user_info, const char *domain, BctbxLogLevel level, const char *fmt, va_list args);
100 BCTBX_PUBLIC void bctbx_logv_file(void* user_info, const char *domain, BctbxLogLevel level, const char *fmt, va_list args);
101
102 #define bctbx_log_level_enabled(domain, level) (bctbx_get_log_level_mask(domain) & (level))
103
104 BCTBX_PUBLIC void bctbx_logv(const char *domain, BctbxLogLevel level, const char *fmt, va_list args);
105
106 /**
107 * Flushes the log output queue.
108 * WARNING: Must be called from the thread that has been defined with bctbx_set_log_thread_id().
109 */
110 BCTBX_PUBLIC void bctbx_logv_flush(void);
111
112 /**
113 * Activate all log level greater or equal than specified level argument.
114 **/
115 BCTBX_PUBLIC void bctbx_set_log_level(const char *domain, BctbxLogLevel level);
116
117 BCTBX_PUBLIC void bctbx_set_log_level_mask(const char *domain, int levelmask);
118 BCTBX_PUBLIC unsigned int bctbx_get_log_level_mask(const char *domain);
119
120 /**
121 * Tell oRTP the id of the thread used to output the logs.
122 * This is meant to output all the logs from the same thread to prevent deadlock problems at the application level.
123 * @param[in] thread_id The id of the thread that will output the logs (can be obtained using bctbx_thread_self()).
124 */
125 BCTBX_PUBLIC void bctbx_set_log_thread_id(unsigned long thread_id);
126
127 #ifdef __GNUC__
128 #define CHECK_FORMAT_ARGS(m,n) __attribute__((format(printf,m,n)))
129 #else
130 #define CHECK_FORMAT_ARGS(m,n)
131 #endif
132 #ifdef __clang__
133 /*in case of compile with -g static inline can produce this type of warning*/
134 #pragma GCC diagnostic ignored "-Wunused-function"
135 #endif
136 #ifdef BCTBX_DEBUG_MODE
bctbx_debug(const char * fmt,...)137 static BCTBX_INLINE void CHECK_FORMAT_ARGS(1,2) bctbx_debug(const char *fmt,...)
138 {
139 va_list args;
140 va_start (args, fmt);
141 bctbx_logv(BCTBX_LOG_DOMAIN, BCTBX_LOG_DEBUG, fmt, args);
142 va_end (args);
143 }
144 #else
145
146 #define bctbx_debug(...)
147
148 #endif
149
150 #ifdef BCTBX_NOMESSAGE_MODE
151
152 #define bctbx_log(...)
153 #define bctbx_message(...)
154 #define bctbx_warning(...)
155
156 #else
157
bctbx_log(const char * domain,BctbxLogLevel lev,const char * fmt,...)158 static BCTBX_INLINE void bctbx_log(const char* domain, BctbxLogLevel lev, const char *fmt,...) {
159 va_list args;
160 va_start (args, fmt);
161 bctbx_logv(domain, lev, fmt, args);
162 va_end (args);
163 }
164
bctbx_message(const char * fmt,...)165 static BCTBX_INLINE void CHECK_FORMAT_ARGS(1,2) bctbx_message(const char *fmt,...)
166 {
167 va_list args;
168 va_start (args, fmt);
169 bctbx_logv(BCTBX_LOG_DOMAIN, BCTBX_LOG_MESSAGE, fmt, args);
170 va_end (args);
171 }
172
bctbx_warning(const char * fmt,...)173 static BCTBX_INLINE void CHECK_FORMAT_ARGS(1,2) bctbx_warning(const char *fmt,...)
174 {
175 va_list args;
176 va_start (args, fmt);
177 bctbx_logv(BCTBX_LOG_DOMAIN, BCTBX_LOG_WARNING, fmt, args);
178 va_end (args);
179 }
180
181 #endif
182
bctbx_error(const char * fmt,...)183 static BCTBX_INLINE void CHECK_FORMAT_ARGS(1,2) bctbx_error(const char *fmt,...)
184 {
185 va_list args;
186 va_start (args, fmt);
187 bctbx_logv(BCTBX_LOG_DOMAIN, BCTBX_LOG_ERROR, fmt, args);
188 va_end (args);
189 }
190
bctbx_fatal(const char * fmt,...)191 static BCTBX_INLINE void CHECK_FORMAT_ARGS(1,2) bctbx_fatal(const char *fmt,...)
192 {
193 va_list args;
194 va_start (args, fmt);
195 bctbx_logv(BCTBX_LOG_DOMAIN, BCTBX_LOG_FATAL, fmt, args);
196 va_end (args);
197 }
198
199
200 #ifdef __QNX__
201 void bctbx_qnx_log_handler(const char *domain, BctbxLogLevel lev, const char *fmt, va_list args);
202 #endif
203
204
205 #ifdef __cplusplus
206 }
207
208 #include <string>
209 #include <iostream>
210 #include <sstream>
211
212 #if !defined(_WIN32) && !defined(__QNX__)
213 #include <syslog.h>
214 #endif
215
216 namespace bctoolbox {
217 namespace log {
218
219 // Here we define our application severity levels.
220 enum level { normal, trace, debug, info, warning, error, fatal };
221
222 // The formatting logic for the severity level
223 template <typename CharT, typename TraitsT>
224 inline std::basic_ostream<CharT, TraitsT> &operator<<(std::basic_ostream<CharT, TraitsT> &strm,
225 const bctoolbox::log::level &lvl) {
226 static const char *const str[] = {"normal", "trace", "debug", "info", "warning", "error", "fatal"};
227 if (static_cast<std::size_t>(lvl) < (sizeof(str) / sizeof(*str)))
228 strm << str[lvl];
229 else
230 strm << static_cast<int>(lvl);
231 return strm;
232 }
233
234 template <typename CharT, typename TraitsT>
235 inline std::basic_istream<CharT, TraitsT> &operator>>(std::basic_istream<CharT, TraitsT> &strm,
236 bctoolbox::log::level &lvl) {
237 static const char *const str[] = {"normal", "trace", "debug", "info", "warning", "error", "fatal"};
238
239 std::string s;
240 strm >> s;
241 for (unsigned int n = 0; n < (sizeof(str) / sizeof(*str)); ++n) {
242 if (s == str[n]) {
243 lvl = static_cast<bctoolbox::log::level>(n);
244 return strm;
245 }
246 }
247 // Parse error
248 strm.setstate(std::ios_base::failbit);
249 return strm;
250 }
251 }
252 }
253
254
255
256 #include <ostream>
257
258 struct pumpstream : public std::ostringstream {
259 const std::string mDomain;
260 const BctbxLogLevel level;
pumpstreampumpstream261 pumpstream(const std::string &domain, BctbxLogLevel l) : mDomain(domain), level(l) {}
262
~pumpstreampumpstream263 ~pumpstream() {
264 bctbx_log(mDomain.empty()?NULL:mDomain.c_str(), level, "%s", str().c_str());
265 }
266 };
267
268 #if (__GNUC__ == 4 && __GNUC_MINOR__ < 5 && __cplusplus > 199711L)
269 template <typename _Tp> inline pumpstream &operator<<(pumpstream &&__os, const _Tp &__x) {
270 (static_cast<std::ostringstream &>(__os)) << __x;
271 return __os;
272 }
273 #endif
274
275 #define BCTBX_SLOG(domain, thelevel) \
276 \
277 if (bctbx_log_level_enabled((domain), (thelevel))) \
278 pumpstream((domain != NULL ? domain : ""), (thelevel))
279
280 #define BCTBX_SLOGD(DOMAIN) BCTBX_SLOG(DOMAIN, BCTBX_LOG_DEBUG)
281 #define BCTBX_SLOGI(DOMAIN) BCTBX_SLOG((DOMAIN), (BCTBX_LOG_MESSAGE))
282 #define BCTBX_SLOGW(DOMAIN) BCTBX_SLOG(DOMAIN, BCTBX_LOG_WARNING)
283 #define BCTBX_SLOGE(DOMAIN) BCTBX_SLOG(DOMAIN, BCTBX_LOG_ERROR)
284
285
286 #endif
287
288 #endif
289