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