1 /* layout_simple - a dumb log layout */
3 /* Copyright (c) 2007-2023. The SimGrid Team. */
5 /* This program is free software; you can redistribute it and/or modify it
6 * under the terms of the license (GNU LGPL) which comes with this package. */
8 #include "simgrid/engine.h" /* simgrid_get_clock */
9 #include "simgrid/host.h"
10 #include "src/xbt/log_private.hpp"
11 #include "xbt/sysdep.h"
12 #include <simgrid/actor.h>
13 #include <simgrid/s4u/Actor.hpp>
18 static constexpr const char* ERRMSG =
19 "Unknown %%%c sequence in layout format (%s).\n"
21 " what: %%m: user message %%c: log category %%p: log priority\n"
23 " source: %%F: file %%L: line %%M: function %%l: location (%%F:%%L)\n"
24 " runtime: %%h: hostname %%a: actor %%i: PID\n"
25 " when: %%d: date %%r: app. age\n"
26 " other: %%%%: %% %%n: new line %%e: plain space\n";
28 #define check_overflow(len) \
29 if ((rem_size -= (len)) > 0) { \
34 #define set_sz_from_precision() \
37 if (precision != -1) { \
39 sz = precision + 1; /* +1 for the final '\0' */ \
45 #define show_it(data, letter) \
55 if (precision == -1) { \
56 len = snprintf(p, rem_size, "%*" letter, wd, (data)); \
58 len = snprintf(p, rem_size, "%*.*" letter, wd, precision, (data)); \
61 check_overflow(len); \
65 #define show_string(data) \
67 const char* show_string_data = (data); \
68 show_it(show_string_data ? show_string_data : "(null)", "s"); \
71 #define show_int(data) show_it((data), "d")
72 #define show_long(data) show_it((data), "ld")
73 #define show_double(data) show_it((data), "f")
75 static bool xbt_log_layout_format_doit(const s_xbt_log_layout_t* l, xbt_log_event_t ev, const char* msg_fmt)
78 int rem_size = ev->buffer_size;
82 auto* q = static_cast<char*>(l->data);
98 fprintf(stderr, "Layout format (%s) ending with %%\n", (char*)l->data);
104 case 'n': /* platform-dependant line separator; LOG4J compliant */
108 case 'e': /* plain space; SimGrid extension */
112 case '.': /* precision specifier */
113 precision = static_cast<int>(strtol(q + 1, &q, 10));
114 continue; /* conversion specifier still not found, continue reading */
124 case '9': /* length modifier */
125 length = static_cast<int>(strtol(q, &q, 10));
126 continue; /* conversion specifier still not found, continue reading */
127 case 'c': /* category name; LOG4J compliant
128 should accept a precision postfix to show the hierarchy */
129 show_string(ev->cat->name);
131 case 'p': /* priority name; LOG4J compliant */
132 show_string(xbt_log_priority_names[ev->priority]);
134 case 'h': /* host name; SimGrid extension */
135 show_string(sg_host_self_get_name());
137 case 't': /* thread/process name; LOG4J compliant */
138 case 'P': /* Used before SimGrid 3.26 and kept for compatiblity. Should not hurt. */
139 case 'a': /* actor name; SimGrid extension */
140 show_string(sg_actor_self_get_name());
142 case 'i': /* actor ID; SimGrid extension */
143 show_long(sg_actor_self_get_pid());
145 case 'F': /* file name; LOG4J compliant */
146 show_string(ev->fileName);
148 case 'l': /* location; LOG4J compliant */
149 set_sz_from_precision();
150 len = snprintf(p, sz, "%s:%d", ev->fileName, ev->lineNum);
151 check_overflow(std::min(sz, len));
153 case 'L': /* line number; LOG4J compliant */
154 show_int(ev->lineNum);
156 case 'M': /* method (ie, function) name; LOG4J compliant */
157 show_string(ev->functionName);
159 case 'd': /* date; LOG4J compliant */
160 case 'r': /* application age; LOG4J compliant */
161 show_double(simgrid_get_clock());
163 case 'm': /* user-provided message; LOG4J compliant */
164 set_sz_from_precision();
167 len = vsnprintf(p, sz, msg_fmt, ap);
169 check_overflow(std::min(sz, len));
172 fprintf(stderr, ERRMSG, *q, (char*)l->data);
175 break; /* done, continue normally */
184 static void xbt_log_layout_format_free(const s_xbt_log_layout_t* lay)
189 xbt_log_layout_t xbt_log_layout_format_new(const char* arg)
191 auto* res = xbt_new0(s_xbt_log_layout_t, 1);
192 res->do_layout = &xbt_log_layout_format_doit;
193 res->free_ = &xbt_log_layout_format_free;
194 res->data = xbt_strdup(arg);