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

Hitoshi Mitake mitake.hitoshi at lab.ntt.co.jp
Fri Oct 18 13:54:33 CEST 2013


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 loglevel get
info (6)
$ dog node loglevel set debug	# <- change loglevel from info to debug
$ dog node loglevel get
debug (7)

Signed-off-by: Hitoshi Mitake <mitake.hitoshi at lab.ntt.co.jp>
---
 CHANGELOG.md             |    7 ++--
 dog/common.c             |   80 ++++++++++++++++++++++++++++++++++++++++++++++
 dog/dog.h                |    5 +++
 dog/node.c               |   70 +++++++++++++++++++++++++++++++++++++++-
 include/internal_proto.h |    2 ++
 include/logger.h         |    3 ++
 lib/logger.c             |   12 +++++++
 sheep/ops.c              |   43 +++++++++++++++++++++++++
 8 files changed, 219 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 98d221e..83ec887 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,9 +3,12 @@
 
 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 loglevel set" sets loglevel of running sheep process
+  - "node loglevel get" gets loglevel from running sheep process
 
 SHEEP COMMAND INTERFACE:
  - improvements of help messages
diff --git a/dog/common.c b/dog/common.c
index a2fb945..275ad7e 100644
--- a/dog/common.c
+++ b/dog/common.c
@@ -338,3 +338,83 @@ size_t get_store_objsize(uint8_t copy_policy, uint64_t oid)
 		return SD_EC_OBJECT_SIZE;
 	return get_objsize(oid);
 }
+
+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_err(void)
+{
+	for (int i = 0; i < ARRAY_SIZE(loglevel_table); i++)
+		sd_err("%s\t(%d)", loglevel_table[i], i);
+}
diff --git a/dog/dog.h b/dog/dog.h
index cfc9d54..681e1da 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_err(void);
+
 #endif
diff --git a/dog/node.c b/dog/node.c
index 052739c..0713609 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,73 @@ static struct sd_option node_options[] = {
 	{ 0, NULL, false, NULL },
 };
 
+static int node_loglevel_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_err();
+
+		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_loglevel_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 struct subcommand node_loglevel_cmd[] = {
+	{"set", NULL, NULL, "set new loglevel",
+	 NULL, 0, node_loglevel_set},
+	{"get", NULL, NULL, "get current loglevel",
+	 NULL, 0, node_loglevel_get},
+	{NULL},
+};
+
+static int node_loglevel(int argc, char **argv)
+{
+	return do_generic_subcommand(node_loglevel_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 +523,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},
+	{"loglevel", NULL, "aph", "show or set log level of the node", NULL,
+	 0, node_loglevel},
 	{NULL,},
 };
 
diff --git a/include/internal_proto.h b/include/internal_proto.h
index 59c6e2a..cc25ce1 100644
--- a/include/internal_proto.h
+++ b/include/internal_proto.h
@@ -90,6 +90,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 e39a21b..09bc66e 100644
--- a/sheep/ops.c
+++ b/sheep/ops.c
@@ -945,6 +945,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 */
@@ -1215,6 +1244,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