1 /* layout_simple - a dumb log layout */
3 /* Copyright (c) 2007, 2008, 2009, 2010. 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;
21 #define append1(fmt,fmt2,elm) \
23 if (precision == -1) { \
24 xbt_strbuff_append(buff, tmp=bprintf(fmt,elm)); \
27 xbt_strbuff_append(buff, tmp=bprintf(fmt2,precision,elm)); \
32 #define append2(fmt,elm,elm2) \
34 xbt_strbuff_append(buff, tmp=bprintf(fmt,elm,elm2)); \
39 #define ERRMSG "Unknown %%%c sequence in layout format (%s).\nKnown sequences:\n" \
40 " what: %%m: user message %%c: log category %%p: log priority\n" \
42 " source: %%F: file %%L: line %%M: function %%l: location (%%F:%%L)\n" \
43 " runtime: %%h: hostname %%t: thread %%P: process %%i: PID\n" \
44 " backtrace: %%b: full %%B: short\n" \
45 " when: %%d: date %%r: app. age\n" \
46 " other: %%%%: %% %%n: new line %%e: plain space\n"
49 static void xbt_log_layout_format_dynamic(xbt_log_layout_t l,
52 xbt_log_appender_t app)
54 xbt_strbuff_t buff = xbt_strbuff_new();
66 fprintf(stderr, "Layout format (%s) ending with %%\n",
70 xbt_strbuff_append(buff, "%");
72 case 'n': /* platform-dependant line separator (LOG4J compliant) */
73 xbt_strbuff_append(buff, "\n");
75 case 'e': /* plain space (SimGrid extension) */
76 xbt_strbuff_append(buff, " ");
79 case '.': /* precision specifyier */
81 q += sscanf(q, "%d", &precision);
84 case 'c': /* category name; LOG4J compliant
85 should accept a precision postfix to show the hierarchy */
86 append1("%s", "%.*s", ev->cat->name);
88 case 'p': /* priority name; LOG4J compliant */
89 append1("%s", "%.*s", xbt_log_priority_names[ev->priority]);
92 case 'h': /* host name; SimGrid extension */
93 append1("%s", "%.*s", gras_os_myname());
95 case 't': /* thread name; LOG4J compliant */
96 append1("%s", "%.*s", xbt_thread_self_name());
98 case 'P': /* process name; SimGrid extension */
99 append1("%s", "%.*s", xbt_procname());
101 case 'i': /* process PID name; SimGrid extension */
102 append1("%d", "%.*d", (*xbt_getpid) ());
105 case 'F': /* file name; LOG4J compliant */
106 append1("%s", "%.*s", ev->fileName);
108 case 'l': /* location; LOG4J compliant */
109 append2("%s:%d", ev->fileName, ev->lineNum);
110 precision = -1; /* Ignored */
112 case 'L': /* line number; LOG4J compliant */
113 append1("%d", "%.*d", ev->lineNum);
115 case 'M': /* method (ie, function) name; LOG4J compliant */
116 append1("%s", "%.*s", ev->functionName);
118 case 'b': /* backtrace; called %throwable in LOG4J */
119 case 'B': /* short backtrace; called %throwable{short} in LOG4J */
120 #if defined(HAVE_EXECINFO_H) && defined(HAVE_POPEN) && defined(ADDR2LINE)
125 e.used = backtrace((void **) e.bt, XBT_BACKTRACE_SIZE);
129 xbt_backtrace_current(&e);
131 append1("%s", "%.*s", e.bt_strings[2] + 8);
133 for (i = 2; i < e.used; i++)
134 append1("%s\n", "%.*s\n", e.bt_strings[i] + 8);
140 append1("%s", "%.*s", "(no backtrace on this arch)");
144 case 'd': /* date; LOG4J compliant */
145 append1("%f", "%.*f", gras_os_time());
147 case 'r': /* application age; LOG4J compliant */
148 append1("%f", "%.*f", gras_os_time() - format_begin_of_time);
151 case 'm': /* user-provided message; LOG4J compliant */
152 tmp2 = bvprintf(fmt, ev->ap_copy);
153 append1("%s", "%.*s", tmp2);
158 fprintf(stderr, ERRMSG, *q, (char *) l->data);
166 xbt_strbuff_append(buff, tmp2);
169 app->do_append(app, buff->data);
170 xbt_strbuff_free(buff);
173 #undef check_overflow
174 #define check_overflow \
175 if (p-ev->buffer > XBT_LOG_BUFF_SIZE) { /* buffer overflow */ \
176 xbt_log_layout_format_dynamic(l,ev,msg_fmt,app); \
179 static void xbt_log_layout_format_doit(xbt_log_layout_t l,
182 xbt_log_appender_t app)
197 fprintf(stderr, "Layout format (%s) ending with %%\n",
203 case 'n': /* platform-dependant line separator (LOG4J compliant) */
204 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), "\n");
207 case 'e': /* plain space (SimGrid extension) */
208 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), " ");
212 case '.': /* precision specifyier */
214 q += sscanf(q, "%d", &precision);
215 goto handle_modifier;
217 case 'c': /* category name; LOG4J compliant
218 should accept a precision postfix to show the hierarchy */
219 if (precision == -1) {
220 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), "%s",
224 p += sprintf(p, "%.*s",
225 (int) MIN(XBT_LOG_BUFF_SIZE - (p - ev->buffer),
226 precision), ev->cat->name);
231 case 'p': /* priority name; LOG4J compliant */
232 if (precision == -1) {
233 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), "%s",
234 xbt_log_priority_names[ev->priority]);
237 p += sprintf(p, "%.*s",
238 (int) MIN(XBT_LOG_BUFF_SIZE - (p - ev->buffer),
240 xbt_log_priority_names[ev->priority]);
246 case 'h': /* host name; SimGrid extension */
247 if (precision == -1) {
248 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), "%s",
252 p += sprintf(p, "%.*s",
253 (int) MIN(XBT_LOG_BUFF_SIZE - (p - ev->buffer),
254 precision), gras_os_myname());
259 case 't': /* thread name; LOG4J compliant */
260 if (precision == -1) {
261 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), "%s",
262 xbt_thread_self_name());
265 p += sprintf(p, "%.*s",
266 (int) MIN(XBT_LOG_BUFF_SIZE - (p - ev->buffer),
267 precision), xbt_thread_self_name());
272 case 'P': /* process name; SimGrid extension */
273 if (precision == -1) {
274 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), "%s",
278 p += sprintf(p, "%.*s",
279 (int) MIN(XBT_LOG_BUFF_SIZE - (p - ev->buffer),
280 precision), xbt_procname());
285 case 'i': /* process PID name; SimGrid extension */
286 if (precision == -1) {
287 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), "%d",
291 p += sprintf(p, "%.*d",
292 (int) MIN(XBT_LOG_BUFF_SIZE - (p - ev->buffer),
293 precision), (*xbt_getpid) ());
299 case 'F': /* file name; LOG4J compliant */
300 if (precision == -1) {
301 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), "%s",
305 p += sprintf(p, "%.*s",
306 (int) MIN(XBT_LOG_BUFF_SIZE - (p - ev->buffer),
307 precision), ev->fileName);
312 case 'l': /* location; LOG4J compliant */
313 if (precision == -1) {
314 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), "%s:%d",
315 ev->fileName, ev->lineNum);
319 (int) MIN(XBT_LOG_BUFF_SIZE - (p - ev->buffer),
320 precision), "%s:%d", ev->fileName,
326 case 'L': /* line number; LOG4J compliant */
327 if (precision == -1) {
328 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), "%d",
332 p += sprintf(p, "%.*d",
333 (int) MIN(XBT_LOG_BUFF_SIZE - (p - ev->buffer),
334 precision), ev->lineNum);
339 case 'M': /* method (ie, function) name; LOG4J compliant */
340 if (precision == -1) {
341 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), "%s",
345 p += sprintf(p, "%.*s",
346 (int) MIN(XBT_LOG_BUFF_SIZE - (p - ev->buffer),
347 precision), ev->functionName);
352 case 'b': /* backtrace; called %throwable in LOG4J */
353 case 'B': /* short backtrace; called %throwable{short} in LOG4J */
354 #if defined(HAVE_EXECINFO_H) && defined(HAVE_POPEN) && defined(ADDR2LINE)
359 e.used = backtrace((void **) e.bt, XBT_BACKTRACE_SIZE);
363 xbt_backtrace_current(&e);
365 if (precision == -1) {
366 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), "%s",
367 e.bt_strings[2] + 8);
370 p += sprintf(p, "%.*s",
371 (int) MIN(XBT_LOG_BUFF_SIZE - (p - ev->buffer),
372 precision), e.bt_strings[2] + 8);
377 for (i = 2; i < e.used; i++)
378 if (precision == -1) {
379 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer),
380 "%s\n", e.bt_strings[i] + 8);
383 p += sprintf(p, "%.*s\n",
384 (int) MIN(XBT_LOG_BUFF_SIZE -
385 (p - ev->buffer), precision),
386 e.bt_strings[i] + 8);
395 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer),
396 "(no backtrace on this arch)");
401 case 'd': /* date; LOG4J compliant */
402 if (precision == -1) {
403 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), "%f",
407 p += sprintf(p, "%.*f",
408 (int) MIN(XBT_LOG_BUFF_SIZE - (p - ev->buffer),
409 precision), gras_os_time());
414 case 'r': /* application age; LOG4J compliant */
415 if (precision == -1) {
416 p += snprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), "%f",
417 gras_os_time() - format_begin_of_time);
420 p += sprintf(p, "%.*f",
421 (int) MIN(XBT_LOG_BUFF_SIZE - (p - ev->buffer),
423 gras_os_time() - format_begin_of_time);
429 case 'm': /* user-provided message; LOG4J compliant */
430 if (precision == -1) {
431 p += vsnprintf(p, XBT_LOG_BUFF_SIZE - (p - ev->buffer), msg_fmt,
436 (int) MIN(XBT_LOG_BUFF_SIZE - (p - ev->buffer),
437 precision), msg_fmt, ev->ap);
444 fprintf(stderr, ERRMSG, *q, (char *) l->data);
454 app->do_append(app, ev->buffer);
457 static void xbt_log_layout_format_free(xbt_log_layout_t lay)
462 xbt_log_layout_t xbt_log_layout_format_new(char *arg)
464 xbt_log_layout_t res = xbt_new0(s_xbt_log_layout_t, 1);
465 res->do_layout = xbt_log_layout_format_doit;
466 res->free_ = xbt_log_layout_format_free;
467 res->data = xbt_strdup((char *) arg);
469 if (format_begin_of_time < 0)
470 format_begin_of_time = gras_os_time();