#include "MESA_handle_logger.h" #include "zlog.h" #include #include #include #include #include #include #define MAX_HANDLE_LOG_PATH 4096 static int g_zlog_inited = 0; 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 const char *loglevel_to_name(int level) { if (level <= RLOG_LV_DEBUG) return "DEBUG"; if (level > RLOG_LV_DEBUG && level <= RLOG_LV_INFO) return "INFO"; return "FATAL"; } 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] = ""; static char *zlog_conf_init_buff = "[global]\ndefault format = \"%d(%c), %V, %F, %U, %m%n\" \n[levels]\nDEBUG=10\nINFO=20\nFATAL=30\n[rules]"; 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; } write(g_zlog_conf_fp, zlog_conf_init_buff, strlen(zlog_conf_init_buff)); fsync(g_zlog_conf_fp); } snprintf(zlog_rule_conf_content, sizeof(zlog_rule_conf_content), "\n%s.%s \"%s.%%d(%%F)\"", handle_name, loglevel_to_name(level), log_path); write(g_zlog_conf_fp, zlog_rule_conf_content, strlen(zlog_rule_conf_content)); fsync(g_zlog_conf_fp); if(g_zlog_inited == 0) { printf("[snapshot_handle_info], Nobody call MESA_handle_runtime_log_creation before, Using (%s) to init zlog, handle_name(%s), log_path(%s), log_level(%d)!!!\n", tmp_conf_filepath, handle_name, log_path, level); zlog_init(tmp_conf_filepath); zlog_reload(NULL); } 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); zlog_reload(NULL); zc = zlog_get_category(p_name); if (!zc) { printf("[MESA_create_runtime_log_handle], get zlog category (%s) in global_conf_filepath(%s) fail\n", p_name, global_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) { char *env = getenv("ZLOG_CONF_PATH"); int rc = 0; if (conf_path == NULL || (access(conf_path, R_OK) != 0)) { printf("[MESA_handle_runtime_log_creation], PATH (%s) unable to access, will output log to STDOUT or Using ZLOG_CONF_PATH (%s) !\n", conf_path, env); rc = zlog_init(NULL); if (rc) { printf("[MESA_handle_runtime_log_creation], INIT zlog by (NULL) or (%s) failed !!! \n", env); return -1; } else { if (env != NULL) { strcpy(global_conf_filepath, env); } } } else { rc = zlog_init(conf_path); if (rc) { printf("[MESA_handle_runtime_log_creation], INIT zlog by (%s) failed , using [NULL] retry !\n", conf_path); rc = zlog_init(NULL); if (rc) { printf("[MESA_handle_runtime_log_creation], INIT zlog by (NULL) or (%s) failed \n", env); return -1; } else { if(env != NULL) { strcpy(global_conf_filepath, env); } } } else { strcpy(global_conf_filepath, conf_path); } } printf("[MESA_handle_runtime_log_creation], INIT zlog finish, Using (%s). \n", global_conf_filepath); g_zlog_inited = 1; zlog_profile(); return rc; } 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); } }