[sheepdog] [PATCH stable-0.7 1/5] sheep, dog: runtime loglevel changing

Hitoshi Mitake mitake.hitoshi at lab.ntt.co.jp
Thu Dec 12 10:46:41 CET 2013


From: Hitoshi Mitake <mitake.hitoshi at gmail.com>

This patch adds two new opcode for runtime loglevel changes and let
dog support the changing from command line. This is useful for making
sheep process verbose temporally and can make troubleshooting easier.

Example of usage:

$ dog node log level list
emerg   (0)
alert   (1)
crit    (2)
err     (3)
warning (4)
notice  (5)
info    (6)
debug   (7)
$ dog node log level get
info (6)
$ dog node log level set debug	# <- change loglevel from info to debug
$ dog node log level get
debug (7)

Signed-off-by: Hitoshi Mitake <mitake.hitoshi at lab.ntt.co.jp>
Signed-off-by: Liu Yuan <namei.unix at gmail.com>

Conflicts:
	CHANGELOG.md
	dog/common.c
	dog/node.c
	include/internal_proto.h
	sheep/ops.c

Conflicts were resolved by Hitoshi Mitake.
Signed-off-by: Hitoshi Mitake <mitake.hitoshi at lab.ntt.co.jp>
---
 dog/common.c             |   84 ++++++++++++++++++++++++++++++++++++++
 dog/dog.h                |    5 +++
 dog/node.c               |  100 +++++++++++++++++++++++++++++++++++++++++++++-
 include/internal_proto.h |    2 +
 include/logger.h         |    3 ++
 lib/logger.c             |   11 +++++
 sheep/ops.c              |   43 ++++++++++++++++++++
 7 files changed, 247 insertions(+), 1 deletion(-)

diff --git a/dog/common.c b/dog/common.c
index b185d4e..c6e85e8 100644
--- a/dog/common.c
+++ b/dog/common.c
@@ -328,3 +328,87 @@ void show_progress(uint64_t done, uint64_t total, bool raw)
 
 	free(buf);
 }
+
+static const char * const loglevel_table[] = {
+	"emerg",
+	"alert",
+	"crit",
+	"err",
+	"warning",
+	"notice",
+	"info",
+	"debug",
+};				/* index is log level */
+
+int do_loglevel_set(const struct node_id *nid, const char *loglevel_str)
+{
+	int32_t loglevel = -1;
+	int ret;
+	struct sd_req hdr;
+	struct sd_rsp *rsp = (struct sd_rsp *)&hdr;
+
+	for (int i = 0; i < ARRAY_SIZE(loglevel_table); i++) {
+		if (!strcmp(loglevel_table[i], loglevel_str)) {
+			loglevel = i;
+			break;
+		}
+	}
+
+	if (loglevel == -1)
+		return EXIT_USAGE;
+
+	sd_init_req(&hdr, SD_OP_SET_LOGLEVEL);
+	hdr.flags = SD_FLAG_CMD_WRITE;
+	hdr.data_length = sizeof(loglevel);
+
+	ret = dog_exec_req(nid->addr, nid->port, &hdr, &loglevel);
+	if (ret < 0)
+		return EXIT_SYSFAIL;
+
+	if (rsp->result != SD_RES_SUCCESS)
+		return EXIT_FAILURE;
+
+	return EXIT_SUCCESS;
+}
+
+int do_loglevel_get(const struct node_id *nid, int32_t *ret_loglevel)
+{
+	int32_t loglevel = -1;
+	int ret;
+	struct sd_req hdr;
+	struct sd_rsp *rsp = (struct sd_rsp *)&hdr;
+
+	sd_init_req(&hdr, SD_OP_GET_LOGLEVEL);
+	hdr.data_length = sizeof(loglevel);
+
+	ret = dog_exec_req(nid->addr, nid->port, &hdr, &loglevel);
+	if (ret < 0)
+		return EXIT_SYSFAIL;
+
+	if (rsp->result != SD_RES_SUCCESS)
+		return EXIT_FAILURE;
+
+	*ret_loglevel = loglevel;
+
+	return EXIT_SUCCESS;
+}
+
+const char *loglevel_to_str(int loglevel)
+{
+	for (int i = 0; i < ARRAY_SIZE(loglevel_table); i++) {
+		if (i == loglevel)
+			return loglevel_table[i];
+	}
+
+	return "unknown loglevel";
+}
+
+void dump_loglevels(bool err)
+{
+	for (int i = 0; i < ARRAY_SIZE(loglevel_table); i++) {
+		if (err)
+			sd_err("%s\t(%d)", loglevel_table[i], i);
+		else
+			sd_info("%s\t(%d)", loglevel_table[i], i);
+	}
+}
diff --git a/dog/dog.h b/dog/dog.h
index 92dd4d2..4cdc6a1 100644
--- a/dog/dog.h
+++ b/dog/dog.h
@@ -94,4 +94,9 @@ extern struct command cluster_command;
   #define trace_command {}
 #endif /* HAVE_TRACE */
 
