[sheepdog] [PATCH v2 1/4] logger: add a mechanism for initializing log file with user specified callbacks

Hitoshi Mitake mitake.hitoshi at lab.ntt.co.jp
Tue Feb 5 03:49:29 CET 2013


It is convenient for parsing log files if the log files have an entry
which describes about a logging process as their first line.

This patch adds a mechanism for doing such a logging. Users of logger
can pass a callback as a paramter of init_log(). Before starting
actual logs, logger calls the callback if a selected formatter has a
function for this initialization.

After applying this patch, a first log line produced by sheep will be
like this:
{ "type": 0, "header": { "program": "sheep", "pid": 2500, "port":
7000} }

(If the log format the sheep is JSON, this line appears. The default
log formatter doesn't produce lines like this.)

Signed-off-by: Hitoshi Mitake <mitake.hitoshi at lab.ntt.co.jp>
---
 include/logger.h |    2 +-
 lib/logger.c     |   48 ++++++++++++++++++++++++++++++++++++------------
 sheep/sheep.c    |   33 ++++++++++++++++++++++++++-------
 3 files changed, 63 insertions(+), 20 deletions(-)

diff --git a/include/logger.h b/include/logger.h
index 309b484..8dd867f 100644
--- a/include/logger.h
+++ b/include/logger.h
@@ -23,7 +23,7 @@
 
 void select_log_formatter(const char *format_name);
 int log_init(const char *progname, int size, bool to_stdout, int level,
-	char *outfile);
+	char *outfile, char *(*init_cb)(const char *));
 void log_close(void);
 void dump_logmsg(void *);
 void log_write(int prio, const char *func, int line, const char *fmt, ...)
diff --git a/lib/logger.c b/lib/logger.c
index f3f03e3..8866e40 100644
--- a/lib/logger.c
+++ b/lib/logger.c
@@ -70,15 +70,18 @@ struct logmsg {
 
 struct log_format {
 	const char *name;
+	char *(*init)(char *(*user_cb)(const char *));
 	int (*formatter)(char *, size_t, const struct logmsg *);
 	struct list_head list;
 };
 
-#define log_format_register(n, formatter_fn)				\
+#define log_format_register(n, init_fn, formatter_fn)			\
 	static void __attribute__((constructor))			\
 	regist_ ## formatter_fn(void) {					\
 		static struct log_format f =				\
-			{ .name = n, .formatter = formatter_fn };	\
+			{ .name = n,					\
+			  .init = init_fn,				\
+			  .formatter = formatter_fn, };			\
 		list_add(&f.list, &log_formats);			\
 }
 
@@ -200,7 +203,17 @@ static notrace int default_log_formatter(char *buff, size_t size,
 
 	return p - buff;
 }
-log_format_register("default", default_log_formatter);
+log_format_register("default", NULL, default_log_formatter);
+
+static char *init_json_log_formatter(char *(*user_cb)(const char *))
+{
+	static char init_msg[MAX_MSG_SIZE];
+
+	snprintf(init_msg, MAX_MSG_SIZE, "{ \"type\": 0, \"header\": %s }\n",
+		user_cb("json"));
+
+	return init_msg;
+}
 
 static notrace int json_log_formatter(char *buff, size_t size,
 				const struct logmsg *msg)
