[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