4 #include "cetlib/bold_fontify.h" 37 ELdestination::Category::Config::~Config() =
default;
39 ELdestination::Category::Config::Config()
54 return R
"(The 'limit' parameter is an integer after which the logger will start 55 to ignore messages of this category. Beyond the specified limit, an 56 occasional further message will appear, based on an exponential 57 fall-off. For example, if the limit is set to 5, and 100 messages of 58 this category are issued, then the destination containing this 59 configuration will log messages numbered 1, 2, 3, 4, 5, 10, 15, 25, 60 45, and 85. A limit of zero disables reporting any messages.)"; 66 return R
"(The 'reportEvery' parameter is an integer n which logs only every nth 67 message. If the value is zero or less, then the report-every feature 74 return R
"(The 'timespan' parameter is an integer representing seconds. When a 75 limit is set, one can also specify that if no occurrences for that 76 particular category of messages have been seen in a period of time 77 (the timespan), then the count toward that limit is to be reset. For 78 example, if one wish to suppress most of the thousands of warnings of 79 some category expected at startup, but would like to know if another 80 one happens after a gap of ten minutes, one can set the timespan value 81 to 600. A value of zero or less disables the timespan functionality.)"; 94 : previousTimestamp_{}
106 "The 'timestamp' parameter represents a format that can be " 108 "by strftime. Allowed values include:\n\n" 109 " - \"none\" (suppress timestamp printing)\n" 110 " - \"default\" (format string shown below)\n" 111 " - \"default_ms\" (use millisecond precision)\n" 112 " - any user-specified format interpretable by strftime"),
113 "%d-%b-%Y %H:%M:%S %Z"}
117 "'noLineBreaks' has been set to 'false'."},
135 auto const&
value = config.timestamp();
136 bool const use_timestamp = (
value !=
"none"s);
138 if (!use_timestamp) {
140 }
else if (
value ==
"default"s) {
143 }
else if (
value ==
"default_ms"s) {
145 timeFmt_ =
"%d-%b-%Y %H:%M:%S.%%03u %Z"s;
150 lineLength = config.noLineBreaks() ? 32000ull : config.lineLength();
165 return flags.test(FLAG);
171 size_t constexpr SIZE{144};
180 ts,
sizeof(ts),
timeFmt_.data(), localtime_r(&t.tv_sec, &timebuf));
186 tmpts,
sizeof(tmpts),
timeFmt_.data(), localtime_r(&t.tv_sec, &timebuf));
187 snprintf(ts,
sizeof(ts), tmpts, static_cast<unsigned>(t.tv_usec / 1000));
233 "The 'threshold' parameter specifies the lowest severity " 235 "messages that will be logged to the destination"},
240 R
"(The 'categories' parameter (if provided) is a FHiCL table that 241 configures the behavior of logging to this destination for the specified 242 category. For example, if the following appears in C++ source code: 244 mf::LogInfo{"Tracking"} << my_track.diagnostics(); 246 the category is 'Tracking', and its behavior can be specified via: 251 reportEvery: -1 # default 252 timespan: -1 # default 256 Within the 'categories' table, it is permitted to specify a 'default' 257 category, which becomes the configuration for all message categories 258 that are not explicitly listed. 260 Note the categories listed only customize the behavior of messages 261 that are logged specifically to this destination. Messages that are 262 routed to other destinations are not be affected. 277 ,
defaultLimit_{numeric_limits<decltype(defaultLimit_)>::max()}
285 ,
reset_{pset.msgStatistics().reset() ||
286 pset.msgStatistics().resetStatistics()}
289 vector<string> configuration_errors;
295 auto const default_category_name =
"default"s;
298 remove_if(
begin(categories),
end(categories), [](
auto const& category) {
299 return category ==
"default"s;
301 categories.erase(erase_from, categories.cend());
305 auto const& default_pset =
311 default_params().limit();
315 default_params().timespan();
318 string msg{
"Category: "s + cet::bold_fontify(
"default"s) +
"\n\n"s};
320 configuration_errors.push_back(std::move(msg));
326 for (
auto const& category : categories) {
333 string msg{
"Category: " + cet::bold_fontify(category) +
"\n\n"};
335 configuration_errors.push_back(std::move(msg));
338 if (category_params().limit() < 0) {
343 categoryParams_[category].reportEvery_ = category_params().reportEvery();
344 if (category_params().timespan() < 0) {
350 if (!configuration_errors.empty()) {
351 string msg{
"The following categories were misconfigured:\n\n"};
352 for (
auto const&
error : configuration_errors) {
362 if (c.substr(0, 4) !=
"Run:") {
368 is >> runWord >> run;
372 if (runWord !=
"Run:") {
377 is >> eventWord >> event;
381 if (eventWord !=
"Event:") {
385 os << run <<
"/" << event;
393 bool const preambleMode)
395 string const indent(6,
' ');
407 char const first = s[0];
408 char const second = (s.length() < 2) ?
'\0' : s[1];
409 char const last = (s.length() < 2) ?
'\0' : s[s.length() - 1];
410 char const last2 = (s.length() < 3) ?
'\0' : s[s.length() - 2];
428 if ((last ==
'\n') || (last2 ==
'\n')) {
449 auto const& xid = msg.
xid();
452 emitToken(oss, xid.severity().getSymbol(),
false,
true);
460 emitToken(oss,
"[serial #" + s.str() +
"] ",
false,
true);
462 bool needAspace =
true;
464 if (xid.module().length() + xid.subroutine().length() > 0) {
477 emitToken(oss, xid.module() +
" ",
false,
true);
484 emitToken(oss, xid.subroutine() +
"() ",
false,
true);
528 for (
auto const& val : msg.
items()) {
564 ostringstream payload;
586 for (
auto const& [xid, count] :
statsMap_) {
587 auto const& cat = xid.id();
592 s <<
" type category sev module subroutine " 594 <<
" ---- -------------------- -- ---------------- " 595 "---------------- ----- -----\n";
601 <<
right << setw(5) << ++
n 604 <<
left << setw(20) << cat.substr(0, 20)
607 <<
left << setw(2) << xid.severity().getSymbol()
610 <<
left << setw(16) << xid.module().substr(0, 16)
614 << xid.subroutine().substr(0, 16)
616 <<
right << setw(7) << count.n_ <<
left << setw(1)
617 << (count.ignoredFlag_ ?
'*' :
' ')
619 <<
right << setw(8) << count.aggregateN_ <<
'\n';
620 ftnote = ftnote || count.ignoredFlag_;
623 p3[xid.severity().getLevel()].n += count.n_;
624 p3[xid.severity().getLevel()].t += count.aggregateN_;
629 s <<
"\n* Some occurrences of this message were suppressed in all " 630 "logs, due to limits.\n";
635 for (
auto const& pr : statsMap_) {
636 auto const& xid = pr.first;
637 auto const& count = pr.second;
638 string const& cat = xid.id();
641 <<
" type category Examples: run/evt run/evt " 643 <<
" ---- -------------------- ---------------- ---------------- " 644 "----------------\n";
648 <<
right << setw(5) << ++
n 651 <<
left << setw(20) << cat
654 <<
left << setw(16) << count.context1_.c_str()
657 <<
left << setw(16) << count.context2_.c_str()
660 << count.contextLast_ <<
'\n';
665 <<
"Severity # Occurrences Total Occurrences\n" 666 <<
"-------- ------------- -----------------\n";
668 if (p3[k].
n != 0 || p3[k].t != 0) {
677 <<
right << setw(20) << p3[k].t <<
'\n';
689 ostringstream payload;
690 payload <<
"\n=============================================\n\n" 691 <<
"MessageLogger Summary\n" 718 msg <<
"Call to unimplemented flush()!";
738 auto const& cp = cp_iter->second;
755 time_t now = time(0);
774 if (limiter.
limit_ == 0) {
786 long r = diff / limiter.
limit_;
787 if (r * limiter.
limit_ != diff) {
fhicl::Table< MsgFormatSettings::Config > format
ELseverityLevel severity() const
fhicl::Atom< bool > resetStatistics
virtual void fillUsrMsg(std::ostringstream &, mf::ErrorObj const &msg)
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
bool skipMsg(ELextendedID const &)
static std::string limit_comment()
static std::string const value
timeval timestamp() const
fhicl::TableFragment< MsgStatistics::Config > msgStatistics
void add(std::string const &context, bool reactedTo)
void emitToken(std::ostream &os, std::string const &s, bool nl=false, bool preambleMode=false)
fhicl::OptionalDelegatedParameter categories
virtual void fillSuffix(std::ostringstream &, mf::ErrorObj const &msg)
std::map< std::string const, CategoryParams > categoryParams_
virtual void log(mf::ErrorObj &)
fhicl::Atom< int > timespan
std::list< std::string > const & items() const
static std::string timespan_comment()
std::string const & context() const
fhicl::Atom< std::string > threshold
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
fhicl::Atom< int > reportEvery
std::string const & idOverflow() const
std::vector< std::string > get_pset_names() const
std::map< ELextendedID const, StatsCount > statsMap_
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
std::string summarizeContext(std::string const &)
ELslProxy< ELzeroSeverityGen > constexpr ELzeroSeverity
ELextendedID const & xid() const
static std::string reportEvery_comment()
ELslProxy< ELwarningGen > constexpr ELwarning
T get(std::string const &key) const
std::string indent(std::size_t const i)
std::string const & filename() const
ELdestination(Config const &)
ELseverityLevel threshold_
std::string const & id() const
fhicl::Atom< bool > outputStatistics
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
char const * what() const noexcept override
std::string formSummary()
std::optional< T > get_if_present(std::string const &key) const
virtual void fillPrefix(std::ostringstream &, mf::ErrorObj const &msg)
virtual void setReactedTo(bool)
MsgFormatSettings format_
void setThreshold(ELseverityLevel sv)
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
std::map< ELextendedID const, XidLimiter > xidLimiters_
time_t previousTimestamp_
second_as<> second
Type of time stored in seconds, in double precision.
std::string nl(std::size_t i=1)
virtual void routePayload(std::ostringstream const &, mf::ErrorObj const &msg)
Event finding and building.