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"
21 #ifdef FLOG_TIMESTAMP_USEC
24 typedef struct timeval FLOG_TIMESTAMP_T
;
25 #else //FLOG_TIMESTAMP_USEC
27 typedef time_t FLOG_TIMESTAMP_T
;
28 #endif //FLOG_TIMESTAMP_USEC
29 #endif //FLOG_TIMESTAMP
32 #ifdef FLOG_CONFIG_MSG_TYPE_ENUM_API
34 typedef enum flog_msg_type
{
36 FLOG_NOTHING
= FLOG_NONE
,
39 FLOG_CRITICAL
= FLOG_CRIT
,
42 FLOG_ERROR
= FLOG_ERR
,
45 FLOG_WARNING
= FLOG_WARN
,
46 FLOG_ALERT
= FLOG_WARN
,
49 FLOG_NOTIFY
= FLOG_NOTE
,
51 FLOG_IMPORTANT
= FLOG_NOTE
,
54 FLOG_INFORMATION
= FLOG_INFO
,
56 FLOG_MESSAGE
= FLOG_INFO
,
59 FLOG_VERBOSE
= FLOG_VINFO
,
63 FLOG_DEEP_DEBUG
= 0x80,
65 FLOG_ACCEPT_ONLY_CRITICAL
= FLOG_CRIT
,
66 FLOG_ACCEPT_ONLY_ERROR
= FLOG_CRIT
| FLOG_ERR
,
67 FLOG_ACCEPT_ERROR_AND_WARNING
= FLOG_CRIT
| FLOG_ERR
| FLOG_WARN
,
68 FLOG_ACCEPT_IMPORTANT_NOTES
= FLOG_CRIT
| FLOG_ERR
| FLOG_WARN
| FLOG_NOTE
,
69 FLOG_ACCEPT_INFO
= FLOG_CRIT
| FLOG_ERR
| FLOG_WARN
| FLOG_NOTE
| FLOG_INFO
,
70 FLOG_ACCEPT_VERBOSE_INFO
= FLOG_CRIT
| FLOG_ERR
| FLOG_WARN
| FLOG_NOTE
| FLOG_INFO
| FLOG_VINFO
,
71 FLOG_ACCEPT_DEBUG
= FLOG_CRIT
| FLOG_ERR
| FLOG_WARN
| FLOG_NOTE
| FLOG_INFO
| FLOG_VINFO
| FLOG_DEBUG
,
72 FLOG_ACCEPT_DEEP_DEBUG
= FLOG_CRIT
| FLOG_ERR
| FLOG_WARN
| FLOG_NOTE
| FLOG_INFO
| FLOG_VINFO
| FLOG_DEBUG
| FLOG_DEEP_DEBUG
,
73 FLOG_ACCEPT_ALL
= FLOG_ACCEPT_DEBUG
76 #else //FLOG_CONFIG_MSG_TYPE_ENUM_API
79 //! @addtogroup FLOG_MSG_TYPE_T
80 //! @brief Types of messages supported by FLOG
81 //! @details Use where ever a @ref FLOG_MSG_TYPE_T is referred
84 typedef uint_fast8_t FLOG_MSG_TYPE_T
;
87 #define FLOG_NONE 0x00
88 #define FLOG_NOTHING FLOG_NONE
91 #define FLOG_CRIT 0x01
92 #define FLOG_CRITICAL FLOG_CRIT
96 #define FLOG_ERROR FLOG_ERR
99 #define FLOG_WARN 0x04
100 #define FLOG_WARNING FLOG_WARN
101 #define FLOG_ALERT FLOG_WARN
104 #define FLOG_NOTE 0x08
105 #define FLOG_NOTIFY FLOG_NOTE
106 #define FLOG_IMP FLOG_NOTE
107 #define FLOG_IMPORTANT FLOG_NOTE
110 #define FLOG_INFO 0x10
111 #define FLOG_INFORMATION FLOG_INFO
112 #define FLOG_MSG FLOG_INFO
113 #define FLOG_MESSAGE FLOG_INFO
115 //! Info in verbose mode
116 #define FLOG_VINFO 0x20
117 #define FLOG_VERBOSE FLOG_VINFO
120 #define FLOG_DEBUG 0x40
122 //! Deep debug info (such as when functions are started etc. )
123 #define FLOG_DEEP_DEBUG 0x80
128 //! @addtogroup FLOG_ACCEPT_BITMASKS
129 //! @brief Bitmasks for filtering messages
130 //! @details Set the variable @ref FLOG_T->accepted_message_type
133 //! Bitmask to accept only critical
134 #define FLOG_ACCEPT_ONLY_CRITICAL FLOG_CRIT
135 //! Bitmask to accept only errors
136 #define FLOG_ACCEPT_ONLY_ERROR FLOG_CRIT | FLOG_ERR
137 //! Bitmask to accept error and warning
138 #define FLOG_ACCEPT_ERROR_AND_WARNING FLOG_CRIT | FLOG_ERR | FLOG_WARN
139 //! Bitmask to accept all important messages
140 #define FLOG_ACCEPT_IMPORTANT_NOTE FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE
141 //! Bitmask to accept informational messages
142 #define FLOG_ACCEPT_INFO FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE | FLOG_INFO
143 //! Bitmask to accept verbose messages
144 #define FLOG_ACCEPT_VERBOSE_INFO FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE | FLOG_INFO | FLOG_VINFO
145 //! Bitmask to accept all messages (except deep debug)
146 #define FLOG_ACCEPT_DEBUG FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE | FLOG_INFO | FLOG_VINFO | FLOG_DEBUG
147 //! Bitmask to accept all messages
148 #define FLOG_ACCEPT_DEEP_DEBUG FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE | FLOG_INFO | FLOG_VINFO | FLOG_DEBUG | FLOG_DEEP_DEBUG
149 //! Bitmask to accept all messages (except deep debug)
150 #define FLOG_ACCEPT_ALL FLOG_ACCEPT_DEBUG
154 #endif //FLOG_CONFIG_MSG_TYPE_ENUM_API
157 // Macros to insert source info into print strings
158 // Maybe it is better to use __func__ than __FUNCTION__ ?
161 //! emit an flog message
163 //! use this when you need to emit simple text messages and flog_printf() when formatting is needed
164 //! @param[in,out] p log to emit message to
165 //! @param[in] type use one of the FLOG_* defines
166 //! @param[in] subsystem which part of the program is outputing this message
167 //! @param[in] text message text
168 //! @retval 0 success
169 //! @see _flog_print(), flog_printf(), flog_dprint()
171 #define flog_print(p, subsystem, type, msg_id, text) _flog_print(p,subsystem,__FILE__,__LINE__,__FUNCTION__,type,msg_id,text)
173 #define flog_print(p, subsystem, type, msg_id, text) _flog_print(p,subsystem,type,msg_id,text)
177 //! emit a formatted flog message (calls flog_print())
179 //! use this when you need to emit formatted text messages and flog_print() when no formatting is needed
180 //! @param[in,out] p log to emit message to
181 //! @param[in] type use one of the FLOG_* defines
182 //! @param[in] subsystem which part of the program is outputing this message
183 //! @param[in] ... formatted message text
184 //! @retval 0 success
185 //! @see _flog_printf(), flog_print(), flog_dprintf()
187 #define flog_printf(p, subsystem, type, msg_id, ...) _flog_printf(p,subsystem,__FILE__,__LINE__,__FUNCTION__,type,msg_id,__VA_ARGS__)
189 #define flog_printf(p, subsystem, type, msg_id, ...) _flog_printf(p,subsystem,type,msg_id,__VA_ARGS__)
193 //! Same as flog_print() but only defined if DEBUG is set
195 //! Use this macro to allow removal of messages from release builds
196 //! @see flog_print()
198 #define flog_dprint(p, subsystem, type, msg_id, text) flog_print(p,subsystem,type,msg_id,text)
200 #define flog_dprint(p, subsystem, type, msg_id, text)
204 //! Same as flog_printf() but only defined if DEBUG is set
206 //! Use this macro to allow removal of messages from release builds
207 //! @see flog_printf()
209 #define flog_dprintf(p, subsystem, type, msg_id, ...) flog_printf(p,subsystem,type,msg_id,__VA_ARGS__)
211 #define flog_dprintf(p, subsystem, type, msg_id, ...)
215 //! Macro for flog assert functionality
217 //! @param[in,out] p log to emit message to
218 //! @param[in] cond statement to evaluate
219 #ifdef FLOG_ABORT_ON_ASSERT
220 #define flog_assert(p, cond) \
223 flog_printf(p,NULL,FLOG_ERROR,FLOG_MSG_ASSERTION_FAILED,#cond); \
228 #define flog_assert(p, cond) \
231 flog_printf(p,NULL,FLOG_ERROR,FLOG_MSG_ASSERTION_FAILED,#cond); \
236 //! Message structure - Holds all data related to a single message
238 char *subsystem
; //!< subsystem which is outputting the msg
239 #ifdef FLOG_TIMESTAMP
240 FLOG_TIMESTAMP_T timestamp
; //!< timestamp
243 char *src_file
; //!< source file emitting message
244 uint_fast16_t src_line
; //!< source line number emitting message
245 char *src_func
; //!< source function emitting message
247 FLOG_MSG_TYPE_T type
; //!< type of message
248 FLOG_MSG_ID_T msg_id
; //!< message id (instead of, or with text) see flog_msg_id.h
249 char *text
; //!< message text
253 //! Main log structure - typedefined as @ref FLOG_T
255 //! These can be appended to each other in a tree structure (by using flog_append_sublog())
256 //! to form good flow and structure in software.
257 //! Sublogs are created for 3 main purposes: namespacing, multiple outputs and filtering
258 typedef struct flog_t
{
259 char *name
; //!< name of log
260 FLOG_MSG_TYPE_T accepted_msg_type
; //!< bitmask of which messages to accept
261 int (*output_func
)(struct flog_t
*,const FLOG_MSG_T
*); //!< function to output messages to
262 void *output_func_data
; //!< data passed to output func
263 uint_fast8_t output_error
; //!< errors occurred on output
264 uint_fast8_t output_stop_on_error
; //!< stop outputting messages on error
265 struct flog_t
*error_log
; //!< error log for flog errors
266 FLOG_MSG_T
**msg
; //!< array of messages
267 uint_fast16_t msg_amount
; //!< amount of messages in array
268 uint_fast16_t msg_max
; //!< maximum amount of buffered messages
269 struct flog_t
**sublog
; //!< array of sublogs
270 uint_fast8_t sublog_amount
; //!< amount of sublogs in array
274 void init_flog_msg_t(FLOG_MSG_T
*p
);
276 FLOG_MSG_T
* create_flog_msg_t(const char *subsystem
,
277 #ifdef FLOG_TIMESTAMP
278 FLOG_TIMESTAMP_T timestamp
,
281 const char *src_file
,int src_line
,const char *src_func
,
283 FLOG_MSG_TYPE_T msg_type
,FLOG_MSG_ID_T msg_id
,const char *text
);
285 void destroy_flog_msg_t(FLOG_MSG_T
*p
);
287 void init_flog_t(FLOG_T
*p
);
288 FLOG_T
* create_flog_t(const char *name
, FLOG_MSG_TYPE_T accepted_msg_type
);
289 void destroy_flog_t(FLOG_T
*p
);
291 int flog_add_msg(FLOG_T
*p
,FLOG_MSG_T
*msg
);
292 void flog_clear_msg_buffer(FLOG_T
*p
);
293 int flog_append_sublog(FLOG_T
*p
,FLOG_T
*sublog
);
296 int _flog_print(FLOG_T
*p
,const char *subsystem
,const char *src_file
,int src_line
,const char *src_func
,FLOG_MSG_TYPE_T type
,FLOG_MSG_ID_T msg_id
,const char *text
);
297 int _flog_printf(FLOG_T
*p
,const char *subsystem
,const char *src_file
,int src_line
,const char *src_func
,FLOG_MSG_TYPE_T type
,FLOG_MSG_ID_T msg_id
,const char *textf
, ...);
299 int _flog_print(FLOG_T
*p
,const char *subsystem
,FLOG_MSG_TYPE_T type
,FLOG_MSG_ID_T msg_id
,const char *text
);
300 int _flog_printf(FLOG_T
*p
,const char *subsystem
,FLOG_MSG_TYPE_T type
,FLOG_MSG_ID_T msg_id
,const char *textf
, ...);
304 void flog_test(FLOG_T
*p
);