3 @brief Flog logging library
4 @author Nabeel Sowan (nabeel.sowan@vibes.se)
6 Useful as the main logger of a program
18 //! initialise a FLOG_MSG_T to defaults
19 void init_flog_msg_t(FLOG_MSG_T
*p
)
34 //! create and return a FLOG_MSG_T type
39 FLOG_MSG_T
* create_flog_msg_t(const char *src_file
,int src_line
,const char *src_func
,FLOG_MSG_TYPE_T type
,const char *subsystem
,const char *text
)
41 FLOG_MSG_T
* create_flog_msg_t(FLOG_MSG_TYPE_T type
,const char *subsystem
,const char *text
)
47 if((p
=malloc(sizeof(FLOG_MSG_T
)))!=NULL
) {
53 if((src_file
!= NULL
) && (strlen(src_file
)>0)) {
54 if(asprintf(&p
->src_file
,src_file
)==-1) {
55 destroy_flog_msg_t(p
);
60 if((src_func
!= NULL
) && (strlen(src_func
)>0)) {
61 if(asprintf(&p
->src_func
,src_func
)==-1) {
62 destroy_flog_msg_t(p
);
68 if((subsystem
!= NULL
) && (strlen(subsystem
)>0)) {
69 if(asprintf(&p
->subsystem
,subsystem
)==-1) {
70 destroy_flog_msg_t(p
);
74 if(asprintf(&p
->text
,text
)==-1) {
75 destroy_flog_msg_t(p
);
83 void destroy_flog_msg_t(FLOG_MSG_T
*p
)
96 //! initialise a FLOG_T to defaults
97 void init_flog_t(FLOG_T
*p
)
100 p
->accepted_msg_type
=FLOG_ACCEPT_ALL
;
102 p
->output_func_data
=NULL
;
104 p
->output_stop_on_error
=1;
113 //! create and return a FLOG_T type
117 FLOG_T
* create_flog_t(const char *name
, FLOG_MSG_TYPE_T accepted_msg_type
)
120 if((p
=malloc(sizeof(FLOG_T
)))!=NULL
) {
122 p
->accepted_msg_type
=accepted_msg_type
;
123 if((name
!= NULL
) && (strlen(name
)>0)) {
124 if(asprintf(&p
->name
,name
)==-1) {
134 void destroy_flog_t(FLOG_T
*p
)
140 for(i
=0;i
<p
->msg_amount
;i
++)
141 destroy_flog_msg_t(p
->msg
[i
]);
144 free(p
->sublog
); //!< Note that the sublogs themselves are not freed
149 //! add a FLOG_MSG_T to FLOG_T and do all required logic (used by flog_print[f] functions)
152 @param msg message to add
155 int flog_add_msg(FLOG_T
*p
,FLOG_MSG_T
*msg
)
159 //create temporary msg to allow reformatting the message
162 if((tmpmsg
=create_flog_msg_t(msg
->src_file
,msg
->src_line
,msg
->src_func
,msg
->type
,msg
->subsystem
,msg
->text
))==NULL
)
164 if((tmpmsg
=create_flog_msg_t(msg
->type
,msg
->subsystem
,msg
->text
))==NULL
)
168 //append name to subsystem
169 if((p
->name
!= NULL
) && (strlen(p
->name
)==0))
171 if((tmpmsg
->subsystem
!= NULL
) && (strlen(tmpmsg
->subsystem
)==0))
172 free(tmpmsg
->subsystem
);
173 if((p
->name
!= NULL
) && (tmpmsg
->subsystem
!= NULL
)) {
175 if(asprintf(&tmpstr
,"%s/%s",p
->name
,tmpmsg
->subsystem
)!=-1) {
176 free(tmpmsg
->subsystem
);
177 tmpmsg
->subsystem
=tmpstr
;
180 else if((p
->name
!= NULL
) && (tmpmsg
->subsystem
== NULL
))
181 asprintf(&tmpmsg
->subsystem
,p
->name
);
183 //compare if accepted message type
184 if(tmpmsg
->type
& p
->accepted_msg_type
) {
185 //add message to buffer
186 if(p
->msg_amount
<p
->msg_max
) {
187 FLOG_MSG_T
**new_msg
;
188 if((new_msg
=realloc(p
->msg
,(p
->msg_amount
+1)*sizeof(FLOG_MSG_T
*)))!=NULL
) {
190 p
->msg
[p
->msg_amount
]=msg
;
195 //run output function
196 if(p
->output_func
!= NULL
) {
197 if(p
->output_stop_on_error
? !p
->output_error
: 1) {
198 if((e
=p
->output_func(p
,tmpmsg
)))
204 //add message to sublogs
206 for(i
=0;i
<p
->sublog_amount
;i
++) {
207 if(flog_add_msg(p
->sublog
[i
],tmpmsg
))
210 destroy_flog_msg_t(tmpmsg
);
214 //! clear all messages stored in log
215 void flog_clear_msg_buffer(FLOG_T
*p
)
217 if((p
!=NULL
) && (p
->msg
!=NULL
)) {
219 for(i
=0;i
<p
->msg_amount
;i
++)
220 destroy_flog_msg_t(p
->msg
[i
]);
226 //! add a sublog to a log
229 @param sublog log to add
232 int flog_append_sublog(FLOG_T
*p
,FLOG_T
*sublog
)
237 flog_print(p
->error_log
,FLOG_ERROR
,"flog_append_sublog","cannot append log to itself (causes circular dependency)");
241 if((new_sublog
=realloc(p
->sublog
,(p
->sublog_amount
+1)*sizeof(FLOG_T
*)))==NULL
)
243 p
->sublog
=new_sublog
;
244 p
->sublog
[p
->sublog_amount
]=sublog
;
249 //! output an flog message
251 @param type use one of the FLOG_* defines
252 @param subsystem which part of the program is outputing this message (use __func__ typically)
253 @param text message text
257 int _flog_print(FLOG_T
*p
,const char *src_file
,int src_line
,const char *src_func
,FLOG_MSG_TYPE_T type
,const char *subsystem
,const char *text
)
259 int _flog_print(FLOG_T
*p
,FLOG_MSG_TYPE_T type
,const char *subsystem
,const char *text
)
266 if((msg
=create_flog_msg_t(src_file
,src_line
,src_func
,type
,subsystem
,text
))==NULL
)
268 if((msg
=create_flog_msg_t(type
,subsystem
,text
))==NULL
)
271 if(flog_add_msg(p
,msg
)) {
272 destroy_flog_msg_t(msg
);
275 destroy_flog_msg_t(msg
);
279 //! output a formatted flog message (calls flog_print())
281 @param type use one of the FLOG_* defines
282 @param subsystem which part of the program is outputing this message (use __func__ typically)
283 @param textf formatted message text
287 int _flog_printf(FLOG_T
*p
,const char *src_file
,int src_line
,const char *src_func
,FLOG_MSG_TYPE_T type
,const char *subsystem
,const char *textf
, ...)
289 int _flog_printf(FLOG_T
*p
,FLOG_MSG_TYPE_T type
,const char *subsystem
,const char *textf
, ...)
297 if(vasprintf(&text
,textf
,ap
)==-1)
302 if(_flog_print(p
,src_file
,src_line
,src_func
,type
,subsystem
,text
)) {
304 if(_flog_print(p
,type
,subsystem
,text
)) {
313 //! create and return a string from FLOG_MSG_T type
317 char * flog_msg_t_to_str(const FLOG_MSG_T
*p
)
320 typestr
=flog_get_msg_type_str(p
->type
);
321 #ifdef FLOG_TIMESTAMP
322 //! @todo add timestamp support
325 if((p
->subsystem
!= NULL
) && (typestr
!= NULL
))
326 asprintf(&str
,"%s:%d %s() [%s] %s%s\n",p
->src_file
,p
->src_line
,p
->src_func
,p
->subsystem
,typestr
,p
->text
);
327 else if((p
->subsystem
!= NULL
) && (typestr
== NULL
))
328 asprintf(&str
,"%s:%d %s() [%s] %s\n",p
->src_file
,p
->src_line
,p
->src_func
,p
->subsystem
,p
->text
);
329 else if((p
->subsystem
== NULL
) && (typestr
!= NULL
))
330 asprintf(&str
,"%s:%d %s() %s%s\n",p
->src_file
,p
->src_line
,p
->src_func
,typestr
,p
->text
);
332 asprintf(&str
,"%s:%d %s() %s\n",p
->src_file
,p
->src_line
,p
->src_func
,p
->text
);
334 if((p
->subsystem
!= NULL
) && (typestr
!= NULL
))
335 asprintf(&str
,"[%s] %s%s\n",p
->subsystem
,typestr
,p
->text
);
336 else if((p
->subsystem
!= NULL
) && (typestr
== NULL
))
337 asprintf(&str
,"[%s] %s\n",p
->subsystem
,p
->text
);
338 else if((p
->subsystem
== NULL
) && (typestr
!= NULL
))
339 asprintf(&str
,"%s%s\n",typestr
,p
->text
);
341 asprintf(&str
,"%s\n",p
->text
);
348 //! Return a string or NULL according to message type
349 char * flog_get_msg_type_str(FLOG_MSG_TYPE_T type
)
356 e
=asprintf(&str
,"Critical: ");
359 e
=asprintf(&str
,"Error: ");
362 e
=asprintf(&str
,"Warning: ");
365 e
=asprintf(&str
,"!: ");
372 e
=asprintf(&str
,"Debug: ");
374 case FLOG_FLOG_DEBUG
:
375 e
=asprintf(&str
,"Flog debug: ");
385 void flog_test(FLOG_T
*p
)
387 flog_printf(p
,FLOG_NONE
,__func__
,"This is a test message with FLOG_NONE (0x%02x) as type - This message should NEVER be visible",FLOG_NONE
);
388 flog_printf(p
,FLOG_CRIT
,__func__
,"This is a test message with FLOG_CRIT (0x%02x) as type",FLOG_CRIT
);
389 flog_printf(p
,FLOG_ERR
,__func__
,"This is a test message with FLOG_ERR (0x%02x) as type",FLOG_ERR
);
390 flog_printf(p
,FLOG_WARN
,__func__
,"This is a test message with FLOG_WARN (0x%02x) as type",FLOG_WARN
);
391 flog_printf(p
,FLOG_NOTE
,__func__
,"This is a test message with FLOG_NOTE (0x%02x) as type",FLOG_NOTE
);
392 flog_printf(p
,FLOG_INFO
,__func__
,"This is a test message with FLOG_INFO (0x%02x) as type",FLOG_INFO
);
393 flog_printf(p
,FLOG_VINFO
,__func__
,"This is a test message with FLOG_VINFO (0x%02x) as type",FLOG_VINFO
);
394 flog_printf(p
,FLOG_DEBUG
,__func__
,"This is a test message with FLOG_DEBUG (0x%02x) as type",FLOG_DEBUG
);
395 flog_printf(p
,FLOG_FLOG_DEBUG
,__func__
,"This is a test message with FLOG_FLOG_DEBUG (0x%02x) as type - This message should only be visible when debugging the flog library itself",FLOG_FLOG_DEBUG
);
396 flog_dprintf(p
,FLOG_CRITICAL
,__func__
,"This is a test message using flog_dprintf() macro with FLOG_CRITICAL (0x%02x) as type",FLOG_CRITICAL
);
399 #ifdef FLOG_TIMESTAMP
400 //! Return a string with current timestamp in ISO-format
402 @todo this function is probably a memory leak by design :(
404 const char * get_timestamp(void)
410 timeinfo
= localtime(&rawtime
);
411 sprintf(str
,"%04d-%02d-%02d %02d:%02d:%02d",timeinfo
->tm_year
+1900,timeinfo
->tm_mon
+1,timeinfo
->tm_mday
,timeinfo
->tm_hour
,timeinfo
->tm_min
,timeinfo
->tm_sec
);