fix bug in handling of FLOG_MSG_T.src_line (changed from signed to unsigned)
[flog.git] / flog.h
blobb5cdd4e2b6978d71f3f64978695cae681a8b2c75
1 //! Flog - The F logging library
3 //! @file flog.h
4 //! @author Nabeel Sowan (nabeel.sowan@vibes.se)
5 //!
6 //! Useful as the main logger of a program or embedded system.
7 //! Requires C99 + GNU support
10 #ifndef FLOG_H
11 #define FLOG_H
13 //! We need asprintf() for flog.c and flog_string.c
14 #define _GNU_SOURCE
16 #include "config.h"
17 #include "flog_msg_id.h"
18 #include <stdint.h>
20 #ifdef FLOG_CONFIG_TIMESTAMP
21 #ifdef FLOG_CONFIG_TIMESTAMP_USEC
22 #include <sys/time.h>
23 #include <time.h>
24 typedef struct timeval FLOG_TIMESTAMP_T;
25 #else //FLOG_CONFIG_TIMESTAMP_USEC
26 #include <time.h>
27 typedef time_t FLOG_TIMESTAMP_T;
28 #endif //FLOG_CONFIG_TIMESTAMP_USEC
29 #endif //FLOG_CONFIG_TIMESTAMP
32 #ifdef FLOG_CONFIG_MSG_TYPE_ENUM_API
34 //! @addtogroup FLOG_MSG_TYPE_T
35 //! @brief Types of messages supported by FLOG
36 //! @details Use where ever a @ref FLOG_MSG_TYPE_T is referred
37 //! @{
39 typedef enum flog_msg_type {
40 FLOG_NONE = 0x00,
41 FLOG_NOTHING = FLOG_NONE,
43 FLOG_CRIT = 0x01,
44 FLOG_CRITICAL = FLOG_CRIT,
46 FLOG_ERR = 0x02,
47 FLOG_ERROR = FLOG_ERR,
49 FLOG_WARN = 0x04,
50 FLOG_WARNING = FLOG_WARN,
51 FLOG_ALERT = FLOG_WARN,
53 FLOG_NOTE = 0x08,
54 FLOG_NOTIFY = FLOG_NOTE,
55 FLOG_IMP = FLOG_NOTE,
56 FLOG_IMPORTANT = FLOG_NOTE,
58 FLOG_INFO = 0x10,
59 FLOG_INFORMATION = FLOG_INFO,
60 FLOG_MSG = FLOG_INFO,
61 FLOG_MESSAGE = FLOG_INFO,
63 FLOG_VINFO = 0x20,
64 FLOG_VERBOSE = FLOG_VINFO,
66 FLOG_DEBUG = 0x40,
68 FLOG_DEEP_DEBUG = 0x80,
70 FLOG_ACCEPT_ONLY_CRITICAL = FLOG_CRIT,
71 FLOG_ACCEPT_ONLY_ERROR = FLOG_CRIT | FLOG_ERR,
72 FLOG_ACCEPT_ERROR_AND_WARNING = FLOG_CRIT | FLOG_ERR | FLOG_WARN,
73 FLOG_ACCEPT_IMPORTANT_NOTES = FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE,
74 FLOG_ACCEPT_INFO = FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE | FLOG_INFO,
75 FLOG_ACCEPT_VERBOSE_INFO = FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE | FLOG_INFO | FLOG_VINFO,
76 FLOG_ACCEPT_DEBUG = FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE | FLOG_INFO | FLOG_VINFO | FLOG_DEBUG,
77 FLOG_ACCEPT_DEEP_DEBUG = FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE | FLOG_INFO | FLOG_VINFO | FLOG_DEBUG | FLOG_DEEP_DEBUG,
78 FLOG_ACCEPT_ALL = FLOG_ACCEPT_DEBUG
79 } FLOG_MSG_TYPE_T;
81 //! @}
83 #else //FLOG_CONFIG_MSG_TYPE_ENUM_API
86 //! @addtogroup FLOG_MSG_TYPE_T
87 //! @brief Types of messages supported by FLOG
88 //! @details Use where ever a @ref FLOG_MSG_TYPE_T is referred
89 //! @{
91 typedef uint_fast8_t FLOG_MSG_TYPE_T;
93 //! Nothing
94 #define FLOG_NONE 0x00
95 #define FLOG_NOTHING FLOG_NONE
97 //! Critical error
98 #define FLOG_CRIT 0x01
99 #define FLOG_CRITICAL FLOG_CRIT
101 //! Error
102 #define FLOG_ERR 0x02
103 #define FLOG_ERROR FLOG_ERR
105 //! Warning
106 #define FLOG_WARN 0x04
107 #define FLOG_WARNING FLOG_WARN
108 #define FLOG_ALERT FLOG_WARN
110 //! Note
111 #define FLOG_NOTE 0x08
112 #define FLOG_NOTIFY FLOG_NOTE
113 #define FLOG_IMP FLOG_NOTE
114 #define FLOG_IMPORTANT FLOG_NOTE
116 //! Info
117 #define FLOG_INFO 0x10
118 #define FLOG_INFORMATION FLOG_INFO
119 #define FLOG_MSG FLOG_INFO
120 #define FLOG_MESSAGE FLOG_INFO
122 //! Info in verbose mode
123 #define FLOG_VINFO 0x20
124 #define FLOG_VERBOSE FLOG_VINFO
126 //! Debug info
127 #define FLOG_DEBUG 0x40
129 //! Deep debug info (such as when functions are started etc. )
130 #define FLOG_DEEP_DEBUG 0x80
132 //! @}
135 //! @addtogroup FLOG_ACCEPT_BITMASKS
136 //! @brief Bitmasks for filtering messages
137 //! @details Set the variable @ref FLOG_T->accepted_message_type
138 //! @{
140 //! Bitmask to accept only critical
141 #define FLOG_ACCEPT_ONLY_CRITICAL FLOG_CRIT
142 //! Bitmask to accept only errors
143 #define FLOG_ACCEPT_ONLY_ERROR FLOG_CRIT | FLOG_ERR
144 //! Bitmask to accept error and warning
145 #define FLOG_ACCEPT_ERROR_AND_WARNING FLOG_CRIT | FLOG_ERR | FLOG_WARN
146 //! Bitmask to accept all important messages
147 #define FLOG_ACCEPT_IMPORTANT_NOTE FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE
148 //! Bitmask to accept informational messages
149 #define FLOG_ACCEPT_INFO FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE | FLOG_INFO
150 //! Bitmask to accept verbose messages
151 #define FLOG_ACCEPT_VERBOSE_INFO FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE | FLOG_INFO | FLOG_VINFO
152 //! Bitmask to accept all messages (except deep debug)
153 #define FLOG_ACCEPT_DEBUG FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE | FLOG_INFO | FLOG_VINFO | FLOG_DEBUG
154 //! Bitmask to accept all messages
155 #define FLOG_ACCEPT_DEEP_DEBUG FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE | FLOG_INFO | FLOG_VINFO | FLOG_DEBUG | FLOG_DEEP_DEBUG
156 //! Bitmask to accept all messages (except deep debug)
157 #define FLOG_ACCEPT_ALL FLOG_ACCEPT_DEBUG
159 //! @}
161 #endif //FLOG_CONFIG_MSG_TYPE_ENUM_API
164 // Macros to insert source info into print strings
165 // Maybe it is better to use __func__ than __FUNCTION__ ?
168 //! emit an flog message
170 //! use this when you need to emit simple text messages and flog_printf() when formatting is needed
171 //! @param[in,out] p log to emit message to
172 //! @param[in] subsystem which part of the program is outputing this message
173 //! @param[in] type use one of the FLOG_* defines
174 //! @param[in] msg_id optionally use errno or one of the FLOG_MSG_* defines
175 //! @param[in] text message text
176 //! @retval 0 success
177 //! @retval 1 error while adding message to log
178 //! @retval 2 error unable to get time
179 //! @retval 3 did not add null message (flog is configured not to allow null messages)
180 //! @see _flog_print(), flog_printf(), flog_dprint()
181 #ifdef FLOG_CONFIG_SRC_INFO
182 #define flog_print(p, subsystem, type, msg_id, text) _flog_print(p,subsystem,__FILE__,__LINE__,__FUNCTION__,type,msg_id,text)
183 #else
184 #define flog_print(p, subsystem, type, msg_id, text) _flog_print(p,subsystem,type,msg_id,text)
185 #endif
188 //! emit a formatted flog message (calls flog_print())
190 //! use this when you need to emit formatted text messages and flog_print() when no formatting is needed
191 //! @param[in,out] p log to emit message to
192 //! @param[in] subsystem which part of the program is outputing this message
193 //! @param[in] type use one of the FLOG_* defines
194 //! @param[in] msg_id optionally use errno or one of the FLOG_MSG_* defines
195 //! @param[in] ... formatted message text
196 //! @retval 0 success
197 //! @retval 1 error while adding message to log
198 //! @retval 2 error unable to get time
199 //! @retval 3 did not add null message (flog is configured not to allow null messages)
200 //! @see _flog_printf(), flog_print(), flog_dprintf()
201 #ifdef FLOG_CONFIG_SRC_INFO
202 #define flog_printf(p, subsystem, type, msg_id, ...) _flog_printf(p,subsystem,__FILE__,__LINE__,__FUNCTION__,type,msg_id,__VA_ARGS__)
203 #else
204 #define flog_printf(p, subsystem, type, msg_id, ...) _flog_printf(p,subsystem,type,msg_id,__VA_ARGS__)
205 #endif
208 //! @addtogroup flog_runtime_debug_macros
209 //! @brief Macros for runtime debugging
210 //! @details Use these macros for various debugging purposes
211 //! @{
214 //! Macro to signify function start
216 //! Use this macro for deep debugging of program flow
217 #define flog_function_start(p, subsystem) flog_printf(p,subsystem,FLOG_DEEP_DEBUG,FLOG_MSG_FUNCTION_START,"%s()",__FUNCTION__)
220 //! Macro to signify function end
222 //! Use this macro for deep debugging of program flow
223 #define flog_function_end(p, subsystem) flog_printf(p,subsystem,FLOG_DEEP_DEBUG,FLOG_MSG_FUNCTION_END,"%s()",__FUNCTION__)
226 //! Macro for flog assert functionality
228 //! @param[in,out] p log to emit message to
229 //! @param[in] cond statement to evaluate
230 #ifdef FLOG_CONFIG_ABORT_ON_ASSERT
231 #define flog_assert(p, cond) \
233 if(!(cond)) { \
234 flog_printf(p,NULL,FLOG_ERROR,FLOG_MSG_ASSERTION_FAILED,#cond); \
235 abort(); \
238 #else //FLOG_CONFIG_ABORT_ON_ASSERT
239 #define flog_assert(p, cond) \
241 if(!(cond)) \
242 flog_printf(p,NULL,FLOG_ERROR,FLOG_MSG_ASSERTION_FAILED,#cond); \
244 #endif //FLOG_CONFIG_ABORT_ON_ASSERT
247 //! @}
250 //! @addtogroup flog_buildtime_debug_macros
251 //! @brief Macros that are only defined when DEBUG is defined
252 //! @details Use these macros to allow removal of messages from release builds
253 //! @{
256 //! Same as flog_print() but only defined if DEBUG is set
258 //! Use this macro to allow removal of messages from release builds
259 //! @see flog_print()
260 #ifdef DEBUG
261 #define flog_dprint(p, subsystem, type, msg_id, text) flog_print(p,subsystem,type,msg_id,text)
262 #else
263 #define flog_dprint(p, subsystem, type, msg_id, text) (0)
264 #endif
267 //! Same as flog_printf() but only defined if DEBUG is set
269 //! Use this macro to allow removal of messages from release builds
270 //! @see flog_printf()
271 #ifdef DEBUG
272 #define flog_dprintf(p, subsystem, type, msg_id, ...) flog_printf(p,subsystem,type,msg_id,__VA_ARGS__)
273 #else
274 #define flog_dprintf(p, subsystem, type, msg_id, ...) (0)
275 #endif
278 //! Same as flog_function_start() but only defined if DEBUG is set
280 //! Use this macro to allow removal of messages from release builds
281 //! @see flog_function_start()
282 #ifdef DEBUG
283 #define flog_debug_function_start(p, subsystem) flog_function_start(p, subsystem)
284 #else
285 #define flog_debug_function_start(p, subsystem) (0)
286 #endif
289 //! Same as flog_function_end() but only defined if DEBUG is set
291 //! Use this macro to allow removal of messages from release builds
292 //! @see flog_function_end()
293 #ifdef DEBUG
294 #define flog_debug_function_end(p, subsystem) flog_function_end(p, subsystem)
295 #else
296 #define flog_debug_function_end(p, subsystem) (0)
297 #endif
300 //! @}
303 //! Message structure - Holds all data related to a single message
304 typedef struct {
305 char *subsystem; //!< subsystem which is outputting the msg
306 #ifdef FLOG_CONFIG_TIMESTAMP
307 FLOG_TIMESTAMP_T timestamp; //!< timestamp
308 #endif
309 #ifdef FLOG_CONFIG_SRC_INFO
310 char *src_file; //!< source file emitting message
311 uint_fast16_t src_line; //!< source line number emitting message
312 char *src_func; //!< source function emitting message
313 #endif
314 FLOG_MSG_TYPE_T type; //!< type of message
315 FLOG_MSG_ID_T msg_id; //!< message id (instead of, or with text) see flog_msg_id.h
316 char *text; //!< message text
317 } FLOG_MSG_T;
320 //! Main log structure - typedefined as @ref FLOG_T
322 //! These can be appended to each other in a tree structure (by using flog_append_sublog())
323 //! to form good flow and structure in software.
324 //! Sublogs are created for 3 main purposes: namespacing, multiple outputs and filtering
325 typedef struct flog_t {
326 char *name; //!< name of log
327 FLOG_MSG_TYPE_T accepted_msg_type; //!< bitmask of which messages to accept
328 int (*output_func)(struct flog_t *,const FLOG_MSG_T *); //!< function to output messages to
329 void *output_func_data; //!< data passed to output func
330 uint_fast16_t output_error; //!< errors occurred on output
331 uint_fast8_t output_stop_on_error; //!< stop outputting messages on error
332 struct flog_t *error_log; //!< error log for flog errors
333 FLOG_MSG_T **msg; //!< array of messages
334 uint_fast16_t msg_amount; //!< amount of messages in array
335 uint_fast16_t msg_max; //!< maximum amount of buffered messages
336 struct flog_t **sublog; //!< array of sublogs
337 uint_fast8_t sublog_amount; //!< amount of sublogs in array
338 } FLOG_T;
341 void init_flog_msg_t(FLOG_MSG_T *p);
343 FLOG_MSG_T * create_flog_msg_t(const char *subsystem,
344 #ifdef FLOG_CONFIG_TIMESTAMP
345 FLOG_TIMESTAMP_T timestamp,
346 #endif
347 #ifdef FLOG_CONFIG_SRC_INFO
348 const char *src_file,uint_fast16_t src_line,const char *src_func,
349 #endif
350 FLOG_MSG_TYPE_T msg_type,FLOG_MSG_ID_T msg_id,const char *text);
352 void destroy_flog_msg_t(FLOG_MSG_T *p);
354 void init_flog_t(FLOG_T *p);
355 FLOG_T * create_flog_t(const char *name, FLOG_MSG_TYPE_T accepted_msg_type);
356 void destroy_flog_t(FLOG_T *p);
358 int flog_add_msg(FLOG_T *p,FLOG_MSG_T *msg);
359 void flog_clear_msg_buffer(FLOG_T *p);
360 int flog_append_sublog(FLOG_T *p,FLOG_T *sublog);
362 #ifdef FLOG_CONFIG_SRC_INFO
363 int _flog_print(FLOG_T *p,const char *subsystem,const char *src_file,uint_fast16_t src_line,const char *src_func,FLOG_MSG_TYPE_T type,FLOG_MSG_ID_T msg_id,const char *text);
364 int _flog_printf(FLOG_T *p,const char *subsystem,const char *src_file,uint_fast16_t src_line,const char *src_func,FLOG_MSG_TYPE_T type,FLOG_MSG_ID_T msg_id,const char *textf, ...);
365 #else
366 int _flog_print(FLOG_T *p,const char *subsystem,FLOG_MSG_TYPE_T type,FLOG_MSG_ID_T msg_id,const char *text);
367 int _flog_printf(FLOG_T *p,const char *subsystem,FLOG_MSG_TYPE_T type,FLOG_MSG_ID_T msg_id,const char *textf, ...);
368 #endif
370 #ifdef DEBUG
371 void flog_test(FLOG_T *p);
372 #endif
374 #endif