Line data Source code
1 : /* This file (tracemf.h) was created by Ron Rechenmacher <ron@fnal.gov> on
2 : // Apr 18, 2014. "TERMS AND CONDITIONS" governing this file are in the README
3 : // or COPYING file. If you do not have such a file, one can be obtained by
4 : // contacting Ron or Fermi Lab in Batavia IL, 60510, phone: 630-840-3000.
5 : // $RCSfile: tracemf.hh,v $
6 : // rev="$Revision: 1702 $$Date: 2025-01-28 12:48:14 -0600 (Tue, 28 Jan 2025) $";
7 : */
8 : /**
9 : * \file tracemf.h
10 : * Defines TRACE macros which send "slow" traces to MessageFacility
11 : *
12 : */
13 : #ifndef TRACEMF_H
14 : #define TRACEMF_H
15 :
16 : #ifdef __cplusplus
17 :
18 : // Use this define! -- trace.h won't define it's own version of TRACE_LOG_FUNCTION
19 : // The TRACE macro will then use the static vmftrace_user function defined in this file
20 : // for the "slow" tracing function (if appropriate mask bit is set :)
21 : # include <stdint.h> // uint16_t
22 : # include <string> // std::string
23 :
24 : # define TRACE_LOG_FUN_PROTO \
25 : static void mftrace_user(struct timeval*, int, uint8_t, const char*, const char*, int, const char*, uint16_t nargs, \
26 : const char* msg, ...); \
27 : static void mftrace_user(struct timeval*, int, uint8_t, const char*, const char*, int, const char*, uint16_t nargs, \
28 : const std::string& msg, ...)
29 : # undef TRACE_LOG_FUNCTION
30 : # define TRACE_LOG_FUNCTION mftrace_user
31 : # undef TSTREAMER_SL_FRC
32 : # define TSTREAMER_SL_FRC(lvl) \
33 : ((lvl < static_cast<int>(TLVL_INFO)) || \
34 : ((lvl <= static_cast<int>(TLVL_DEBUG)) && DEBUG_FORCED)) /* in these cases, only mf config/thresh rules */
35 : # include "TRACE/trace.h" /* TRACE */
36 :
37 : # include "messagefacility/MessageLogger/MessageLogger.h" // LOG_DEBUG
38 : # include "cetlib_except/exception.h" // cet::exception
39 :
40 : # if defined(__has_feature)
41 : # if __has_feature(thread_sanitizer)
42 : __attribute__((no_sanitize("thread")))
43 : # endif
44 : # endif
45 : static void
46 703 : vmftrace_user(struct timeval*, int TID, uint8_t lvl, const char* insert, const char* file, int line, uint16_t nargs,
47 : const char* msg, va_list ap)
48 : {
49 : /* I format output in a local output buffer (with specific/limited size)
50 : first. There are 2 main reasons that this is done:
51 : 1) allows the use of write to a specific tracePrintFd;
52 : 2) there will be one system call which is most efficient and less likely
53 : to have the output mangled in a multi-threaded environment.
54 : */
55 703 : size_t printed= 0;
56 : int retval;
57 : const char* outp;
58 : char obuf[TRACE_USER_MSGMAX];
59 :
60 703 : if ((insert && (printed= strlen(insert))) || nargs) {
61 : /* check insert 1st to make sure printed is set */
62 : // assume insert is smaller than obuf
63 7 : if (printed) {
64 7 : retval= snprintf(obuf, sizeof(obuf), "%s ", insert);
65 7 : printed= TRACE_SNPRINTED(retval, sizeof(obuf));
66 : }
67 7 : if (nargs) {
68 0 : retval= vsnprintf(&(obuf[printed]), sizeof(obuf) - printed, msg, ap); // man page say obuf will always be terminated
69 0 : printed+= TRACE_SNPRINTED(retval, sizeof(obuf) - printed);
70 : } else {
71 : /* don't do any parsing for format specifiers in the msg -- tshow will
72 : also know to do this on the memory side of things */
73 7 : retval= snprintf(&(obuf[printed]), sizeof(obuf) - printed, "%s", msg);
74 7 : printed+= TRACE_SNPRINTED(retval, sizeof(obuf) - printed);
75 : }
76 7 : if (obuf[printed - 1] == '\n') obuf[printed - 1]= '\0'; // DONE w/ printed (don't need to decrement
77 7 : outp= obuf;
78 : } else {
79 696 : if (msg[strlen(msg) - 1] == '\n') { // need to copy to remove the trailing nl
80 0 : retval= snprintf(obuf, sizeof(obuf), "%s", msg);
81 0 : printed= TRACE_SNPRINTED(retval, sizeof(obuf));
82 0 : if (obuf[printed - 1] == '\n') obuf[printed - 1]= '\0'; // DONE w/ printed (don't need to decrement
83 0 : outp= obuf;
84 : } else
85 696 : outp= msg;
86 : }
87 :
88 : // Define MESSAGEFACILITY_HEX_VERSION in top-level CMakeLists.txt (see artdaq's CMakeLists.txt!)
89 : # ifdef MESSAGEFACILITY_HEX_VERSION
90 : # if MESSAGEFACILITY_HEX_VERSION >= 0x20201
91 : # ifdef ARTDAQ_DAQDATA_GLOBALS_HH
92 : mf::SetIteration(GetMFIteration());
93 : mf::SetModuleName(GetMFModuleName());
94 : # endif
95 : # else
96 : # ifdef ARTDAQ_DAQDATA_GLOBALS_HH
97 : mf::SetContextIteration(GetMFIteration());
98 : mf::SetContextSinglet(GetMFModuleName());
99 : # endif
100 : # endif
101 : # endif
102 :
103 703 : switch (lvl) {
104 : # ifdef TRACEMF_USE_VERBATIM
105 : // NOTE: need this "Verbatim" set of methods to get full filename
106 : case TLVL_ERROR: ::mf::LogProblem(TRACE_TID2NAME(TID), file, line) << outp; break;
107 : case TLVL_WARNING: ::mf::LogPrint(TRACE_TID2NAME(TID), file, line) << outp; break;
108 : case TLVL_INFO: ::mf::LogVerbatim{TRACE_TID2NAME(TID), file, line} << outp; break;
109 : case TLVL_DEBUG: ::mf::LogTrace{TRACE_TID2NAME(TID), file, line} << outp; break;
110 : default: ::mf::LogTrace{TRACE_TID2NAME(TID), file, line} << std::to_string(lvl) << ": " << outp; break;
111 : # else
112 85 : case TLVL_ERROR: ::mf::LogError(TRACE_TID2NAME(TID), file, line) << outp; break;
113 45 : case TLVL_WARNING: ::mf::LogWarning(TRACE_TID2NAME(TID), file, line) << outp; break;
114 2415 : case TLVL_INFO: ::mf::LogInfo{TRACE_TID2NAME(TID), file, line} << outp; break;
115 970 : case TLVL_DEBUG: ::mf::LogDebug{TRACE_TID2NAME(TID), file, line} << outp; break;
116 0 : default: ::mf::LogDebug{TRACE_TID2NAME(TID), file, line} << std::to_string(lvl) << ": " << outp; break;
117 : # endif
118 : }
119 703 : }
120 :
121 : SUPPRESS_NOT_USED_WARN
122 1015 : static void mftrace_user(struct timeval* tvp, int TID, uint8_t lvl, const char* insert, const char* file, int line,
123 : const char* function, uint16_t nargs, const char* msg, ...)
124 : {
125 : va_list ap;
126 1015 : va_start(ap, msg);
127 1015 : if (mf::isMessageProcessingSetUp()) {
128 703 : vmftrace_user(tvp, TID, lvl, insert, file, line, nargs, msg, ap);
129 : } else {
130 312 : vtrace_user(tvp, TID, lvl, insert, file, line, function, nargs, msg, ap); // vtrace_user does not use file, line
131 : }
132 1015 : va_end(ap);
133 1015 : }
134 :
135 : # pragma GCC diagnostic push
136 : # pragma GCC diagnostic ignored "-Wvarargs"
137 : SUPPRESS_NOT_USED_WARN
138 0 : static void mftrace_user(struct timeval* tvp, int TID, uint8_t lvl, const char* insert, const char* file, int line,
139 : const char* function, uint16_t nargs, const std::string& msg, ...)
140 : {
141 : va_list ap;
142 0 : va_start(ap, msg);
143 0 : if (mf::isMessageProcessingSetUp()) {
144 0 : vmftrace_user(tvp, TID, lvl, insert, file, line, nargs, &msg[0], ap);
145 : } else {
146 0 : vtrace_user(tvp, TID, lvl, insert, file, line, function, nargs, &msg[0], ap); // vtrace_user does not use file, line
147 : }
148 0 : va_end(ap);
149 0 : } /* trace */
150 : # pragma GCC diagnostic pop
151 :
152 : inline TraceStreamer& operator<<(TraceStreamer& x, cet::exception r)
153 : {
154 : if (x.do_s || x.do_m) x.msg_append(r.what());
155 : return x;
156 : }
157 :
158 : #endif /* __cplusplus */
159 : #endif /* TRACEMF_H */
|