@@ -208,7 +221,7 @@ static notrace int json_log_formatter(char *buff, size_t size,
 	int i, body_len;
 	char *p = buff;
 
-	snprintf(p, size, "{");
+	snprintf(p, size, "{ \"type\": 1, \"body\": {");
 	p += strlen(p);
 
 	snprintf(p, size - strlen(buff), "\"second\": %lu", msg->tv.tv_sec);
@@ -235,7 +248,7 @@ static notrace int json_log_formatter(char *buff, size_t size,
 	snprintf(p, size - strlen(buff), ", \"line\": %d", msg->line);
 	p += strlen(p);
 
-	snprintf(p, size - strlen(buff), ", \"body\": \"");
+	snprintf(p, size - strlen(buff), ", \"msg\": \"");
 	p += strlen(p);
 
 	body_len = strlen(msg->str) - 1;
@@ -246,26 +259,31 @@ static notrace int json_log_formatter(char *buff, size_t size,
 		*p++ = msg->str[i];
 	}
 
-	snprintf(p, size - strlen(buff), "\"}\n");
+	snprintf(p, size - strlen(buff), "\"} }\n");
 	p += strlen(p);
 
 	return p - buff;
 }
-log_format_register("json", json_log_formatter);
+log_format_register("json", init_json_log_formatter, json_log_formatter);
 
 /*
  * this one can block under memory pressure
  */
+static notrace void do_log_syslog(int prio, char *str)
+{
+	if (log_fd >= 0)
+		xwrite(log_fd, str, strlen(str));
+	else
+		syslog(prio, "%s", str);
+}
+
 static notrace void log_syslog(const struct logmsg *msg)
 {
 	char str[MAX_MSG_SIZE];
 
 	memset(str, 0, MAX_MSG_SIZE);
 	format->formatter(str, MAX_MSG_SIZE, msg);
-	if (log_fd >= 0)
-		xwrite(log_fd, str, strlen(str));
-	else
-		syslog(msg->prio, "%s", str);
+	do_log_syslog(msg->prio, str);
 }
 
 static notrace void init_logmsg(struct logmsg *msg, struct timeval *tv,
@@ -427,6 +445,8 @@ static notrace void crash_handler(int signo)
 	exit(1);
 }
 
+static char *(*user_init_cb)(const char *);
+
 static notrace void logger(char *log_dir, char *outfile)
 {
 	struct sigaction sa_old;
@@ -472,6 +492,9 @@ static notrace void logger(char *log_dir, char *outfile)
 	if (kill(sheep_pid, 0) < 0)
 		kill(logger_pid, SIGHUP);
 
+	if (format->init)
+		do_log_syslog(SDOG_INFO, format->init(user_init_cb));
+
 	while (la->active) {
 		log_flush();
 
@@ -520,10 +543,11 @@ void select_log_formatter(const char *format_name)
 }
 
 notrace int log_init(const char *program_name, int size, bool to_stdout,
-		int level, char *outfile)
+		int level, char *outfile, char *(*init_cb)(const char *))
 {
 	char log_dir[PATH_MAX], tmp[PATH_MAX];
 
+	user_init_cb = init_cb;
 	log_level = level;
 
 	log_name = program_name;
diff --git a/sheep/sheep.c b/sheep/sheep.c
index a9b9bdb..6c7a86b 100644
--- a/sheep/sheep.c
+++ b/sheep/sheep.c
@@ -39,6 +39,8 @@
 
 LIST_HEAD(cluster_drivers);
 static const char program_name[] = "sheep";
+static pid_t sheep_pid;
+static int port = SD_LISTEN_PORT;
 
 static struct sd_option sheep_options[] = {
 	{'b', "bindaddr", true, "specify IP address of interface to listen on"},
@@ -99,6 +101,21 @@ static void sdlog_help(void)
 	       "  7    SDOG_DEBUG      debugging messages\n");
 }
 
+static char *log_init_cb(const char *format)
+{
+	static char hdr[MAX_MSG_SIZE];
+
+	if (!strcmp(format, "json")) {
+		snprintf(hdr, MAX_MSG_SIZE, "{ "
+			"\"program\": \"%s\", \"pid\": %d, \"port\": %d"
+			"}", program_name, sheep_pid, port);
+
+		return hdr;
+	}
+
+	return NULL;
+}
+
 static int create_pidfile(const char *filename)
 {
 	int fd = -1;
@@ -114,7 +131,7 @@ static int create_pidfile(const char *filename)
 		return -1;
 	}
 
-	len = snprintf(buffer, sizeof(buffer), "%d\n", getpid());
+	len = snprintf(buffer, sizeof(buffer), "%d\n", sheep_pid);
 	if (write(fd, buffer, len) != len) {
 		close(fd);
 		return -1;
@@ -347,13 +364,13 @@ static void init_journal_arg(char *arg)
 static char *io_addr, *io_pt;
 static void init_io_arg(char *arg)
 {
-	const char *host = "host=", *port = "port=";
-	int hl = strlen(host), pl = strlen(port);
+	const char *host = "host=", *io_port = "port=";
+	int hl = strlen(host), pl = strlen(io_port);
 
 	if (!strncmp(host, arg, hl)) {
 		arg += hl;
 		io_addr = arg;
-	} else if (!strncmp(port, arg, pl)) {
+	} else if (!strncmp(io_port, arg, pl)) {
 		arg += hl;
 		io_pt = arg;
 	} else {
@@ -423,7 +440,7 @@ static void check_host_env(void)
 
 int main(int argc, char **argv)
 {
-	int ch, longindex, ret, port = SD_LISTEN_PORT, io_port = SD_LISTEN_PORT;
+	int ch, longindex, ret, io_port = SD_LISTEN_PORT;
 	int log_level = SDOG_INFO, nr_vnodes = SD_DEFAULT_VNODES;
 	const char *dirp = DEFAULT_OBJECT_DIR, *short_options;
 	char *dir, *p, *pid_file = NULL, *bindaddr = NULL, path[PATH_MAX];
@@ -433,6 +450,7 @@ int main(int argc, char **argv)
 	struct option *long_options;
 	const char *log_format = "default";
 
+	sheep_pid = getpid();
 	signal(SIGPIPE, SIG_IGN);
 
 	long_options = build_long_options(sheep_options);
@@ -607,8 +625,9 @@ int main(int argc, char **argv)
 	if (is_daemon && daemon(0, 0))
 		exit(1);
 
-	ret = log_init(program_name, LOG_SPACE_SIZE, to_stdout, log_level,
-		path);
+	ret = log_init(program_name, LOG_SPACE_SIZE, to_stdout, log_level, path,
+		log_init_cb);
+
 	if (ret)
 		exit(1);
 
-- 
1.7.2.5




More information about the sheepdog mailing list