/* * Copyright (c) 2020 YuQing <384681@qq.com> * * This program is free software: you can use, redistribute, and/or modify * it under the terms of the Lesser GNU General Public License, version 3 * or later ("LGPL"), as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. * * You should have received a copy of the Lesser GNU General Public License * along with this program. If not, see . */ //logger.h #ifndef LOGGER_H #define LOGGER_H #include #include #include "common_define.h" #ifdef __cplusplus extern "C" { #endif //log time precision #define LOG_TIME_PRECISION_SECOND 's' //second #define LOG_TIME_PRECISION_MSECOND 'm' //millisecond #define LOG_TIME_PRECISION_USECOND 'u' //microsecond #define LOG_TIME_PRECISION_NONE '0' //do NOT output timestamp //log compress flags #define LOG_COMPRESS_FLAGS_NONE 0 #define LOG_COMPRESS_FLAGS_ENABLED 1 #define LOG_COMPRESS_FLAGS_NEW_THREAD 2 #define LOG_NOTHING (LOG_DEBUG + 10) struct log_context; //log header line callback typedef void (*LogHeaderCallback)(struct log_context *pContext); #define FC_LOG_BY_LEVEL(level) \ (level <= g_log_context.log_level) typedef struct log_context { /* log level value please see: sys/syslog.h default value is LOG_INFO */ int log_level; /* default value is STDERR_FILENO */ int log_fd; /* cache buffer */ char *log_buff; /* string end in the cache buffer for next sprintf */ char *pcurrent_buff; /* mutext lock */ pthread_mutex_t lock; /* rotate the log when the log file exceeds this parameter rotate_size > 0 means need rotate log by log file size */ int64_t rotate_size; /* log file current size */ int64_t current_size; /* if write to buffer firstly, then sync to disk. default value is false (no cache) */ bool log_to_cache; /* if rotate the access log */ bool rotate_immediately; /* if stderr to the log file */ bool take_over_stderr; /* if stdout to the log file */ bool take_over_stdout; /* time precision */ char time_precision; /* if use file write lock */ bool use_file_write_lock; /* compress the log file use gzip command */ short compress_log_flags; /* save the log filename */ char log_filename[MAX_PATH_SIZE]; /* the time format for rotated filename, * default: %Y%m%d_%H%M%S * */ char rotate_time_format[32]; /* keep days for rotated log files */ int keep_days; /* log fd flags */ int fd_flags; /* * log the header (title line) callback * */ LogHeaderCallback print_header_callback; /* * compress the log files before N days * */ int compress_log_days_before; } LogContext; extern LogContext g_log_context; /** init function using global log context * return: 0 for success, != 0 fail */ int log_init(); /** init function using global log context * do nothing when already inited * return: 0 for success, != 0 fail */ static inline int log_try_init() { if (g_log_context.log_buff != NULL) { return 0; } return log_init(); } /** init function using global log context, take over stderr and stdout * return: 0 for success, != 0 fail */ int log_init2(); #define log_reopen() log_reopen_ex(&g_log_context) #define log_set_prefix(base_path, filename_prefix) \ log_set_prefix_ex(&g_log_context, base_path, filename_prefix) #define log_set_filename(log_filename) \ log_set_filename_ex(&g_log_context, log_filename) #define log_set_cache(bLogCache) log_set_cache_ex(&g_log_context, bLogCache) #define log_take_over_stderr() log_take_over_stderr_ex(&g_log_context) #define log_take_over_stdout() log_take_over_stdout_ex(&g_log_context) #define log_set_compress_log_flags(flags) \ log_set_compress_log_flags_ex(&g_log_context, flags) #define log_set_compress_log_days_before(days_before) \ log_set_compress_log_days_before_ex(&g_log_context, days_before) #define log_set_use_file_write_lock(use_lock) \ log_set_use_file_write_lock_ex(&g_log_context, use_lock) #define log_header(pContext, header, header_len) \ log_it_ex2(pContext, NULL, header, header_len, false, false) #define log_destroy() log_destroy_ex(&g_log_context) #define log_it1(priority, text, text_len) \ log_it_ex1(&g_log_context, priority, text, text_len) #define log_it2(caption, text, text_len, bNeedSync, bNeedLock) \ log_it_ex2(&g_log_context, caption, text, text_len, bNeedSync, bNeedLock) /** init function, use stderr for output by default * parameters: * pContext: the log context * return: 0 for success, != 0 fail */ int log_init_ex(LogContext *pContext); /** reopen the log file * parameters: * pContext: the log context * return: 0 for success, != 0 fail */ int log_reopen_ex(LogContext *pContext); /** set log filename prefix, such as "tracker", the log filename will be * ${base_path}/logs/tracker.log * parameters: * pContext: the log context * base_path: base path * filename_prefix: log filename prefix * return: 0 for success, != 0 fail */ int log_set_prefix_ex(LogContext *pContext, const char *base_path, const char *filename_prefix); /** set log filename * parameters: * pContext: the log context * log_filename: log filename * return: 0 for success, != 0 fail */ int log_set_filename_ex(LogContext *pContext, const char *log_filename); /** set if use log cache * parameters: * pContext: the log context * bLogCache: true for cache in buffer, false directly write to disk * return: none */ void log_set_cache_ex(LogContext *pContext, const bool bLogCache); /** set if use file write lock * parameters: * pContext: the log context * use_lock: true for use write lock, false NOT use write lock * return: none */ void log_set_use_file_write_lock_ex(LogContext *pContext, const bool use_lock); /** set time precision * parameters: * pContext: the log context * time_precision: the time precision * return: none */ void log_set_time_precision(LogContext *pContext, const int time_precision); /** set rotate time format, the time format same as function strftime * parameters: * pContext: the log context * time_format: rotate time format * return: none */ void log_set_rotate_time_format(LogContext *pContext, const char *time_format); /** set keep days * parameters: * pContext: the log context * keep_days: the keep days * return: none */ void log_set_keep_days(LogContext *pContext, const int keep_days); /** set print header callback * parameters: * pContext: the log context * header_callback: the callback * return: none */ void log_set_header_callback(LogContext *pContext, LogHeaderCallback header_callback); /** set take_over_stderr to true * parameters: * pContext: the log context * return: none */ void log_take_over_stderr_ex(LogContext *pContext); /** set take_over_stdout to true * parameters: * pContext: the log context * return: none */ void log_take_over_stdout_ex(LogContext *pContext); /** init function using global log context * do nothing when already inited * return: 0 for success, != 0 fail */ static inline int log_try_init2() { int result; if ((result=log_try_init()) != 0) { return result; } log_take_over_stderr(); log_take_over_stdout(); return 0; } /** set compress_log_flags to true * parameters: * pContext: the log context * flags: the compress log flags * return: none */ void log_set_compress_log_flags_ex(LogContext *pContext, const short flags); /** set compress log file before N days * parameters: * pContext: the log context * days_before: compress log file before N days * return: none */ void log_set_compress_log_days_before_ex(LogContext *pContext, const int days_before); /** set log fd flags * parameters: * pContext: the log context * flags: the fd flags * return: none */ void log_set_fd_flags(LogContext *pContext, const int flags); /** destroy function * parameters: * pContext: the log context * bLogCache: true for cache in buffer, false directly write to disk * return: none */ void log_destroy_ex(LogContext *pContext); /** log to file * parameters: * pContext: the log context * priority: unix priority * format: printf format * ...: arguments for printf format * return: none */ void log_it_ex(LogContext *pContext, const int priority, \ const char *format, ...) __gcc_attribute__ ((format (printf, 3, 4))); /** log to file * parameters: * pContext: the log context * priority: unix priority * text: text string to log * text_len: text string length (bytes) * return: none */ void log_it_ex1(LogContext *pContext, const int priority, const char *text, const int text_len); /** log to file * parameters: * pContext: the log context * caption: such as INFO, ERROR, NULL for no caption * text: text string to log * text_len: text string length (bytes) * bNeedSync: if sync to file immediatelly * return: none */ void log_it_ex2(LogContext *pContext, const char *caption, const char *text, const int text_len, const bool bNeedSync, const bool bNeedLock); void log_it_ex3(LogContext *pContext, struct timeval *tv, const char *caption, const char *text, const int text_len, const bool bNeedSync, const bool bNeedLock); /** sync log buffer to log file * parameters: * args: should be (LogContext *) * return: error no, 0 for success, != 0 fail */ int log_sync_func(void *args); /** set rotate flag to true * parameters: * args: should be (LogContext *) * return: error no, 0 for success, != 0 fail */ int log_notify_rotate(void *args); /** rotate log file * parameters: * pContext: the log context * return: error no, 0 for success, != 0 fail */ int log_rotate(LogContext *pContext); /** delete old log files * parameters: * args: should be (LogContext *) * return: error no, 0 for success, != 0 fail */ int log_delete_old_files(void *args); /** get log level caption * parameters: * pContext: the log context * return: log level caption */ const char *log_get_level_caption_ex(LogContext *pContext); #define log_get_level_caption() log_get_level_caption_ex(&g_log_context) void logEmergEx(LogContext *pContext, const char *format, ...) __gcc_attribute__ ((format (printf, 2, 3))); void logCritEx(LogContext *pContext, const char *format, ...) __gcc_attribute__ ((format (printf, 2, 3))); void logAlertEx(LogContext *pContext, const char *format, ...) __gcc_attribute__ ((format (printf, 2, 3))); void logErrorEx(LogContext *pContext, const char *format, ...) __gcc_attribute__ ((format (printf, 2, 3))); void logWarningEx(LogContext *pContext, const char *format, ...) __gcc_attribute__ ((format (printf, 2, 3))); void logNoticeEx(LogContext *pContext, const char *format, ...) __gcc_attribute__ ((format (printf, 2, 3))); void logInfoEx(LogContext *pContext, const char *format, ...) __gcc_attribute__ ((format (printf, 2, 3))); void logDebugEx(LogContext *pContext, const char *format, ...) __gcc_attribute__ ((format (printf, 2, 3))); void logAccess(LogContext *pContext, struct timeval *tvStart, const char *format, ...) __gcc_attribute__ ((format (printf, 3, 4))); //#define LOG_FORMAT_CHECK #ifdef LOG_FORMAT_CHECK /*only for format check*/ #define logEmerg printf #define logCrit printf #define logAlert printf #define logError printf #define logWarning printf #define logNotice printf #define logInfo printf #define logDebug printf #else /* following functions use global log context: g_log_context */ void logEmerg(const char *format, ...) __gcc_attribute__ ((format (printf, 1, 2))); void logCrit(const char *format, ...) __gcc_attribute__ ((format (printf, 1, 2))); void logAlert(const char *format, ...) __gcc_attribute__ ((format (printf, 1, 2))); void logError(const char *format, ...) __gcc_attribute__ ((format (printf, 1, 2))); void logWarning(const char *format, ...) __gcc_attribute__ ((format (printf, 1, 2))); void logNotice(const char *format, ...) __gcc_attribute__ ((format (printf, 1, 2))); void logInfo(const char *format, ...) __gcc_attribute__ ((format (printf, 1, 2))); void logDebug(const char *format, ...) __gcc_attribute__ ((format (printf, 1, 2))); #endif #ifdef __cplusplus } #endif #endif