+int do_loglevel_set(const struct node_id *nid, const char *loglevel_str);
+int do_loglevel_get(const struct node_id *nid, int32_t *ret_loglevel);
+const char *loglevel_to_str(int loglevel);
+void dump_loglevels(bool err);
+
 #endif
diff --git a/dog/node.c b/dog/node.c
index f6fe28b..d3206d7 100644
--- a/dog/node.c
+++ b/dog/node.c
@@ -384,7 +384,6 @@ static int node_md(int argc, char **argv)
 	return do_generic_subcommand(node_md_cmd, argc, argv);
 }
 
-
 static int node_parser(int ch, char *opt)
 {
 	switch (ch) {
@@ -406,6 +405,103 @@ static struct sd_option node_options[] = {
 	{ 0, NULL, false, NULL },
 };
 
+static int node_log_level_set(int argc, char **argv)
+{
+	int ret = 0;
+	char *loglevel_str = argv[optind];
+	struct node_id nid;
+
+	memset(&nid, 0, sizeof(nid));
+	memcpy(nid.addr, sdhost, sizeof(sdhost));
+	nid.port = sdport;
+
+	ret = do_loglevel_set(&nid, loglevel_str);
+	switch (ret) {
+	case EXIT_USAGE:
+		sd_err("invalid loglevel: %s", loglevel_str);
+		sd_err("available loglevels:");
+		dump_loglevels(true);
+
+		ret = -1;
+		break;
+	case EXIT_FAILURE:
+	case EXIT_SYSFAIL:
+		sd_err("Failed to execute request");
+		ret = -1;
+		break;
+	case EXIT_SUCCESS:
+		/* do nothing */
+		break;
+	default:
+		sd_err("unknown return code of do_loglevel_set(): %d", ret);
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static int node_log_level_get(int argc, char **argv)
+{
+	int ret = 0, loglevel = -1;
+	struct node_id nid;
+
+	memset(&nid, 0, sizeof(nid));
+	memcpy(nid.addr, sdhost, sizeof(sdhost));
+	nid.port = sdport;
+
+	ret = do_loglevel_get(&nid, &loglevel);
+	switch (ret) {
+	case EXIT_FAILURE:
+	case EXIT_SYSFAIL:
+		sd_err("Failed to execute request");
+		ret = -1;
+		break;
+	case EXIT_SUCCESS:
+		sd_info("%s (%d)", loglevel_to_str(loglevel), loglevel);
+		break;
+	default:
+		sd_err("unknown return code of do_loglevel_get(): %d", ret);
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+static int node_log_level_list(int argc, char **argv)
+{
+	dump_loglevels(false);
+
+	return EXIT_SUCCESS;
+}
+
+static struct subcommand node_log_level_cmd[] = {
+	{"set", "<log level>", NULL, "set new loglevel",
+	 NULL, CMD_NEED_ARG, node_log_level_set},
+	{"get", NULL, NULL, "get current loglevel",
+	 NULL, 0, node_log_level_get},
+	{"list", NULL, NULL, "list available loglevels",
+	 NULL, 0, node_log_level_list},
+	{NULL},
+};
+
+static int node_log_level(int argc, char **argv)
+{
+	return do_generic_subcommand(node_log_level_cmd, argc, argv);
+}
+
+static struct subcommand node_log_cmd[] = {
+	{"level", "<subcommand>", NULL, "manipulate loglevel",
+	 node_log_level_cmd, CMD_NEED_ARG, node_log_level},
+	{NULL},
+};
+
+static int node_log(int argc, char **argv)
+{
+	return do_generic_subcommand(node_log_cmd, argc, argv);
+}
+
 static struct subcommand node_cmd[] = {
 	{"kill", "<node id>", "aprh", "kill node", NULL,
 	 CMD_NEED_ARG | CMD_NEED_NODELIST, node_kill},
@@ -417,6 +513,8 @@ static struct subcommand node_cmd[] = {
 	 CMD_NEED_NODELIST, node_recovery, node_options},
 	{"md", "[disks]", "apAh", "See 'dog node md' for more information",
 	 node_md_cmd, CMD_NEED_ARG, node_md, node_options},
+	{"log", NULL, "aph", "show or set log level of the node", node_log_cmd,
+	 CMD_NEED_ARG, node_log},
 	{NULL,},
 };
 
diff --git a/include/internal_proto.h b/include/internal_proto.h
index 8802300..7974f68 100644
--- a/include/internal_proto.h
+++ b/include/internal_proto.h
@@ -79,6 +79,8 @@
 #define SD_OP_GET_HASH       0xB4
 #define SD_OP_REWEIGHT       0xB5
 #define SD_OP_GET_CACHE_INFO 0xB6
+#define SD_OP_GET_LOGLEVEL	0xB9
+#define SD_OP_SET_LOGLEVEL	0xBA
 
 /* internal flags for hdr.flags, must be above 0x80 */
 #define SD_FLAG_CMD_RECOVERY 0x0080
diff --git a/include/logger.h b/include/logger.h
index 5bb3a65..3f9292d 100644
--- a/include/logger.h
+++ b/include/logger.h
@@ -87,4 +87,7 @@ void sd_backtrace(void);
 	abort();				\
 })
 
+void set_loglevel(int new_loglevel);
+int get_loglevel(void);
+
 #endif	/* LOG_H */
diff --git a/lib/logger.c b/lib/logger.c
index 0e55569..987d2f5 100644
--- a/lib/logger.c
+++ b/lib/logger.c
@@ -857,3 +857,14 @@ fallback:
 	/* dump the stack frames if possible*/
 	dump_stack_frames();
 }
+
+void set_loglevel(int new_loglevel)
+{
+	assert(SDOG_EMERG <= new_loglevel && new_loglevel <= SDOG_DEBUG);
+	sd_log_level = new_loglevel;
+}
+
+int get_loglevel(void)
+{
+	return sd_log_level;
+}
diff --git a/sheep/ops.c b/sheep/ops.c
index 5baa7fd..77a5314 100644
--- a/sheep/ops.c
+++ b/sheep/ops.c
@@ -968,6 +968,35 @@ out:
 	return ret;
 }
 
+static int local_get_loglevel(struct request *req)
+{
+	int32_t current_level;
+
+	current_level = get_loglevel();
+	memcpy(req->data, &current_level, sizeof(current_level));
+	req->rp.data_length = sizeof(current_level);
+
+	sd_info("returning log level: %u", current_level);
+
+	return SD_RES_SUCCESS;
+}
+
+static int local_set_loglevel(struct request *req)
+{
+	int32_t new_level = 0;
+
+	memcpy(&new_level, req->data, sizeof(int32_t));
+	if (!(LOG_EMERG <= new_level && new_level <= LOG_DEBUG)) {
+		sd_err("invalid log level: %d", new_level);
+		return SD_RES_INVALID_PARMS;
+	}
+
+	set_loglevel(new_level);
+
+	return SD_RES_SUCCESS;
+
+}
+
 static struct sd_op_template sd_ops[] = {
 
 	/* cluster operations */
@@ -1226,6 +1255,20 @@ static struct sd_op_template sd_ops[] = {
 		.process_work = local_get_cache_info,
 	},
 
+	[SD_OP_GET_LOGLEVEL] = {
+		.name = "GET_LOGLEVEL",
+		.type = SD_OP_TYPE_LOCAL,
+		.force = true,
+		.process_work = local_get_loglevel,
+	},
+
+	[SD_OP_SET_LOGLEVEL] = {
+		.name = "SET_LOGLEVEL",
+		.type = SD_OP_TYPE_LOCAL,
+		.force = true,
+		.process_work = local_set_loglevel,
+	},
+
 	/* gateway I/O operations */
 	[SD_OP_CREATE_AND_WRITE_OBJ] = {
 		.name = "CREATE_AND_WRITE_OBJ",
-- 
1.7.10.4




More information about the sheepdog mailing list