#include #include #include #include #include #include "log_remote.h" #include "log_common.h" #define LOG_CONF_REMOTE_FILE_NAME "log-remote.conf" #define RESET_SEEK(fp) fseek(fp, 0, SEEK_SET) #define LOG_CONF_KEY_REMOTE_LEVEL "remote.level=" typedef enum { LOG_REMOTE_OP_ADD = 0, LOG_REMOTE_OP_DEL, LOG_REMOTE_MAX } log_op_t; typedef struct _rfc_key_fmt { log_rfc_t rfc; char fmt[20]; } rfc_key_fmt; static rfc_key_fmt rfc_tbl[] = { {LOG_RFC_3164, "RFC3164fmt"}, {LOG_RFC_5424, "RFC5424fmt"} }; typedef int (*op_func)(const log_remote_host_t *conf); static int add_remote_host(const log_remote_host_t *conf); static int del_remote_host(const log_remote_host_t *conf); static op_func remote_funcs[] = { add_remote_host, del_remote_host }; static int match_remote_config(const char *line, const void *src) { char text_level[MAX_LINE_SZ], old_redirect[MAX_LINE_SZ]; int n; ULOG_DEBUG(g_log, "The line:%s will be matched", line); n = sscanf(line, "%s"REDIRECT_SEPERATE"%s", text_level, old_redirect); if (errno != 0) { // 错误发生 ULOG_ERR(g_log, "Parsing remote line is failure:%s", strerror(errno)); return -1; } if (n == 2) { // 匹配到 // 是否相同配置判读 ULOG_DEBUG(g_log, "%s will compare with %s", old_redirect, (const char *)src); if (strcmp(old_redirect, src) == 0) { return 0; } } else { // 未能识别行 ULOG_DEBUG(g_log, "The line:%s can't be parsed", line); } return -1; } static int remote_conf_content(FILE *fp, const u8 level, const char *filter_mod, int (*match_cb)(const char *line, const void *src), int (*final_cb)(FILE *fp, const u8 level, const char *filter_mod, void *arg), void *arg) { int ret = -1; FILE *bak_fp = NULL; char path[MAX_PATH_SZ]; snprintf(path, sizeof(path), BAK_FILE, LOG_CONF_REMOTE_FILE_NAME); bak_fp = fopen(path, "r"); if (bak_fp == NULL) { if (errno == ENOENT) { goto FINAL_PHASE; } else { ULOG_ERR(g_log, "Opening remote backup file:%s is failure:%s", path, strerror(errno)); return -1; } } char *line = NULL; ssize_t n, n1; char text_level[MAX_LINE_SZ], old_redirect[MAX_LINE_SZ]; while ((n = getline(&line, &n, bak_fp)) != -1) { int match = match_cb(line, arg); if (match == -1) { ULOG_ERR(g_log, "Configure which is matched is failure"); } else if (match == 0) { ULOG_DEBUG(g_log, "Be matched"); continue; } ULOG_DEBUG(g_log, "Recover old line:%s to file:%s", line, path); n1 = fwrite(line, 1, n, fp); if (n != n1) { ULOG_ERR(g_log, "Recovering old line:%s to file is failure:%s", line, strerror(errno)); goto END; } } FINAL_PHASE: if (final_cb != NULL) { if (final_cb(fp, level, filter_mod, arg) != 0) { ULOG_ERR(g_log, "Executing final callback is failure"); goto END; } } ret = 0; END: if (line != NULL) { free(line); } if (bak_fp != NULL) { fclose(bak_fp); } return ret; } static int remote_conf_level_content(FILE *fp, const u8 level) { int ret = -1; FILE *bak_fp = NULL; char path[MAX_PATH_SZ]; snprintf(path, sizeof(path), BAK_FILE, LOG_CONF_REMOTE_FILE_NAME); bak_fp = fopen(path, "r"); if (bak_fp == NULL) { ULOG_ERR(g_log, "Opening remote backup file:%s is failure:%s", path, strerror(errno)); return -1; } char *line = NULL; ssize_t n, n1; ssize_t n3; char text_level[MAX_LINE_SZ], old_redirect[MAX_LINE_SZ]; char rewrite_line[MAX_LINE_SZ]; while ((n1 = getline(&line, &n, bak_fp)) != -1) { n3 = sscanf(line, "%s"REDIRECT_SEPERATE"%s", text_level, old_redirect); if (errno != 0) { // 错误发生 ULOG_ERR(g_log, "Parsing remote line is failure:%s", strerror(errno)); goto END; } if (n3 == 2) { // 匹配到 // 改变该行日志级别 memset(rewrite_line, 0, sizeof(rewrite_line)); if (log_level_to_str(level, rewrite_line, sizeof(rewrite_line)) != 0) { ULOG_ERR(g_log, "Log level converts str is failure"); goto END; } strcat(rewrite_line, REDIRECT_SEPERATE); strcat(rewrite_line, old_redirect); strcat(rewrite_line, "\n"); n3 = strlen(rewrite_line); } else { // 未能识别行 ULOG_DEBUG(g_log, "The line:%s can't be parsed", line); } ULOG_DEBUG(g_log, "Recover old line:%s to file:%s", rewrite_line, path); n1 = fwrite(rewrite_line, 1, n3, fp); if (n3 != n1) { ULOG_ERR(g_log, "Recovering old line:%s to file is failure:%s", rewrite_line, strerror(errno)); goto END; } } ret = 0; END: if (line != NULL) { free(line); } if (bak_fp != NULL) { fclose(bak_fp); } return ret; } static int add_remote_conf_content(FILE *fp, const u8 level, const char *filter_mod, void *arg) { return remote_conf_content(fp, level, filter_mod, match_remote_config, write_conf_content, arg); } static int del_remote_conf_content(FILE *fp, const u8 level, const char *filter_mod, void *arg) { return remote_conf_content(fp, level, filter_mod, match_remote_config, NULL, arg); } static int modify_remote_conf_log_level(FILE *fp, const u8 level, const char *filter_mod, void *arg) { return remote_conf_level_content(fp, level); } static int get_log_level() { if (RESET_SEEK(g_conf_fp) == -1) { ULOG_ERR(g_log, "[get log level]Seeknig config to begin is faiure:%s", strerror(errno)); return -1; } ssize_t n, n1, n2; char *line; u8 value; while ((n1 = getline(&line, &n, g_conf_fp)) != -1) { n2 = sscanf(line, LOG_CONF_KEY_REMOTE_LEVEL"%u", &value); if (errno != 0) { // 错误发生 ULOG_ERR(g_log, "Parsing level from configure is failure:%s", strerror(errno)); return -1; } if (n2 == 1) { return value; } else { ULOG_DEBUG(g_log, "Unknown level row:%s", line); } } return LOG_INFO; } static int add_remote_host(const log_remote_host_t *conf) { ULOG_INFO(g_log, "Adding remote log server[%s:%u], rfc is %s", conf->host, conf->port, rfc_tbl[conf->rfc].fmt); char prefix[1] = ""; if (conf->rfc == LOG_RFC_5424) { strcat(prefix, "@"); }; char redirect[MAX_LINE_SZ]; if (snprintf(redirect, sizeof(redirect), "%s@%s:%u:%s", prefix, conf->host, conf->port, rfc_tbl[conf->rfc].fmt) < 0) { ULOG_ERR(g_log, "Setting remote redirect[%s:%u:%s] is faulure", conf->host, conf->port, rfc_tbl[conf->rfc].fmt); return -1; } int level = get_log_level(); if (level == -1) { ULOG_ERR(g_log, "Getting log level is failure"); return -1; } if (log_conf(level, LOG_CONF_PATH, LOG_CONF_REMOTE_FILE_NAME, NULL, add_remote_conf_content, (void *)redirect) != 0) { ULOG_ERR(g_log, "Adding remote server[%s:%u:%s] is faulure", conf->host, conf->port, rfc_tbl[conf->rfc].fmt); return -1; } return 0; } static int del_remote_host(const log_remote_host_t *conf) { int ret; char prefix[1] = ""; ULOG_INFO(g_log, "Deleting remote log server[%s:%u], rfc is %s", conf->host, conf->port, rfc_tbl[conf->rfc].fmt); if (conf->rfc == LOG_RFC_5424) { strcat(prefix, "@"); }; char redirect[MAX_LINE_SZ]; if (snprintf(redirect, sizeof(redirect), "%s@%s:%u:%s", prefix, conf->host, conf->port, rfc_tbl[conf->rfc].fmt) < 0) { ULOG_ERR(g_log, "Setting remote redirect[%s:%u:%s] is faulure", conf->host, conf->port, rfc_tbl[conf->rfc].fmt); return -1; } if (log_conf(7, LOG_CONF_PATH, LOG_CONF_REMOTE_FILE_NAME, NULL, del_remote_conf_content, (void *)redirect) != 0) { ULOG_ERR(g_log, "Adding remote server[%s:%u:%s] is faulure", conf->host, conf->port, rfc_tbl[conf->rfc].fmt); return -1; } return ret; } static int config_log_remote_host(const log_op_t op, const log_remote_host_t *conf) { if ((sizeof(rfc_tbl) / sizeof(rfc_key_fmt)) < conf->rfc) { ULOG_WARNING(g_log, "Unknown rfc format key:%u", conf->rfc); return -1; } if (op >= LOG_REMOTE_MAX) { ULOG_WARNING(g_log, "Unknown operation type:%u", op); return -1; } return remote_funcs[op](conf); } static int config_log_remote_level(const log_remote_level_t *level) { if (truncate(g_conf_file, 0) == -1) { ULOG_ERR(g_log, "Truncate configure:%s is faiure:%s", g_conf_file, strerror(errno)); return -1; } /* 定位到开始位置 */ if (RESET_SEEK(g_conf_fp) == -1) { ULOG_ERR(g_log, "Seeknig config to begin is faiure:%s", strerror(errno)); return -1; } char fmt[MAX_LINE_SZ]; snprintf(fmt, sizeof(fmt), LOG_CONF_KEY_REMOTE_LEVEL"%u", level->level); ULOG_DEBUG(g_log, "Configure content is %s", fmt); int len = strlen(fmt); int n = fwrite(fmt, 1, len, g_conf_fp); if (len != n) { ULOG_ERR(g_log, "Writing remote level is failure:%s", strerror(errno)); return -1; } fflush(g_conf_fp); if (log_conf(level->level, LOG_CONF_PATH, LOG_CONF_REMOTE_FILE_NAME, NULL, modify_remote_conf_log_level, NULL) != 0) { ULOG_ERR(g_log, "Modifing log level:%u of remote server [%s:%u:%s] is faulure", level->level); return -1; } return 0; } static void rpc_conf_log_remote(const log_op_t op, rpc_conn *conn, pointer input, int input_len, pointer data) { if (input == NULL) { ULOG_WARNING(g_log, "Remote log configure can't null"); return; } u32 need_len = sizeof(log_remote_host_t); if (input_len < need_len) { ULOG_WARNING(g_log, "The input paramter of rpc log remote host is needed length of %u, but the actual length is %u", need_len, input_len); return; } config_log_remote_host(op, (const log_remote_host_t *)input); } void rpc_conf_log_add_remote(rpc_conn *conn, pointer input, int input_len, pointer data) { rpc_conf_log_remote(LOG_REMOTE_OP_ADD, conn, input, input_len, data); } void rpc_conf_log_del_remote(rpc_conn *conn, pointer input, int input_len, pointer data) { rpc_conf_log_remote(LOG_REMOTE_OP_DEL, conn, input, input_len, data); } void rpc_conf_log_remote_level(rpc_conn *conn, pointer input, int input_len, pointer data) { if (input == NULL) { ULOG_WARNING(g_log, "Remote log level can't null"); return; } u32 need_len = sizeof(log_remote_level_t); if (input_len < need_len) { ULOG_WARNING(g_log, "The input paramter of rpc log remote level is needed length of %u, but the actual length is %u", need_len, input_len); return; } config_log_remote_level((const log_remote_level_t *)input); }