DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
Logger.hxx
Go to the documentation of this file.
1
8#ifndef LOGGING_INCLUDE_LOGGING_DETAIL_LOGGER_HXX_
9#define LOGGING_INCLUDE_LOGGING_DETAIL_LOGGER_HXX_
10
11#include <stdlib.h> // setenv
12
13
14/* verstrace_user
15 Only log and debug "levels" (or "streams") are supported
16 */
17#if defined(__has_feature)
18# if __has_feature(thread_sanitizer)
19__attribute__((no_sanitize("thread")))
20# endif
21#endif
22static void verstrace_user(struct timeval */*tvp*/, int TID, uint8_t lvl, const char* insert
23 , const char* file, int line, const char* function, uint16_t nargs, const char *msg, va_list ap)
24{
25
26 size_t printed = 0;
27 int retval;
28 const char *outp;
29 char obuf[TRACE_USER_MSGMAX];
30
31 if ((insert && (printed = strlen(insert))) || nargs)
32 {
33 /* check insert 1st to make sure printed is set */
34 // assume insert is smaller than obuf
35 if (printed) {
36 retval = snprintf(obuf,sizeof(obuf),"%s ",insert );
37 printed = TRACE_SNPRINTED(retval,sizeof(obuf));
38 }
39 if (nargs) {
40 retval = vsnprintf(&(obuf[printed]), sizeof(obuf) - printed, msg, ap); // man page say obuf will always be terminated
41 printed += TRACE_SNPRINTED(retval,sizeof(obuf)-printed);
42 } else {
43 /* don't do any parsing for format specifiers in the msg -- tshow will
44 also know to do this on the memory side of things */
45 retval = snprintf( &(obuf[printed]), sizeof(obuf)-printed, "%s", msg );
46 printed += TRACE_SNPRINTED(retval,sizeof(obuf)-printed);
47 }
48 if (obuf[printed-1] == '\n')
49 obuf[printed-1] = '\0'; // DONE w/ printed (don't need to decrement
50 outp = obuf;
51 } else {
52 if (msg[strlen(msg)-1] == '\n') { // need to copy to remove the trailing nl
53 retval = snprintf( obuf, sizeof(obuf), "%s", msg );
54 printed = TRACE_SNPRINTED(retval,sizeof(obuf));
55 if (obuf[printed-1] == '\n')
56 obuf[printed-1] = '\0'; // DONE w/ printed (don't need to decrement
57 outp = obuf;
58 } else
59 outp = msg;
60 }
61 // LocalContext args: 1-"package_name" 2-"file" 3-"line" 4-"pretty_function" 5-"include_stack"
63 reinterpret_cast<char*>(idx2namsPtr(TID)),
64 file, line, function, DEBUG_FORCED );
65 //std::ostringstream ers_report_impl_out_buffer;
66 //ers_report_impl_out_buffer << outp;
67 if (lvl < TLVL_DEBUG) { // NOTE: at least currently, TLVL_LOG is numerically 1 less than TLVL_DEBUG
68 //auto d = std::chrono::seconds{tvp->tv_sec} + std::chrono::microseconds{tvp->tv_usec};
70 //std::chrono::system_clock::time_point tp{d};
71 // PROTECTED - ers::Issue iss( ers::Issue( ers::Severity(ers::Log), tp, lc, outp, std::vector<std::string>(), std::map<std::string,std::string>(), nullptr ));
72 ers::log( ers::InternalMessage(lc,outp) );
73 } else {
74 ers::debug( ers::InternalMessage(lc,outp),lvl-TLVL_DEBUG );
75 }
76}
77
78SUPPRESS_NOT_USED_WARN
79static void erstrace_user(struct timeval *tvp, int TID, uint8_t lvl, const char* insert, const char* file, int line, const char* function, uint16_t nargs, const char *msg, ...)
80{
81 va_list ap;
82 va_start(ap, msg);
83 verstrace_user(tvp, TID, lvl, insert, file, line, function, nargs, msg, ap);
84 va_end(ap);
85}
86
87#pragma GCC diagnostic push
88#pragma GCC diagnostic ignored "-Wvarargs"
89SUPPRESS_NOT_USED_WARN
90static void erstrace_user(struct timeval *tvp, int TID, uint8_t lvl, const char* insert, const char* file, int line, const char* function, uint16_t nargs, const std::string& msg, ...)
91{
92 va_list ap;
93 va_start(ap, msg);
94 verstrace_user(tvp, TID, lvl, insert, file, line, function, nargs, &msg[0], ap);
95 va_end(ap);
96} /* trace */
97#pragma GCC diagnostic pop
98
99
100
101// The following allow an ers::Issue to be streamed into TLOG() or TLOG_DEBUG(N)
102inline void operator<<(TraceStreamer& x, const ers::Issue &r)
103{
104 if (x.do_m) {
105 x.line_ = r.context().line_number();
106 x.msg_append(r.message().c_str());
107 // MAY NEED TO APPEND CHAINED ISSUE???
108 // const ers::Issue *issp = &r;
109 // while ((issp=issp->cause())) {
110 // }
111 }
112 if (x.do_s) {
113 if (x.lvl_==TLVL_INFO) ers::info( r ); \
114 else if (x.lvl_==TLVL_LOG) ers::log( r ); \
115 else ers::debug( r, x.lvl_-TLVL_DEBUG ); \
116 x.do_s = 0;
117 }
118}
119
120inline void operator<<(TraceStreamer& x, const ers::InternalMessage &r)
121{
122 if (x.do_m) {
123 x.line_ = r.context().line_number();
124 x.msg_append(r.message().c_str());
125 // MAY NEED TO APPEND CHAINED ISSUE???
126 }
127 if (x.do_s) {
128 if (x.lvl_==TLVL_INFO) ers::info( r ); \
129 else if (x.lvl_==TLVL_LOG) ers::log( r ); \
130 else ers::debug( r, x.lvl_-TLVL_DEBUG ); \
131 x.do_s = 0;
132 }
133}
134
135
136namespace { // unnamed namespace (i.e. static (for each compliation unit only))
137
138 class ErsFatalStreamer
139 {
140 public:
141 inline ErsFatalStreamer &operator<<(const ers::Issue &r)
142 {
143 ers::fatal( r );
144 return *this;
145 }
146 }; // class ErsFatalStreamer
147
148 class ErsErrorStreamer
149 {
150 public:
151 inline ErsErrorStreamer &operator<<(const ers::Issue &r)
152 {
153 ers::error( r );
154 return *this;
155 }
156 }; // class ErsErrorStreamer
157
158 class ErsWarningStreamer
159 {
160 public:
161 //ErsWarningStreamer( ers::LocalContext c ) : _ctx(c) {}
162 //ers::LocalContext _ctx;
163 inline ErsWarningStreamer &operator<<(const ers::Issue &r)
164 {
165 // would be nice of the "context" could be created from the streamer instance
166 ers::warning( r );
167 return *this;
168 }
169 }; // class ErsWarningStreamer
170 class ErsInfoStreamer
171 {
172 public:
173 //ErsInfoStreamer( ers::LocalContext c ) : _ctx(c) {}
174 //ers::LocalContext _ctx;
175 inline ErsInfoStreamer &operator<<(const ers::Issue &r)
176 {
177 // would be nice of the "context" could be created from the streamer instance
178 ers::warning( r );
179 return *this;
180 }
181 }; // class ErsInfoStreamer
182 class ErsLogStreamer
183 {
184 public:
185 //ErsLogStreamer( ers::LocalContext c ) : _ctx(c) {}
186 //ers::LocalContext _ctx;
187 inline ErsLogStreamer &operator<<(const ers::Issue &r)
188 {
189 // would be nice of the "context" could be created from the streamer instance
190 ers::warning( r );
191 return *this;
192 }
193 }; // class ErsLogStreamer
194} // namespace ""
195
196
197
198// The following allows "erstrace" to be included in the ERS configuration via
199// DUNEDAQ_ERS_{FATAL,ERROR,WARNING} environment variables.
200#include <ers/OutputStream.hpp>
201namespace ers
202{
204 void write( const ers::Issue & issue )
205 {
206 ers::Severity sev = issue.severity();
207 uint8_t lvl_=TLVL_DEBUG;
208 switch (sev.type) {
209 case ers::Debug: lvl_=TLVL_DEBUG+sev.rank;break;
210 case ers::Log: lvl_=TLVL_LOG; break;
211 case ers::Information: lvl_=TLVL_INFO; break;
212 case ers::Warning: lvl_=TLVL_WARNING; break;
213 case ers::Error: lvl_=TLVL_ERROR; break;
214 case ers::Fatal: lvl_=TLVL_FATAL; break;
215 }
216 struct { char tn[TRACE_TN_BUFSZ]; } _trc_;
217 if (TRACE_INIT_CHECK(trace_name(TRACE_NAME,issue.context().file_name(),_trc_.tn,sizeof(_trc_.tn)))) {
218 if (traceControl_rwp->mode.bits.M && (traceLvls_p[traceTID].M & TLVLMSK(lvl_))) {
219 struct timeval lclTime;
220 std::chrono::system_clock::time_point tp{issue.ptime()};
221 //auto micros = std::chrono::duration_cast<std::chrono::microseconds>(tp.time_since_epoch());
222 std::chrono::microseconds micros = std::chrono::duration_cast<std::chrono::microseconds>(tp.time_since_epoch());
223 lclTime.tv_sec = micros.count() / 1000000;
224 lclTime.tv_usec = micros.count() % 1000000;
225 int traceID = trace_name2TID( trace_name(TRACE_NAME,issue.context().file_name(),_trc_.tn,sizeof(_trc_.tn)) );
226 std::string complete_message = issue.message();
227 const ers::Issue *issp = &issue;
228 while ((issp=issp->cause())) {
229 char fbuf[0x100], tbuf[0x40];
230 int strip_ns=1;
231 tp = issp->ptime();
232 std::chrono::milliseconds millis
233 = std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch());
234 struct tm tm_s;
235 time_t secs = millis.count() / 1000;
236 localtime_r(&secs, &tm_s);
237 if (strftime(tbuf, sizeof(tbuf), "%Y-%b-%d %H:%M:%S", &tm_s) == 0)
238 tbuf[0]= '\0';
239 complete_message += "\n\tcaused by: " + std::string(tbuf);
240 int milliseconds = millis.count() % 1000;
241 sprintf(tbuf,",%03d ",milliseconds);
242 complete_message += std::string(tbuf);
243 trace_func_to_short_func(issp->context().function_name(), fbuf, sizeof(fbuf), strip_ns);
244 complete_message += ers::to_string(issp->severity())
245 + " [" + fbuf + " at "
246 + trace_path_components(issp->context().file_name(),0)
247 + ":" + std::to_string(issp->context().line_number())
248 + "] " + issp->message();
249 }
250 trace(&lclTime, traceID, lvl_, issue.context().line_number(),
251 issue.context().function_name(),
252 0 TRACE_XTRA_PASSED, complete_message.c_str());
253 }
254 }
255 chained().write( issue );
256 }
257};
258}
259ERS_REGISTER_OUTPUT_STREAM( ers::erstraceStream, "erstrace", ERS_EMPTY ) // last param is "param"
260
261
262// Support macros
263#define SL_FRC(lvl) ((lvl)>=0 && (lvl)<TLVL_DEBUG)
264
265#define LOG0_()
266#define LOG1_(value) value,
267#define LOG2_(value, value1) value , value1,
268#define COMMA_IF_PARENS(...) ,
269#define LPAREN (
270#define EXPAND_(...) __VA_ARGS__
271#define CHOOSE_(...) EXPAND_(LOG__ LPAREN \
272 __VA_ARGS__ COMMA_IF_PARENS __VA_ARGS__ COMMA_IF_PARENS __VA_ARGS__ (), \
273 LOG2_, impossible, LOG2_, LOG1_, LOG0_, LOG1_, ))
274#define LOG__(a0, a1, a2, a3, a4, a5, arg, ...) arg
275#define _tlog_ARG2( a1,a2,...) tlog_ARG2(a1,a2,__VA_ARGS__)
276#define _tlog_ARG3( a1,a2,a3,...) tlog_ARG3(a1,a2,a3,__VA_ARGS__)
277
278
279#endif // LOGGING_INCLUDE_LOGGING_DETAIL_LOGGER_HXX_
#define ERS_EMPTY
static void verstrace_user(struct timeval *, int TID, uint8_t lvl, const char *insert, const char *file, int line, const char *function, uint16_t nargs, const char *msg, va_list ap)
Definition Logger.hxx:22
static SUPPRESS_NOT_USED_WARN void erstrace_user(struct timeval *tvp, int TID, uint8_t lvl, const char *insert, const char *file, int line, const char *function, uint16_t nargs, const char *msg,...)
Definition Logger.hxx:79
void operator<<(TraceStreamer &x, const ers::Issue &r)
Definition Logger.hxx:102
virtual int line_number() const =0
virtual const char * file_name() const =0
virtual const char * function_name() const =0
Base class for any user define issue.
Definition Issue.hpp:69
const Context & context() const
Context of the issue.
Definition Issue.hpp:100
ers::Severity severity() const
severity of the issue
Definition Issue.hpp:112
const system_clock::time_point & ptime() const
original time point of the issue
Definition Issue.hpp:130
const std::string & message() const
General cause of the issue.
Definition Issue.hpp:103
const Issue * cause() const
return the cause Issue of this Issue
Definition Issue.hpp:97
ERS abstract output stream interface.
virtual void write(const Issue &issue)=0
OutputStream & chained()
#define ERS_REGISTER_OUTPUT_STREAM(class, name, param)
Definition macro.hpp:16
void warning(const Issue &issue)
Definition ers.hpp:115
void info(const Issue &issue)
Definition ers.hpp:95
void log(const Issue &issue)
Definition ers.hpp:102
std::string to_string(severity s)
void debug(const Issue &issue, int level=debug_level())
Definition ers.hpp:74
void fatal(const Issue &issue)
Definition ers.hpp:88
@ Debug
Definition Severity.hpp:26
@ Error
Definition Severity.hpp:26
@ Fatal
Definition Severity.hpp:26
@ Log
Definition Severity.hpp:26
@ Warning
Definition Severity.hpp:26
@ Information
Definition Severity.hpp:26
void error(const Issue &issue)
Definition ers.hpp:81
#define TRACE_NAME
enum severity type
Definition Severity.hpp:38
void write(const ers::Issue &issue)
Definition Logger.hxx:204