[sheepdog] [PATCH v3 2/3] logger: JSON format for logging
Hitoshi Mitake
mitake.hitoshi at gmail.com
Tue Jan 29 13:04:54 CET 2013
From: Hitoshi Mitake <mitake.hitoshi at lab.ntt.co.jp>
This patch implements a function for formatting logs in JSON, and a
simple mechanism for supporting multiple formatters like backend
stores and cluster drivers.
Signed-off-by: Hitoshi Mitake <mitake.hitoshi at lab.ntt.co.jp>
---
include/logger.h | 2 +-
lib/logger.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
sheep/sheep.c | 3 +-
3 files changed, 83 insertions(+), 5 deletions(-)
diff --git a/include/logger.h b/include/logger.h
index a972dd0..eac4655 100644
--- a/include/logger.h
+++ b/include/logger.h
@@ -22,7 +22,7 @@
#define MAX_THREAD_NAME_LEN 20
int log_init(const char *progname, int size, bool to_stdout, int level,
- char *outfile);
+ char *outfile, const char *format_name);
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 25ea371..0f5d857 100644
--- a/lib/logger.c
+++ b/lib/logger.c
@@ -68,6 +68,23 @@ struct logmsg {
char str[0];
};
+struct log_format {
+ const char *name;
+ int (*formatter)(char *, size_t, const struct logmsg *);
+ struct list_head list;
+};
+
+#define log_format_register(n, formatter_fn) \
+ static void __attribute__((constructor)) \
+ regist_ ## formatter_fn(void) { \
+ static struct log_format f = \
+ { .name = n, .formatter = formatter_fn }; \
+ list_add(&f.list, &log_formats); \
+}
+
+static LIST_HEAD(log_formats);
+static struct log_format *format;
+
static int log_fd = -1;
static __thread const char *worker_name;
static __thread int worker_idx;
@@ -154,7 +171,7 @@ static void notrace free_logarea(void)
shmdt(la);
}
-static notrace int default_log_format(char *buff, size_t size,
+static notrace int default_log_formatter(char *buff, size_t size,
const struct logmsg *msg)
{
char *p = buff;
@@ -183,6 +200,58 @@ static notrace int default_log_format(char *buff, size_t size,
return p - buff;
}
+log_format_register("default", default_log_formatter);
+
+static notrace int json_log_formatter(char *buff, size_t size,
+ const struct logmsg *msg)
+{
+ int i, body_len;
+ char *p = buff;
+
+ snprintf(p, size, "{");
+ p += strlen(p);
+
+ snprintf(p, size - strlen(buff), "\"second\": %lu", msg->tv.tv_sec);
+ p += strlen(p);
+
+ snprintf(p, size - strlen(buff), ", \"usecond\": %lu", msg->tv.tv_usec);
+ p += strlen(p);
+
+ if (strlen(msg->worker_name))
+ snprintf(p, size - strlen(buff), ", \"worker_name\": \"%s\"",
+ msg->worker_name);
+ else
+ snprintf(p, size - strlen(buff), ", \"worker_name\": \"main\"");
+
+ p += strlen(p);
+
+ snprintf(p, size - strlen(buff), ", \"worker_idx\": %d",
+ msg->worker_idx);
+ p += strlen(p);
+
+ snprintf(p, size - strlen(buff), ", \"func\": \"%s\"", msg->func);
+ p += strlen(p);
+
+ snprintf(p, size - strlen(buff), ", \"line\": %d", msg->line);
+ p += strlen(p);
+
+ snprintf(p, size - strlen(buff), ", \"body\": \"");
+ p += strlen(p);
+
+ body_len = strlen(msg->str) - 1;
+ /* this - 1 eliminates '\n', dirty... */
+ for (i = 0; i < body_len; i++) {
+ if (msg->str[i] == '"')
+ *p++ = '\\';
+ *p++ = msg->str[i];
+ }
+
+ snprintf(p, size - strlen(buff), "\"}\n");
+ p += strlen(p);
+
+ return p - buff;
+}
+log_format_register("json", json_log_formatter);
/*
* this one can block under memory pressure
@@ -192,7 +261,7 @@ static notrace void log_syslog(const struct logmsg *msg)
char str[MAX_MSG_SIZE];
memset(str, 0, MAX_MSG_SIZE);
- default_log_format(str, MAX_MSG_SIZE, msg);
+ format->formatter(str, MAX_MSG_SIZE, msg);
if (log_fd >= 0)
xwrite(log_fd, str, strlen(str));
else
@@ -431,10 +500,18 @@ static notrace void logger(char *log_dir, char *outfile)
}
notrace int log_init(const char *program_name, int size, bool to_stdout,
- int level, char *outfile)
+ int level, char *outfile, const char *format_name)
{
char log_dir[PATH_MAX], tmp[PATH_MAX];
+ list_for_each_entry(format, &log_formats, list) {
+ if (!strcmp(format->name, format_name))
+ goto format_found;
+ }
+
+ panic("invalid format: %s\n", format_name);
+format_found:
+
log_level = level;
log_name = program_name;
diff --git a/sheep/sheep.c b/sheep/sheep.c
index dd0df48..50810c7 100644
--- a/sheep/sheep.c
+++ b/sheep/sheep.c
@@ -595,7 +595,8 @@ 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,
+ "default");
if (ret)
exit(1);
--
1.7.5.1
More information about the sheepdog
mailing list