From bc2a82351a160e6f7c3353fed5a00ffb9493c95d Mon Sep 17 00:00:00 2001 From: jusung son Date: Tue, 5 Jun 2018 13:21:33 +0900 Subject: [PATCH] Add file log Change-Id: Ieb3b8b76c1f88793081fd2111692863e1a744312 Signed-off-by: jusung son --- client/c_direct.c | 91 ++++++++++++++++++++++- common/config.c | 67 ++++++++++++++++- common/config.h | 2 +- common/direct.c | 4 +- common/direct.h | 2 +- daemon/daemon.c | 197 ++++++++++++++++++++++++++++++++++++++++++++++++- daemon/daemon.h | 1 + packaging/buxton2.conf | 4 + 8 files changed, 358 insertions(+), 10 deletions(-) diff --git a/client/c_direct.c b/client/c_direct.c index 451d051..d9eda3d 100644 --- a/client/c_direct.c +++ b/client/c_direct.c @@ -22,6 +22,9 @@ #include #include #include +#include +#include +#include #include "common.h" #include "direct.h" @@ -29,9 +32,14 @@ #include "c_log.h" #include "c_common.h" #include "c_direct.h" -#include #define BUFFER_SIZE 1024 +#define BXT_LOG_FOLDER "/run/buxton2/log" +#define BXT_NULL_STRING "(VCONF_NULL)" + +static FILE *_fp; +static int _log_max_line = 2000; +static bool _log_on = true; static const char *confpath; static const char const *type_names[BUXTON_TYPE_MAX] = { @@ -65,7 +73,7 @@ static int c_init(void) int r; char err_buf[BUFFER_SIZE]; - r = direct_init(MODULE_DIR, confpath ? confpath : CONFPATH); + r = direct_init(MODULE_DIR, confpath ? confpath : CONFPATH, &_log_on, &_log_max_line); if (r == -1) { strerror_r(errno, err_buf, sizeof(err_buf)); bxt_err("Init: %s", err_buf); @@ -115,6 +123,83 @@ int c_direct_get(const struct buxton_layer *layer, return 0; } +static bool _init_log() +{ + char buffer[256] = {0, }; + int ret; + + ret = mkdir(BXT_LOG_FOLDER, 0755); + if (ret < 0 && errno != EEXIST) { + bxt_err("Failed to mkdir %s - %d", BXT_LOG_FOLDER, errno); + return false; + } + + snprintf(buffer, sizeof(buffer), + "%s/direct_log_%d.log", BXT_LOG_FOLDER, getpid()); + _fp = fopen(buffer, "wt"); + if (_fp == NULL) { + bxt_err("Failed to open %s - %d", buffer, errno); + return false; + } + + return true; +} + +static void _write_file_log(const char *key, const char *value) +{ + char buf[512] = {0,}; + char time_buf[32] = {0,}; + int ret = 0; + int fd; + time_t now; + static int _log_index = 0; + char app_id[512] = {0,}; + const char *refined_value; + + if (_log_on == false) + return; + + if (_fp == NULL) { + if (_init_log() == false) + return; + } + + snprintf(buf, sizeof(buf), "/proc/%d/cmdline", getppid()); + + fd = open(buf, O_RDONLY); + if (fd > 0) { + ret = read(fd, app_id, sizeof(app_id) - 1); + close(fd); + } + + time(&now); + ctime_r(&now, time_buf); + + /* remove newline */ + if (strlen(time_buf) > 1) + time_buf[strlen(time_buf) -1] = '\0'; + + if (value == NULL || strlen(value) == 0) + refined_value = BXT_NULL_STRING; + else + refined_value = value; + + _log_index++; + snprintf(buf, sizeof(buf), "\n[%5d]%s DirectSet - ppid(%d:%s) - %s ", + _log_index, time_buf, getppid(), app_id, key); + ret = fwrite(buf, strlen(buf), 1 , _fp); + if (ret < 0) { + bxt_err("Cannot write the key log: %d, %s %s", errno, buf, refined_value); + return; + } + + ret = fwrite(refined_value, strlen(refined_value), 1 , _fp); + if (ret < 0) { + bxt_err("Cannot write the value log: %d, %s %s", errno, buf, refined_value); + return; + } +} + static int c_direct_set(const struct buxton_layer *layer, const char *key, const char *value, enum buxton_key_type type) { @@ -151,6 +236,8 @@ static int c_direct_set(const struct buxton_layer *layer, err_buf); } + _write_file_log(key, value); + return r; } diff --git a/common/config.c b/common/config.c index db144d7..84bb6e8 100644 --- a/common/config.c +++ b/common/config.c @@ -38,6 +38,10 @@ #define K_B_DB "persistent" #define K_B_MEM "volatile" +#define G_LOG_CONF "log-config" +#define K_LOG_ON "OnOff" +#define K_LOG_MAX "MaxLine" + static GHashTable *layers; static void free_layer(struct layer *layer) @@ -230,6 +234,65 @@ static void add_layers(GKeyFile *kf, GList *backends) g_free(lays); } +static void load_log_conf(GKeyFile *kf, bool *log_on, int *max_line) +{ + GError *err = NULL; + gchar *buf = NULL; + assert(kf); + + bool onoff; + int max = 0; + + /* 'OnOff' */ + buf = g_key_file_get_string(kf, G_LOG_CONF, K_LOG_ON, &err); + if (!buf) { + bxt_err("get_string failed :Group '%s', Key '%s' : %s", + G_LOG_CONF, K_LOG_ON, err ? err->message : ""); + goto out; + } + if (strcasecmp(buf, "ON") == 0) { + onoff = true; + } else if (strcasecmp(buf, "OFF") == 0) { + onoff = false; + } else { + bxt_err("get_string failed : Group '%s', Key '%s' : '%s'(len:%d)", + G_LOG_CONF, K_LOG_ON, buf, strlen(buf)); + goto out; + } + + if (onoff) { + g_free(buf); + buf = NULL; + + /* max line */ + buf = g_key_file_get_string(kf, G_LOG_CONF, K_LOG_MAX, &err); + if (!buf) { + bxt_err("get_string failed : Group '%s', Key '%s' : '%s'", + G_LOG_CONF, K_LOG_MAX, err ? err->message : ""); + goto out; + } + + max = atoi(buf); + if (max <= 0) { + bxt_err("atoi failed : Group '%s', Key '%s' : '%s'", + G_LOG_CONF, K_LOG_MAX, buf); + goto out; + } + } + + *log_on = onoff; + *max_line = max; + bxt_err("log config log on : %s , max line %d", onoff ? "True" : "False", max); + +out: + if (err) + g_clear_error(&err); + if (buf) + g_free(buf); + + g_key_file_remove_group(kf, G_LOG_CONF, NULL); +} + const struct layer *conf_get_layer(const char *name) { const struct layer *layer; @@ -273,7 +336,7 @@ void conf_exit(void) layers = NULL; } -int conf_init(const char *confpath, GList *backends) +int conf_init(const char *confpath, GList *backends, bool *log_on, int *max_line) { GKeyFile *kf; @@ -297,6 +360,8 @@ int conf_init(const char *confpath, GList *backends) return -1; } + load_log_conf(kf, log_on, max_line); + add_layers(kf, backends); g_key_file_free(kf); diff --git a/common/config.h b/common/config.h index 52bce85..fc7ee68 100644 --- a/common/config.h +++ b/common/config.h @@ -22,7 +22,7 @@ #include "common.h" -int conf_init(const char *confpath, GList *backends); +int conf_init(const char *confpath, GList *backends, bool *log_on, int *max_line); void conf_exit(void); const struct layer *conf_get_layer(const char *name); diff --git a/common/direct.c b/common/direct.c index 1c5e002..87d3764 100644 --- a/common/direct.c +++ b/common/direct.c @@ -738,7 +738,7 @@ void direct_exit(void) backend_exit(); } -int direct_init(const char *moddir, const char *confpath) +int direct_init(const char *moddir, const char *confpath, bool *log_on, int *max_line) { int r; GList *backends; @@ -756,7 +756,7 @@ int direct_init(const char *moddir, const char *confpath) if (!backends) return -1; - r = conf_init(confpath, backends); + r = conf_init(confpath, backends, log_on, max_line); g_list_free(backends); diff --git a/common/direct.h b/common/direct.h index 380877c..62bf869 100644 --- a/common/direct.h +++ b/common/direct.h @@ -20,7 +20,7 @@ #include "buxton2.h" -int direct_init(const char *moddir, const char *confpath); +int direct_init(const char *moddir, const char *confpath, bool *log_on, int *max_line); void direct_exit(void); int direct_get(const struct buxton_layer *layer, diff --git a/daemon/daemon.c b/daemon/daemon.c index e7ff808..cd6ebb2 100644 --- a/daemon/daemon.c +++ b/daemon/daemon.c @@ -23,7 +23,9 @@ #include #include #include +#include #include +#include #include #include @@ -41,11 +43,42 @@ #include "dbus.h" #include "cache.h" +#define BXT_LOG_FOLDER "/run/buxton2/log" +#define BXT_NULL_STRING "(VCONF_NULL)" + +static int _log_max_line = 2000; +static bool _log_on = true; + +static FILE *_fp; + +static enum log_type { + LOG_SET, + LOG_NOTI, + LOG_DELAYED_NOTI, + LOG_SEND_DELAYED_NOTI, + LOG_REG_NOTI, + LOG_UNREG_NOTI, + LOG_MAX +}; + +static char *log_map[] = { + "SET", + "NOTIFY", + "DELAYED_NOTI", + "SEND_DELAYED_NOTI", + "REG_NOTI", + "UNREG_NOTI" +}; + + struct bxt_noti { char *layer_key; GList *clients; /* struct bxt_client */ }; +static bool _init_log(); +static void _write_file_log(enum log_type type, struct bxt_client *cli, struct request *rqst); + static gboolean signal_cb(gint fd, GIOCondition cond, gpointer data) { struct bxt_daemon *bxtd = data; @@ -230,6 +263,8 @@ static gboolean _send_notis(gpointer key, gpointer value, gpointer data) } } + _write_file_log(LOG_SEND_DELAYED_NOTI, cli, NULL); + free(_data); return TRUE; } @@ -308,8 +343,10 @@ static void send_notis(struct bxt_daemon *bxtd, struct request *rqst) g_hash_table_replace(cli->delay_notilist, strdup(rqst->key), _data); + _write_file_log(LOG_DELAYED_NOTI, cli, rqst); } } else { + _write_file_log(LOG_NOTI, cli, rqst); if (cli->delay_notilist) g_hash_table_remove(cli->delay_notilist, rqst->key); } @@ -331,6 +368,8 @@ static void proc_set(struct bxt_client *cli, resp->res = errno; return; } + _write_file_log(LOG_SET, cli, rqst); + resp->res = 0; } @@ -464,8 +503,10 @@ static void proc_notify(struct bxt_client *cli, } else { free(lykey); } - add_cli(noti, cli); + + _write_file_log(LOG_REG_NOTI, cli, rqst); + resp->res = 0; } @@ -503,6 +544,8 @@ static void proc_unnotify(struct bxt_client *cli, if (!noti->clients) /* no client */ g_hash_table_remove(cli->bxtd->notis, lykey); + _write_file_log(LOG_UNREG_NOTI, cli, rqst); + resp->res = 0; free(lykey); @@ -831,7 +874,9 @@ static int proc_client_msg(struct bxt_client *cli) static gboolean client_cb(gint fd, GIOCondition cond, gpointer data) { - int r; + int r, proc_fd; + char proc_name[512] = {0,}; + char buf[512] = {0,}; struct bxt_client *cli = data; assert(cli); @@ -853,6 +898,17 @@ static gboolean client_cb(gint fd, GIOCondition cond, gpointer data) if (cli->cred.pid == 0) { sock_get_client_cred(fd, &cli->cred); sock_get_client_label(fd, &cli->label); + + snprintf(buf, sizeof(buf), "/proc/%d/cmdline", cli->cred.pid); + + proc_fd = open(buf, O_RDONLY); + if (proc_fd > 0) { + r = read(proc_fd, proc_name, sizeof(proc_name) - 1); + close(proc_fd); + + if (strlen(proc_name) > 0) + cli->process_name = strdup(proc_name); + } } r = proc_client_msg(cli); @@ -957,11 +1013,146 @@ static void free_client(struct bxt_client *cli) if (cli->fd != -1) close(cli->fd); + if (cli->process_name) + free(cli->process_name); + free(cli->label); free(cli); bxt_dbg("free client %p", cli); } +static bool _init_log() +{ + char buffer[256] = {0, }; + int ret; + + ret = mkdir(BXT_LOG_FOLDER, 0755); + if (ret < 0 && errno != EEXIST) { + bxt_err("Failed to mkdir %s - %d", BXT_LOG_FOLDER, errno); + return false; + } + + snprintf(buffer, sizeof(buffer), + "%s/log_%d.log", BXT_LOG_FOLDER, getpid()); + _fp = fopen(buffer, "wt"); + + if (_fp == NULL) { + bxt_err("Failed to open %s - %d", buffer, errno); + return false; + } + + return true; +} + +static void _write_file_log(enum log_type type, struct bxt_client *cli, struct request *rqst) +{ + char buf[512] = {0,}; + char time_buf[32] = {0,}; + char tmp_value[32] = {0,}; + char *label; + char *value = NULL; + int ret = 0; + time_t now; + + static enum log_type prev_type = LOG_MAX; + static int _log_index = 0; + + if (_log_on == false) + return; + + if (_fp == NULL) { + if (_init_log() == false) + return; + } + + if (_log_index >= _log_max_line) { + fseek(_fp, 0, SEEK_SET); + _log_index = 0; + } + + if (cli->process_name != NULL) + label = cli->process_name; + else + label = cli->label; + + time(&now); + ctime_r(&now, time_buf); + + /* remove newline */ + if (strlen(time_buf) > 1) + time_buf[strlen(time_buf) -1] = '\0'; + + if (type == LOG_NOTI) { + if (prev_type != type) { + _log_index++; + snprintf(buf, sizeof(buf), "\n[%5d]%s %-18s %s - pid(%d:%s)", + _log_index, time_buf, log_map[type], rqst->key, cli->cred.pid, label); + + } else { + snprintf(buf, sizeof(buf), ", pid(%d:%s)", cli->cred.pid, label); + } + } else { + _log_index++; + snprintf(buf, sizeof(buf), "\n[%5d]%s %-18s - pid(%d:%s) - %s ", + _log_index, time_buf, log_map[type], cli->cred.pid, label, rqst ? rqst->key : "NULL"); + + if (type == LOG_SET && rqst) { + value = tmp_value; + + switch (rqst->val->type) { + case BUXTON_TYPE_STRING: + value = rqst->val->value.s; + break; + case BUXTON_TYPE_INT32: + snprintf(tmp_value, sizeof(tmp_value), "%d", rqst->val->value.i); + break; + case BUXTON_TYPE_UINT32: + snprintf(tmp_value, sizeof(tmp_value), "%u", rqst->val->value.u); + break; + case BUXTON_TYPE_INT64: + snprintf(tmp_value, sizeof(tmp_value), "%"PRId64, rqst->val->value.i64); + break; + case BUXTON_TYPE_UINT64: + snprintf(tmp_value, sizeof(tmp_value), "%"PRIu64, rqst->val->value.u64); + break; + case BUXTON_TYPE_DOUBLE: + snprintf(tmp_value, sizeof(tmp_value), "%lf", rqst->val->value.d); + break; + case BUXTON_TYPE_BOOLEAN: + if (rqst->val->value.b) + snprintf(tmp_value, sizeof(tmp_value), "True"); + else + snprintf(tmp_value, sizeof(tmp_value), "False"); + break; + default: + snprintf(tmp_value, sizeof(tmp_value), "Unknown type"); + break; + } + } + } + + if (value == NULL || strlen(value) == 0) + value = BXT_NULL_STRING; + + ret = fwrite(buf, strlen(buf), 1 , _fp); + if (ret <= 0) { + bxt_err("Cannot write the key log: %d, type(%d) pid(%d:%s) %s %s", + errno, type, cli->cred.pid, label, rqst ? rqst->key : BXT_NULL_STRING, value); + return; + } + + if (type == LOG_SET) { + ret = fwrite(value, strlen(value), 1, _fp); + if (ret <= 0) { + bxt_err("Cannot write the value log: %d, type(%d) pid(%d:%s) %s %s", + errno, type, cli->cred.pid, label, rqst ? rqst->key : BXT_NULL_STRING, value); + return; + } + } + + prev_type = type; +} + static void bxt_exit(struct bxt_daemon *bxtd) { buxton_cynara_exit(); @@ -1004,7 +1195,7 @@ static int bxt_init(struct bxt_daemon *bxtd, const char *confpath) bxtd->sigfd = create_sigfd(); g_unix_fd_add(bxtd->sigfd, G_IO_IN, signal_cb, bxtd); - r = direct_init(MODULE_DIR, confpath); + r = direct_init(MODULE_DIR, confpath, &_log_on, &_log_max_line); if (r == -1) return -1; diff --git a/daemon/daemon.h b/daemon/daemon.h index 439c065..9f0762c 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -42,6 +42,7 @@ struct bxt_client { struct ucred cred; char *label; + char *process_name; GList *notilist; /* struct bxt_noti */ GHashTable *delay_notilist; diff --git a/packaging/buxton2.conf b/packaging/buxton2.conf index 79e93c3..ef9e956 100644 --- a/packaging/buxton2.conf +++ b/packaging/buxton2.conf @@ -2,6 +2,10 @@ # buxton2 config file for Tizen # +[log-config] +OnOff=on +MaxLine=2000 + [system] Type=System Backend=sqlite -- 2.7.4