38 #include <sys/types.h> 51 #define LOG_MAX_FILESIZE (256* 1024) 53 #ifndef _INSTALL_DIR //HACK 54 #define _INSTALL_DIR "./" 56 #ifndef _PROCNAME //HACK 57 #define _PROCNAME "stdout" 59 #define LOG_FILEPATH _INSTALL_DIR"/var/log/"_PROCNAME 60 #define LOG_FILE LOG_FILEPATH"/"_PROCNAME".log" 61 #define LOG_FILE_OLD LOG_FILEPATH"/"_PROCNAME".old.log" 64 #ifdef LOG_FORCE_USING_STDOUT 66 #define CNRM "\x1B[0m" 67 #define CRED "\033[1;31m" // Bold-red 68 #define CGRN "\x1B[32m" 69 #define CYEL "\x1B[33m" 70 #define CMAG "\x1B[35m" 71 #define CBLU "\x1B[34m" 73 #define LOG_VERBOSE_HIGHLIGHT CNRM 74 #define LOG_DEBUG_HIGHLIGHT CNRM 75 #define LOG_WARNING_HIGHLIGHT CYEL 76 #define LOG_ERROR_HIGHLIGHT CRED 77 #define LOG_RAW_HIGHLIGHT CNRM 78 #define LOG_EVENT_HIGHLIGHT CGRN 82 #define CLOSE_FILE(FD) 83 #define UPDATE_USE_STDOUT_FLAG() \ 86 #define LOG_VERBOSE_HIGHLIGHT "VERBOSE: " 87 #define LOG_DEBUG_HIGHLIGHT "DEBUG: " 88 #define LOG_WARNING_HIGHLIGHT "WARNING: " 89 #define LOG_ERROR_HIGHLIGHT "ERROR: " 90 #define LOG_RAW_HIGHLIGHT "" 91 #define LOG_EVENT_HIGHLIGHT "EVENT: " 94 open(LOG_FILE, O_RDWR| O_APPEND| O_TRUNC| O_CREAT, S_IRUSR| S_IWUSR) 95 #define CLOSE_FILE(FD) \ 97 #define UPDATE_USE_STDOUT_FLAG() \ 134 static void log_trace_fd(log_level_t type,
const char *filename,
int line,
135 const char *format, va_list arg);
136 static void log_trace_buf(log_level_t type,
log_ctx_t *log_ctx,
137 const char *filename,
int line,
const char *format, va_list arg);
138 static void log_module_fflush();
143 static int logfile_fd= -1;
144 static pthread_mutex_t logfile_mutex= PTHREAD_MUTEX_INITIALIZER;
145 static int flag_use_stdout= 0;
147 int log_module_open()
149 int ret_code, end_code= STAT_ERROR;
153 logfile_fd= OPEN_FILE();
155 printf(
"Could not open LOG file '%s'\n", LOG_FILE);
160 ret_code= pthread_mutex_init(&logfile_mutex, NULL);
164 UPDATE_USE_STDOUT_FLAG();
166 end_code= STAT_SUCCESS;
168 if(end_code!= STAT_SUCCESS)
173 void log_module_close()
179 CLOSE_FILE(logfile_fd);
183 ret_code= pthread_mutex_destroy(&logfile_mutex);
192 int ret_code, end_code= STAT_ERROR;
202 ret_code= pthread_mutex_init(&log_ctx->
mutex, NULL);
209 end_code= STAT_SUCCESS;
211 if(end_code!= STAT_SUCCESS)
220 if(ref_log_ctx== NULL)
223 if((log_ctx= *ref_log_ctx)!= NULL) {
228 ret_code= pthread_mutex_destroy(&log_ctx->
mutex);
235 log_line_ctx_release(&log_line_ctx);
243 void log_trace(log_level_t type,
log_ctx_t *log_ctx,
const char *filename,
244 int line,
const char *format, ...)
246 va_list arg, arg_cpy;
249 if(type>= LOG_TYPE_MAX)
return;
250 if(format== NULL)
return;
254 printf(
"'LOG' module should be initialized previously\n");
258 va_start(arg, format);
259 va_copy(arg_cpy, arg);
261 if(flag_use_stdout== 0 && log_ctx!= NULL) {
263 log_trace_buf(type, log_ctx, filename, line, format, arg_cpy);
265 log_trace_fd(type, filename, line, format, arg_cpy);
274 llist_t *curr_node, *prev_node;
281 pthread_mutex_lock(&log_ctx->
mutex);
286 while(curr_node!= NULL) {
291 log_line_ctx2= log_line_ctx_dup((
const log_line_ctx_t*)curr_node->data);
292 if(log_line_ctx2== NULL)
299 new_node->data= (
void*)log_line_ctx2;
300 new_node->next= NULL;
304 prev_node->next= new_node;
306 log_line_ctx_llist= new_node;
310 curr_node= curr_node->next;
313 pthread_mutex_unlock(&log_ctx->
mutex);
323 pthread_mutex_lock(&log_ctx->
mutex);
329 log_line_ctx_release(&log_line_ctx);
335 pthread_mutex_unlock(&log_ctx->
mutex);
348 if(log_line_ctx_arg== NULL)
352 log_line_ctx= log_line_ctx_allocate();
353 if(log_line_ctx== NULL)
357 strncpy(log_line_ctx->code, log_line_ctx_arg->code, LOG_LINE_SIZE);
358 strncpy(log_line_ctx->desc, log_line_ctx_arg->desc, LOG_LINE_SIZE);
359 strncpy(log_line_ctx->date, log_line_ctx_arg->date, LOG_DATE_SIZE);
360 log_line_ctx->ts= log_line_ctx_arg->ts;
361 log_line_ctx->count= log_line_ctx_arg->count;
370 if(ref_log_line_ctx== NULL)
373 if((log_line_ctx= *ref_log_line_ctx)!= NULL) {
375 *ref_log_line_ctx= NULL;
379 void log_trace_byte_table(
const char *label,
const char *file,
int line,
380 uint8_t *data,
size_t len,
size_t xsize)
386 if(file== NULL || data== NULL)
return;
388 log_trace(LOG_ERROR, NULL, __FILENAME__, __LINE__,
389 "Parameter 'xsize' MUST be a multiple of 4.\n");
393 log_trace(LOG_RAW, NULL, __FILENAME__, __LINE__,
394 "%s %d: \n> ======== %s ========\n", file, line,
395 label!= NULL? label:
"");
396 for(i= 0; i< len; i+= xsize) {
397 log_trace(LOG_RAW, NULL, __FILENAME__, __LINE__,
"> ");
398 for(j= 0; j< xsize; j++) {
401 log_trace(LOG_RAW, NULL, __FILENAME__, __LINE__,
"%02x", p[i+j]);
403 log_trace(LOG_RAW, NULL, __FILENAME__, __LINE__,
" ");
405 log_trace(LOG_RAW, NULL, __FILENAME__, __LINE__,
"\n");
407 log_trace(LOG_RAW, NULL, __FILENAME__, __LINE__,
">\n\n");
411 static void log_trace_fd(log_level_t type,
const char *filename,
int line,
412 const char *format, va_list arg)
414 char str[LOG_LINE_SIZE], *highlight_prefix;
418 pthread_mutex_lock(&logfile_mutex);
423 highlight_prefix= LOG_VERBOSE_HIGHLIGHT;
426 highlight_prefix= LOG_DEBUG_HIGHLIGHT;
429 highlight_prefix= LOG_WARNING_HIGHLIGHT;
432 highlight_prefix= LOG_ERROR_HIGHLIGHT;
435 highlight_prefix= LOG_RAW_HIGHLIGHT;
438 highlight_prefix= LOG_EVENT_HIGHLIGHT;
441 highlight_prefix=
"";
444 str_size+= snprintf(&str[str_size],
sizeof(str)- str_size,
"%s",
448 if(filename!= NULL && type!= LOG_RAW) {
449 if(str_size>=
sizeof(str))
goto end;
450 str_size+= snprintf(&str[str_size],
sizeof(str)- str_size,
"%s %d ",
455 if(str_size>=
sizeof(str))
goto end;
456 str_size+= vsnprintf(&str[str_size],
sizeof(str)- str_size, format, arg);
459 if(str_size>=
sizeof(str)) str_size=
sizeof(str);
460 written= write(logfile_fd, str, str_size);
462 if(written!= str_size) written= -1;
468 pthread_mutex_unlock(&logfile_mutex);
473 static void log_trace_buf(log_level_t type,
log_ctx_t *log_ctx,
474 const char *filename,
int line,
const char *format, va_list arg)
476 char code[LOG_LINE_SIZE], *extp;
480 uint64_t oldest_ts= 0;
481 struct timespec monotime_curr= {0};
482 time_t t= time(NULL);
483 struct tm *tm= localtime(&t);
490 if(clock_gettime(CLOCK_MONOTONIC, &monotime_curr)!= 0)
494 snprintf(code, LOG_LINE_SIZE,
"%d%s", line, filename);
495 extp= strstr(code,
".c");
499 pthread_mutex_lock(&log_ctx->
mutex);
507 while(*ref_curr_node!= NULL) {
510 llist_t *curr_node= *ref_curr_node;
514 if(log_line_ctx_ith== NULL)
518 if(strncmp(code, log_line_ctx_ith->code, strlen(code))== 0) {
520 vsnprintf(log_line_ctx_ith->desc, LOG_LINE_SIZE, format, arg);
521 log_line_ctx_ith->count++;
522 log_line_ctx_ith->ts= (uint64_t)monotime_curr.tv_sec;
524 snprintf(log_line_ctx_ith->date, LOG_DATE_SIZE,
525 "%d:%d:%d %d-%d-%d", tm->tm_hour, tm->tm_min,
526 tm->tm_sec, tm->tm_year + 1900, tm->tm_mon + 1,
529 memset(log_line_ctx_ith->date, 0, LOG_DATE_SIZE);
535 if((ts_ith= log_line_ctx_ith->ts)< oldest_ts) {
541 if((*ref_curr_node)->next== NULL)
545 ref_curr_node= &(*ref_curr_node)->next;
552 new_log_line_ctx= log_line_ctx_allocate();
553 if(new_log_line_ctx== NULL)
555 strncpy(new_log_line_ctx->code, code, LOG_LINE_SIZE);
556 vsnprintf(new_log_line_ctx->desc, LOG_LINE_SIZE, format, arg);
557 new_log_line_ctx->count= 1;
558 new_log_line_ctx->ts= (uint64_t)monotime_curr.tv_sec;
560 snprintf(new_log_line_ctx->date, LOG_DATE_SIZE,
"%d:%d:%d %d-%d-%d",
561 tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_year + 1900,
562 tm->tm_mon + 1, tm->tm_mday);
564 memset(new_log_line_ctx->date, 0, LOG_DATE_SIZE);
571 new_node->data= (
void*)new_log_line_ctx;
572 new_log_line_ctx= NULL;
573 new_node->next= NULL;
584 llist_t *log_line_ctx_llist_oldest=
587 log_line_ctx_llist_oldest->data;
588 if(log_line_ctx_oldest!= NULL)
589 log_line_ctx_release(&log_line_ctx_oldest);
593 log_line_ctx_llist_oldest->next;
594 free(log_line_ctx_llist_oldest);
599 #if 0 //RAL: comment-me 602 printf(
"LOG-traces list length (id= %d): %d; " 603 "last log-trace code: %s\n",
605 log_line_ctx_llist!= NULL?
611 pthread_mutex_unlock(&log_ctx->
mutex);
612 if(new_log_line_ctx!= NULL)
613 log_line_ctx_release(&new_log_line_ctx);
620 #ifdef LOG_FORCE_USING_STDOUT 622 static void log_module_fflush()
630 static void log_module_fflush()
635 logfile_off= lseek(logfile_fd, 0, SEEK_CUR);
636 if(logfile_off> LOG_MAX_FILESIZE) {
637 CLOSE_FILE(logfile_fd);
638 unlink(LOG_FILE_OLD);
639 rename(LOG_FILE, LOG_FILE_OLD);
640 logfile_fd= OPEN_FILE();
642 printf(
"Error: Unable to create log-file '%s'.\n", LOG_FILE);
int log_line_ctx_llist_len
General status codes enumeration.
#define CHECK_DO(COND, ACTION)
llist_t * log_line_ctx_llist
Simple linked-list utility implementation.
llist_t ** log_line_ctx_llist_tail_ref
void * llist_pop(llist_t **ref_llist_head)
llist_t ** log_line_ctx_llist_oldest_ref