1 /* layout_simple - a dumb log layout */
3 /* Copyright (c) 2007-2011. The SimGrid Team.
4 * All rights reserved. */
6 /* This program is free software; you can redistribute it and/or modify it
7 * under the terms of the license (GNU LGPL) which comes with this package. */
9 #include "portable.h" /* execinfo when available */
10 #include "xbt/sysdep.h"
11 #include "xbt/strbuff.h"
12 #include "xbt/log_private.h"
13 #include "gras/virtu.h" /* gras_os_myname (KILLME) */
14 #include "xbt/synchro.h" /* xbt_thread_self_name */
17 extern const char *xbt_log_priority_names[8];
19 static double format_begin_of_time = -1;
22 "Unknown %%%c sequence in layout format (%s).\n" \
23 "Known sequences:\n" \
24 " what: %%m: user message %%c: log category %%p: log priority\n" \
26 " source: %%F: file %%L: line %%M: function %%l: location (%%F:%%L)\n" \
27 " runtime: %%h: hostname %%t: thread %%P: process %%i: PID\n" \
28 " backtrace: %%b: full %%B: short\n" \
29 " when: %%d: date %%r: app. age\n" \
30 " other: %%%%: %% %%n: new line %%e: plain space\n"
32 #define check_overflow(len) \
33 if ((rem_size -= (len)) > 0) { \
38 #define set_sz_from_precision() \
41 if (precision != -1) { \
43 sz = precision + 1; /* +1 for the final '\0' */ \
48 #define show_it(data, letter) \
57 if (precision == -1) { \
58 len = snprintf(p, rem_size, "%*" letter, wd, data); \
60 len = snprintf(p, rem_size, "%*.*" letter, wd, precision, data); \
63 check_overflow(len); \
66 #define show_string(data) show_it(data, "s")
67 #define show_int(data) show_it(data, "d")
68 #define show_double(data) show_it(data, "f")
70 static int xbt_log_layout_format_doit(xbt_log_layout_t l,
75 int rem_size = ev->buffer_size;
80 for (q = l->data ; *q != '\0' ; q++) {
86 xbt_die("Layout format (%s) ending with %%\n", (char *)l->data);
91 case 'n': /* platform-dependant line separator; LOG4J compliant */
95 case 'e': /* plain space; SimGrid extension */
99 case '.': /* precision specifier */
100 precision = strtol(q + 1, &q, 10);
101 goto handle_modifier;
111 case '9': /* length modifier */
112 length = strtol(q, &q, 10);
113 goto handle_modifier;
114 case 'c': /* category name; LOG4J compliant
115 should accept a precision postfix to show the
117 show_string(ev->cat->name);
119 case 'p': /* priority name; LOG4J compliant */
120 show_string(xbt_log_priority_names[ev->priority]);
122 case 'h': /* host name; SimGrid extension */
123 show_string(gras_os_myname());
125 case 't': /* thread name; LOG4J compliant */
126 show_string(xbt_thread_self_name());
128 case 'P': /* process name; SimGrid extension */
129 show_string(xbt_procname());
131 case 'i': /* process PID name; SimGrid extension */
132 show_int(xbt_getpid());
134 case 'F': /* file name; LOG4J compliant */
135 show_string(ev->fileName);
137 case 'l': { /* location; LOG4J compliant */
139 set_sz_from_precision();
140 len = snprintf(p, sz, "%s:%d", ev->fileName, ev->lineNum);
141 check_overflow(MIN(sz, len));
144 case 'L': /* line number; LOG4J compliant */
145 show_int(ev->lineNum);
147 case 'M': /* method (ie, function) name; LOG4J compliant */
148 show_string(ev->functionName);
150 case 'b': /* backtrace; called %throwable in LOG4J */
151 case 'B': /* short backtrace; called %throwable{short} in LOG4J */
152 #if defined(HAVE_EXECINFO_H) && defined(HAVE_POPEN) && defined(ADDR2LINE)
156 e.used = backtrace((void **) e.bt, XBT_BACKTRACE_SIZE);
160 xbt_backtrace_current(&e);
162 show_string(e.bt_strings[2] + 8);
164 xbt_strbuff_t buff = xbt_strbuff_new();
166 for (i = 2; i < e.used; i++) {
167 xbt_strbuff_append(buff, e.bt_strings[i] + 8);
168 xbt_strbuff_append(buff, "\n");
170 show_string(buff->data);
171 xbt_strbuff_free(buff);
176 show_string("(no backtrace on this arch)");
179 case 'd': /* date; LOG4J compliant */
180 show_double(gras_os_time());
182 case 'r': /* application age; LOG4J compliant */
183 show_double(gras_os_time() - format_begin_of_time);
185 case 'm': { /* user-provided message; LOG4J compliant */
187 set_sz_from_precision();
188 len = vsnprintf(p, sz, msg_fmt, ev->ap);
189 check_overflow(MIN(sz, len));
193 xbt_die(ERRMSG, *q, (char *)l->data);
205 static void xbt_log_layout_format_free(xbt_log_layout_t lay)
210 xbt_log_layout_t xbt_log_layout_format_new(char *arg)
212 xbt_log_layout_t res = xbt_new0(s_xbt_log_layout_t, 1);
213 res->do_layout = xbt_log_layout_format_doit;
214 res->free_ = xbt_log_layout_format_free;
215 res->data = xbt_strdup((char *) arg);
217 if (format_begin_of_time < 0)
218 format_begin_of_time = gras_os_time();