1 //! Flog - The F logging library
4 //! @author Nabeel Sowan (nabeel.sowan@vibes.se)
6 //! Useful as the main logger of a program or embedded system.
7 //! Requires C99 + GNU support
13 //! We need asprintf() for flog.c and flog_string.c
17 #include "flog_msg_id.h"
20 #ifdef FLOG_CONFIG_TIMESTAMP
21 #ifdef FLOG_CONFIG_TIMESTAMP_USEC
24 typedef struct timeval FLOG_TIMESTAMP_T
;
25 #else //FLOG_CONFIG_TIMESTAMP_USEC
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
39 typedef enum flog_msg_type
{
41 FLOG_NOTHING
= FLOG_NONE
,
44 FLOG_CRITICAL
= FLOG_CRIT
,
47 FLOG_ERROR
= FLOG_ERR
,
50 FLOG_WARNING
= FLOG_WARN
,
51 FLOG_ALERT
= FLOG_WARN
,
54 FLOG_NOTIFY
= FLOG_NOTE
,
56 FLOG_IMPORTANT
= FLOG_NOTE
,
59 FLOG_INFORMATION
= FLOG_INFO
,
61 FLOG_MESSAGE
= FLOG_INFO
,
64 FLOG_VERBOSE
= FLOG_VINFO
,
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
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
91 typedef uint_fast8_t FLOG_MSG_TYPE_T
;
94 #define FLOG_NONE 0x00
95 #define FLOG_NOTHING FLOG_NONE
98 #define FLOG_CRIT 0x01
99 #define FLOG_CRITICAL FLOG_CRIT
102 #define FLOG_ERR 0x02
103 #define FLOG_ERROR FLOG_ERR
106 #define FLOG_WARN 0x04
107 #define FLOG_WARNING FLOG_WARN
108 #define FLOG_ALERT FLOG_WARN
111 #define FLOG_NOTE 0x08
112 #define FLOG_NOTIFY FLOG_NOTE
113 #define FLOG_IMP FLOG_NOTE
114 #define FLOG_IMPORTANT FLOG_NOTE
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
127 #define FLOG_DEBUG 0x40
129 //! Deep debug info (such as when functions are started etc. )
130 #define FLOG_DEEP_DEBUG 0x80
135 //! @addtogroup FLOG_ACCEPT_BITMASKS
136 //! @brief Bitmasks for filtering messages
137 //! @details Set the variable @ref FLOG_T->accepted_message_type
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
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)
184 #define flog_print(p, subsystem, type, msg_id, text) _flog_print(p,subsystem,type,msg_id,text)
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__)
204 #define flog_printf(p, subsystem, type, msg_id, ...) _flog_printf(p,subsystem,type,msg_id,__VA_ARGS__)
208 //! @addtogroup flog_runtime_debug_macros
209 //! @brief Macros for runtime debugging
210 //! @details Use these macros for various debugging purposes
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) \
234 flog_printf(p,NULL,FLOG_ERROR,FLOG_MSG_ASSERTION_FAILED,#cond); \
238 #else //FLOG_CONFIG_ABORT_ON_ASSERT
239 #define flog_assert(p, cond) \
242 flog_printf(p,NULL,FLOG_ERROR,FLOG_MSG_ASSERTION_FAILED,#cond); \
244 #endif //FLOG_CONFIG_ABORT_ON_ASSERT
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
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()
261 #define flog_dprint(p, subsystem, type, msg_id, text) flog_print(p,subsystem,type,msg_id,text)
263 #define flog_dprint(p, subsystem, type, msg_id, text) (0)
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()
272 #define flog_dprintf(p, subsystem, type, msg_id, ...) flog_printf(p,subsystem,type,msg_id,__VA_ARGS__)
274 #define flog_dprintf(p, subsystem, type, msg_id, ...) (0)
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()
283 #define flog_debug_function_start(p, subsystem) flog_function_start(p, subsystem)
285 #define flog_debug_function_start(p, subsystem) (0)
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()
294 #define flog_debug_function_end(p, subsystem) flog_function_end(p, subsystem)
296 #define flog_debug_function_end(p, subsystem) (0)
303 //! Message structure - Holds all data related to a single message
305 char *subsystem
; //!< subsystem which is outputting the msg
306 #ifdef FLOG_CONFIG_TIMESTAMP
307 FLOG_TIMESTAMP_T timestamp
; //!< timestamp
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
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
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
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
,
347 #ifdef FLOG_CONFIG_SRC_INFO
348 const char *src_file
,uint_fast16_t src_line
,const char *src_func
,
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
, ...);
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
, ...);
371 void flog_test(FLOG_T
*p
);