int log_sync_func(void *args) { if (args == NULL) { return EINVAL; } return log_fsync((LogContext *)args, true); }
int log_force_sync() { if (!logger_init_flag) { fprintf(stderr, "log module may be not init!\n"); return 1; } return log_fsync(true); }
void log_destroy_ex(LogContext *pContext) { if (pContext->log_fd >= 0 && pContext->log_fd != STDERR_FILENO) { log_fsync(pContext, true); close(pContext->log_fd); pContext->log_fd = STDERR_FILENO; pthread_mutex_destroy(&pContext->log_thread_lock); } if (pContext->log_buff != NULL) { free(pContext->log_buff); pContext->log_buff = NULL; pContext->pcurrent_buff = NULL; } }
static void doLogEx(LogContext *pContext, struct timeval *tv, \ const char *caption, const char *text, const int text_len, \ const bool bNeedSync, const bool bNeedLock) { struct tm tm; int time_fragment; int buff_len; int result; if ((pContext->time_precision == LOG_TIME_PRECISION_SECOND) || (pContext->time_precision == LOG_TIME_PRECISION_NONE)) { time_fragment = 0; } else { if (pContext->time_precision == LOG_TIME_PRECISION_MSECOND) { time_fragment = tv->tv_usec / 1000; } else { time_fragment = tv->tv_usec; } } if (bNeedLock && (result=pthread_mutex_lock(&pContext->log_thread_lock)) != 0) { fprintf(stderr, "file: "__FILE__", line: %d, " \ "call pthread_mutex_lock fail, " \ "errno: %d, error info: %s", \ __LINE__, result, STRERROR(result)); } if (text_len + 64 > LOG_BUFF_SIZE) { fprintf(stderr, "file: "__FILE__", line: %d, " \ "log buff size: %d < log text length: %d ", \ __LINE__, LOG_BUFF_SIZE, text_len + 64); if (bNeedLock) { pthread_mutex_unlock(&(pContext->log_thread_lock)); } return; } if ((pContext->pcurrent_buff - pContext->log_buff) + text_len + 64 \ > LOG_BUFF_SIZE) { log_fsync(pContext, false); } if (pContext->time_precision != LOG_TIME_PRECISION_NONE) { localtime_r(&tv->tv_sec, &tm); if (pContext->time_precision == LOG_TIME_PRECISION_SECOND) { buff_len = sprintf(pContext->pcurrent_buff, \ "[%04d-%02d-%02d %02d:%02d:%02d] ", \ tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, \ tm.tm_hour, tm.tm_min, tm.tm_sec); } else { buff_len = sprintf(pContext->pcurrent_buff, \ "[%04d-%02d-%02d %02d:%02d:%02d.%03d] ", \ tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, \ tm.tm_hour, tm.tm_min, tm.tm_sec, time_fragment); } pContext->pcurrent_buff += buff_len; } if (caption != NULL) { buff_len = sprintf(pContext->pcurrent_buff, "%s - ", caption); pContext->pcurrent_buff += buff_len; } memcpy(pContext->pcurrent_buff, text, text_len); pContext->pcurrent_buff += text_len; *pContext->pcurrent_buff++ = '\n'; if (!pContext->log_to_cache || bNeedSync) { log_fsync(pContext, false); } if (bNeedLock && (result=pthread_mutex_unlock(&(pContext->log_thread_lock))) != 0) { fprintf(stderr, "file: "__FILE__", line: %d, " \ "call pthread_mutex_unlock fail, " \ "errno: %d, error info: %s", \ __LINE__, result, STRERROR(result)); } }
int logEx(int priority, const char *caption, const bool bNeedSync, const char *file_name, const char *func_name, int line_number, const char *format, ...) { char text[LOG_LINE_MAX]; int text_len, log_fd; const char *p; struct timeval tv; long milliseconds; struct tm* tm; int buff_len; int result; if (!logger_init_flag) { fprintf(stderr, "log module may be not init!\n"); return 1; } if (log_level < priority) { return 0; } va_list ap; va_start(ap, format); text_len = vsnprintf(text, sizeof(text), format, ap); va_end(ap); /* 日志太长, 无法打印到缓冲区 */ if ((text_len + 128) > LOG_BUFF_SIZE) { fprintf(stderr, "file: " __FILE__ ", line: %d, log buff size: %d < log text length: %d ", __LINE__, LOG_BUFF_SIZE, text_len + 128); return 1; } /* 加锁 */ if ((result = pthread_mutex_lock(&pContext->log_thread_lock)) != 0) { fprintf(stderr, "file: " __FILE__ ", line: %d, call pthread_mutex_lock fail, errno: %d, error info: %s", __LINE__, result, STRERROR(result)); } /* 获取系统时间, 精确到毫秒 */ gettimeofday(&tv, NULL); tm = localtime(&tv.tv_sec); milliseconds = tv.tv_usec / 1000; /* 缓冲区中剩余空间无法容纳本行日志, 先将缓冲区中日志写入磁盘文件 */ if (((pContext->pcurrent_buff - pContext->log_buff) + text_len + 128) > LOG_BUFF_SIZE) { log_fsync(false); } /* 如果文件名存在路径前缀, 则去掉路径前缀 */ if ((p = strrchr(file_name, '/')) != NULL) { p++; } else { p = file_name; } buff_len = sprintf(pContext->pcurrent_buff, "[%04d-%02d-%02d %02d:%02d:%02d:%03ld] [tid=%d] [%s::%s:%d] %s - ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, milliseconds, (int)syscall(__NR_gettid), p, func_name, line_number, caption); pContext->pcurrent_buff += buff_len; memcpy(pContext->pcurrent_buff, text, text_len); pContext->pcurrent_buff += text_len; *pContext->pcurrent_buff++ = '\n'; if (!pContext->log_to_cache || bNeedSync) { log_fsync(false); } /* 进行日志切分 */ int cur_time = 0; switch (pContext->logrotate_cycle) { case ROTATE_CYCLE_NONE: cur_time = -1; break; case ROTATE_CYCLE_MINUTE: cur_time = tm->tm_min; break; case ROTATE_CYCLE_HOUR: cur_time = tm->tm_hour; break; case ROTATE_CYCLE_DAY: cur_time = tm->tm_yday; break; } if (cur_time != last_log_time && pContext->log_fd >= 0 && pContext->log_fd != STDERR_FILENO && pContext->logrotate_cycle != ROTATE_CYCLE_NONE) { /* 首先将缓冲中日志刷新到现在的日志文件中 */ log_fsync(false); char cur_filename[LOG_MAX_PATH_SIZE]; char log_filename[LOG_MAX_PATH_SIZE]; char filename_time_suffix[16]; switch (pContext->logrotate_cycle) { case ROTATE_CYCLE_NONE: /* just remove compile warnings */ break; case ROTATE_CYCLE_MINUTE: snprintf(filename_time_suffix, sizeof(filename_time_suffix), "%04d%02d%02d-%02d%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, last_log_time); break; case ROTATE_CYCLE_HOUR: snprintf(filename_time_suffix, sizeof(filename_time_suffix), "%04d%02d%02d-%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, last_log_time); break; case ROTATE_CYCLE_DAY: snprintf(filename_time_suffix, sizeof(filename_time_suffix), "%04d%02d%02d", tm->tm_year + 1900, tm->tm_mon + 1, last_log_time); break; } snprintf(cur_filename, LOG_MAX_PATH_SIZE, "%s/"LOG_PATH"/%s.log", pContext->log_base_path, pContext->log_filename_prefix); snprintf(log_filename, LOG_MAX_PATH_SIZE, "%s/"LOG_PATH"/%s.%s.log", pContext->log_base_path, pContext->log_filename_prefix, filename_time_suffix); /* 将前一个时间段的日志切分出去 */ if (rename(cur_filename, log_filename) < 0) { fprintf(stderr, "rename log file \"%s\" fail, errno: %d, error info: %s", cur_filename, errno, STRERROR(errno)); } else { if ((log_fd = open(cur_filename, O_WRONLY | O_CREAT | O_APPEND, 0644)) < 0) { fprintf(stderr, "open log file \"%s\" to write fail, errno: %d, error info: %s", log_filename, errno, STRERROR(errno)); } else { close(pContext->log_fd); pContext->log_fd = log_fd; } } } /* 更新最后一次日志时间 */ last_log_time = cur_time; /* 解锁 */ if ((result = pthread_mutex_unlock(&(pContext->log_thread_lock))) != 0) { fprintf(stderr, "file: " __FILE__ ", line: %d, call pthread_mutex_unlock fail, errno: %d, error info: %s", __LINE__, result, STRERROR(result)); } return 0; }