#include "MESA_handle_logger.h" #include "zlog.h" #include #include #include #include #include #include #define MAX_HANDLE_LOG_PATH 4096 static int g_zlog_conf_fp = -1; static char global_conf_filepath[MAX_HANDLE_LOG_PATH] = ""; static char tmp_conf_filepath[MAX_HANDLE_LOG_PATH] = ""; typedef struct log_handle_t { int runtime_log_level; zlog_category_t *zc; const char *global_conf_path; char runtime_log_file[MAX_HANDLE_LOG_PATH]; } log_handle_t; //const int HANDLE_LOGGER_VERSION_20190218 = 1; #define GIT_VERSION_CATTER(v) __attribute__((__used__)) const char * GIT_VERSION_##v = NULL #define GIT_VERSION_EXPEND(v) GIT_VERSION_CATTER(v) #ifdef __cplusplus extern "C" { #endif /* VERSION TAG */ #ifdef GIT_VERSION GIT_VERSION_EXPEND(GIT_VERSION); #else static __attribute__((__used__)) const char * GIT_VERSION_UNKNOWN = NULL; #endif #undef GIT_VERSION_CATTER #undef GIT_VERSION_EXPEND #ifdef __cplusplus } #endif static int create_dir(const char *dir_path, int path_len) { if(dir_path == NULL) return -1; char *buf = (char *)calloc(path_len+1, 1); int ret = -1; memcpy(buf, dir_path, path_len); if(access(buf, R_OK) != 0) { if(mkdir(buf, 0755)!= 0) ret = -1; else ret = 0; } else ret = 1; free(buf); buf = NULL; return ret; } static int create_path(const char *path, int path_len) { const char *p_cur = path; int i = 0; if(create_dir(path, path_len) >= 0) return 0; for(;i<=path_len;i++,p_cur++) { if(*p_cur == '/') { if(create_dir(path, i+1) < 0) return -1; } } return 0; } static int get_filepath(int fp, char *buf, int buflen) { if(buf == NULL || buflen <=0)return -1; char proclnk[0xFFF] = ""; //int fno = fileno(fp); int fno = fp; sprintf(proclnk, "/proc/self/fd/%d", fno); int r = readlink(proclnk, buf, buflen); return r; } static char tmp_template[] = "/tmp/handle_loggger.XXXXXX"; static void escape_for_zlog(char *in_buf, int buflen) { if(in_buf == NULL || buflen <= 0)return; int i = 0; for(i = 0; i < buflen; i++) { if ((!isalnum(in_buf[i])) && (in_buf[i] != '_') && (in_buf[i] != '-') && (in_buf[i] != '*') && (in_buf[i] != '!')) { in_buf[i] = '_'; } } return; } static void snapshot_handle_info(const char *handle_name, const char *log_path, int level) { char zlog_rule_conf_content[MAX_HANDLE_LOG_PATH + 1]; if (g_zlog_conf_fp == -1) { char temp_filename[1024] = ""; sprintf(temp_filename, "/tmp/MESA_handle_logger_%d.XXXXXX", getpid()); g_zlog_conf_fp = mkstemp(temp_filename); if (g_zlog_conf_fp == -1) { return ; } if (get_filepath(g_zlog_conf_fp, tmp_conf_filepath, sizeof(tmp_conf_filepath)) < 0) { return; } int len = snprintf(zlog_rule_conf_content, sizeof(zlog_rule_conf_content), "[global]\ndefault format = \"%%d(%%c), %%V, %F, %U, %%m%%n\" \n[levels]\nDEBUG=10\nINFO=20\nFATAL=30\n[rules]"); write(g_zlog_conf_fp, zlog_rule_conf_content, strlen(zlog_rule_conf_content)); fsync(g_zlog_conf_fp); } snprintf(zlog_rule_conf_content, sizeof(zlog_rule_conf_content), "\n%s.%d \"%s.%%d(%%F)\"", handle_name, level, log_path); write(g_zlog_conf_fp, zlog_rule_conf_content, strlen(zlog_rule_conf_content)); fsync(g_zlog_conf_fp); return; } void *MESA_create_runtime_log_handle(const char *file_path, int level) { if(file_path == NULL) return NULL; int rc = -1; zlog_category_t *zc = NULL; FILE *fp = NULL; log_handle_t *p_handle = NULL; char handle_name[MAX_HANDLE_LOG_PATH]; char *p_path_end = rindex(file_path, '/'); char *p_name = p_path_end+1; strcpy(handle_name, file_path); escape_for_zlog(handle_name, strlen(handle_name)); p_name = handle_name; //creating file_path failed, return NULL if (create_path(file_path, p_path_end - file_path) < 0) return NULL; snapshot_handle_info(p_name, file_path, level); zc = zlog_get_category(p_name); if (!zc) { printf("get zlog category %s in %s fail\n", p_name, tmp_conf_filepath); } p_handle = (log_handle_t *)calloc(sizeof(log_handle_t), 1); strncpy(p_handle->runtime_log_file, file_path, sizeof(p_handle->runtime_log_file) - 1); p_handle->runtime_log_level = level; p_handle->zc = zc; return (void *)p_handle; } void MESA_destroy_runtime_log_handle(void *handle) { if(handle != NULL) { free(handle); handle = NULL; } return; } void MESA_handle_runtime_log(void *handle, int level, const char *module, const char *fmt, ...) { log_handle_t *p_handle = (log_handle_t *)handle; if(p_handle == NULL || p_handle->runtime_log_file == NULL)return; if(p_handle->zc == NULL)return; va_list ap; va_start(ap, fmt); vzlog(p_handle->zc, p_handle->runtime_log_file, strlen(p_handle->runtime_log_file), module, strlen(module), __LINE__, level, fmt, ap); va_end(ap); return ; } int MESA_handle_runtime_log_creation(const char *conf_path) { if(conf_path == NULL) { printf("MESA_handle_runtime_log_creationUsing NULL, will using ZLOG_CONF_PATH or strout as default profile\n"); return zlog_init(NULL); } if (access(conf_path, R_OK) != -1) { int rc = zlog_init(conf_path); if (rc) { printf("init zlog by %s failed\n", conf_path); return -1; } else { strcpy(global_conf_filepath, conf_path); zlog_profile(); } return rc; } return -1; } int MESA_handle_runtime_log_reconstruction(const char *conf_path) { int rc = zlog_reload(conf_path); #ifdef DEBUG char zlog_rule_conf_content[MAX_HANDLE_LOG_PATH + 1]; time_t t; struct tm local_time; static unsigned char weekday_str[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; static unsigned char month_str[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; if (!rc) { strcpy(global_conf_filepath, conf_path); zlog_profile(); if (g_zlog_conf_fp != -1) { time(&t); if (NULL != (localtime_r(&t, &local_time))) { snprintf(zlog_rule_conf_content, sizeof(zlog_rule_conf_content), "\n%s %s %d %02d:%02d:%02d %d, RECONSTRUCTION to %s\n", weekday_str[local_time.tm_wday], month_str[local_time.tm_mon], local_time.tm_mday, local_time.tm_hour, local_time.tm_min, local_time.tm_sec, local_time.tm_year + 1900, conf_path); write(g_zlog_conf_fp, zlog_rule_conf_content, strlen(zlog_rule_conf_content)); fsync(g_zlog_conf_fp); } } } #endif return rc; } void MESA_handle_runtime_log_destruction() { zlog_fini(); if (g_zlog_conf_fp != -1) { unlink(tmp_conf_filepath); close(g_zlog_conf_fp); } }