[sheepdog] [PATCH v3 1/2] sheep, dog: runtime loglevel changing

Hitoshi Mitake mitake.hitoshi at lab.ntt.co.jp
Thu Oct 24 05:08:46 CEST 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>
---
v3:
 - make the previous subcommand loglevel -> log

v2:
 - add a new subcommand "dog node loglevel list" for listing available
   loglevels

 CHANGELOG.md             |    8 +++--
 dog/common.c             |   84 +++++++++++++++++++++++++++++++++++++++++++
 dog/dog.h                |    5 +++
 dog/node.c               |   90 +++++++++++++++++++++++++++++++++++++++++++++-
 include/internal_proto.h |    2 ++
 include/logger.h         |    3 ++
 lib/logger.c             |   12 +++++++
 sheep/ops.c              |   43 ++++++++++++++++++++++
 8 files changed, 244 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 98d221e..dd91a33 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,9 +3,13 @@
 
 DOG COMMAND INTERFACE:
  - new subcommand "vdi cache purge" for cleaning stale object cache
- -- "vdi cache purge" cleans stale cache of all images
- -- "vdi cache purge <image>" cleans stale cache of the specified image
+  - "vdi cache purge" cleans stale cache of all images
+  - "vdi cache purge <image>" cleans stale cache of the specified image
  - new subcommand "node stat" for showing I/O status of the node
+ - new subcommand "node loglevel" for changing log level at runtime
+  - "node log level set" sets loglevel of running sheep process
+  - "node log level get" gets loglevel from running sheep process
+  - "node log level list" lists avialable loglevels
 
 SHEEP COMMAND INTERFACE:
  - improvements of help messages
diff --git a/dog/common.c b/dog/common.c
index 5e7ce2e..44e116d 100644
--- a/dog/common.c
+++ b/dog/common.c
@@ -351,3 +351,87 @@ bool is_erasure_oid(uint64_t oid, uint8_t policy)
 		return false;
 	return true;
 }
+
+static const char *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, &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, &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 769fc6c..28c36a1 100644
--- a/dog/dog.h
+++ b/dog/dog.h
@@ -95,4 +95,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 052739c..f896078 100644
--- a/dog/node.c
+++ b/dog/node.c
@@ -420,7 +420,6 @@ static int node_md(int argc, char **argv)
 	return do_generic_subcommand(node_md_cmd, argc, argv);
 }
 
-
 static int node_parser(int ch, const char *opt)
 {
 	switch (ch) {
@@ -444,6 +443,93 @@ 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];
+
+	ret = do_loglevel_set(&sd_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;
+
+	ret = do_loglevel_get(&sd_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},
@@ -457,6 +543,8 @@ static struct subcommand node_cmd[] = {
 	 node_md_cmd, CMD_NEED_ARG, node_md, node_options},
 	{"stat", NULL, "aprwh", "show stat information about the node", NULL,
 	 0, node_stat, 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 8a23737..c6eecaf 100644
--- a/include/internal_proto.h
+++ b/include/internal_proto.h
@@ -95,6 +95,8 @@
 #define SD_OP_GET_CACHE_INFO 0xB6
 #define SD_OP_CACHE_PURGE    0xB7
 #define SD_OP_STAT	0xB8
+#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 6c6a315..bf1a605 100644
--- a/lib/logger.c
+++ b/lib/logger.c
@@ -767,3 +767,15 @@ 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 7f73ab1..914aea7 100644
--- a/sheep/ops.c
+++ b/sheep/ops.c
@@ -947,6 +947,35 @@ static int peer_create_and_write_obj(struct request *req)
 	return sd_store->create_and_write(hdr->obj.oid, &iocb);
 }
 
+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 */
@@ -1217,6 +1246,20 @@ static struct sd_op_template sd_ops[] = {
 		.process_main = local_sd_stat,
 	},
 
+	[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