5#include "GaudiKernel/IAppMgrUI.h"
6#include "GaudiKernel/IIncidentSvc.h"
7#include "GaudiKernel/ITHistSvc.h"
8#include "GaudiKernel/Message.h"
9#include "GaudiKernel/StatusCode.h"
10#include "GaudiKernel/System.h"
24 "WARNING",
"ERROR",
"FATAL",
"ALWAYS"};
28 size_t msgHash(
const Message&
msg)
30 std::string
s =
msg.getSource() +
msg.getMessage();
31 s.erase(
std::remove_if(
s.begin(),
s.end(), [](
char c) { return std::isdigit(c); }),
s.end());
32 return std::hash<std::string>()(
s);
37 base_class(name, svcloc)
39 m_outputLevel.declareUpdateHandler([svcloc](Gaudi::Details::PropertyBase&) {
40 SmartIF<IAppMgrUI> app = svcloc;
41 if (app) app->outputLevelUpdate();
44 for (
int ic = 0; ic < MSG::NUM_LEVELS; ++ic) {
54 StatusCode
sc = Service::initialize();
55 if (
sc.isFailure())
return sc;
58 sc = incSvc.retrieve();
60 reportMessage(name(), MSG::WARNING,
"Cannot find IncidentSvc");
69 std::cout <<
"TrigMessageSvc WARNING: Colors are not supported by TrigMessageSvc" << std::endl;
71 return StatusCode::SUCCESS;
76 m_state = Gaudi::StateMachine::OFFLINE;
78 if (
sc.isSuccess() ) m_state = Gaudi::StateMachine::INITIALIZED;
87 return StatusCode::SUCCESS;
95 reportMessage(name(), MSG::INFO,
"Disabling asynchronous message reporting");
101 return StatusCode::SUCCESS;
107 reportMessage(name(), MSG::INFO,
"Enabling asynchronous message reporting");
115 if ( histSvc.retrieve().isFailure() ) {
116 reportMessage(name(), MSG::WARNING,
"Cannot find THistSvc. Message stats will not be published.");
122 const std::string path =
"/EXPERT/HLTFramework/" + name() +
"/";
124 m_msgCountHist =
new TH1I(
"MessageCount",
"Messages while RUNNING;Severity;Count",
125 nLevelBins, 0, nLevelBins);
127 const int nSrcBins = 1;
128 m_msgCountSrcHist =
new TH2I(
"MessageCountBySource",
"Messages while RUNNING;Severity;Source",
129 nLevelBins, 0, nLevelBins, nSrcBins, 0, nSrcBins);
137 reportMessage(name(), MSG::WARNING,
"Cannot register monitoring histogram 'MessageCount'");
140 reportMessage(name(), MSG::WARNING,
"Cannot register monitoring histogram 'MessageCountBySource'");
149 if (prop.name() ==
"alwaysLimit") {
150 Gaudi::Property<int>* p =
dynamic_cast<Gaudi::Property<int>*
>(&prop);
151 if (p && p->value() != 0) {
152 std::cout <<
"TrigMessageSvc ERROR: cannot suppress ALWAYS messages" << std::endl;
156 else if (prop.name() ==
"defaultLimit") {
157 for (
int i = MSG::VERBOSE; i < MSG::NUM_LEVELS; ++i) {
158 if (i != MSG::ALWAYS) {
163 else if (prop.name() !=
"fatalLimit" && prop.name() !=
"errorLimit" &&
164 prop.name() !=
"warningLimit" && prop.name() ==
"infoLimit" &&
165 prop.name() ==
"debugLimit" && prop.name() ==
"verboseLimit") {
166 std::cout <<
"TrigMessageSvc ERROR: Unknown message limit parameter: " << prop.name()
174 static const std::array<std::pair<const char*, MSG::Level>, 7> tbl{{{
"setFatal", MSG::FATAL},
175 {
"setError", MSG::ERROR},
176 {
"setWarning", MSG::WARNING},
177 {
"setInfo", MSG::INFO},
178 {
"setDebug", MSG::DEBUG},
179 {
"setVerbose", MSG::VERBOSE},
180 {
"setAlways", MSG::ALWAYS}}};
182 auto i = std::find_if(
183 std::begin(tbl), std::end(tbl),
184 [&](
const std::pair<const char*, MSG::Level>& t) {
return prop.name() == t.first; });
185 if (i == std::end(tbl)) {
186 std::cerr <<
"TrigMessageSvc ERROR: Unknown message threshold parameter: " << prop.name()
192 Gaudi::Property<std::vector<std::string>>* sap =
193 dynamic_cast<Gaudi::Property<std::vector<std::string>
>*>(&prop);
195 std::cerr <<
"could not dcast " << prop.name()
196 <<
" to a Gaudi::Property<std::vector<std::string>> (which it "
208 std::ostringstream os;
211 os <<
"Summarizing all message counts"
215 os <<
"Listing sources of suppressed message: " << std::endl;
218 os <<
"=====================================================" << std::endl;
219 os <<
" Message Source | Level | Count" << std::endl;
220 os <<
"-----------------------------+---------+-------------" << std::endl;
225 for (
unsigned int ic = 0; ic < MSG::NUM_LEVELS; ++ic) {
230 os.setf(std::ios_base::left, std::ios_base::adjustfield);
235 os.setf(std::ios_base::right, std::ios_base::adjustfield);
240 os << itr->second.msg[ic];
247 os <<
"=====================================================" << std::endl;
252 return StatusCode::SUCCESS;
271 std::function<void()> action;
284 const int key =
msg.getType();
287 const Message* cmsg = &
msg;
289 std::unique_ptr<Message> newMessage;
300 if (nmsg > msgLimit) doPrint =
false;
301 if (nmsg == msgLimit) {
302 std::string txt =
levelNames[key] +
" message limit (" + std::to_string(msgLimit) +
303 ") reached for " +
msg.getSource() +
". Suppressing further output.";
304 newMessage = std::make_unique<Message>(
msg.getSource(), MSG::WARNING, std::move(txt));
305 cmsg = newMessage.get();
309 else if (msgLimit < 0) {
311 const unsigned int mh = msgHash(*cmsg);
320 if (nmsg == abs(msgLimit)) {
321 std::ostringstream os;
322 os <<
msg.getMessage() <<
" [Message limit (" << abs(msgLimit)
323 <<
") reached. Log-suppression of further output.]";
324 newMessage = std::make_unique<Message>(
msg.getSource(),
msg.getType(), os.str());
325 cmsg = newMessage.get();
327 else if (nmsg > abs(msgLimit)) {
328 const int everyNth = (int)exp10((
int)log10(nmsg));
329 if ((nmsg % everyNth) == 0) {
330 std::ostringstream os;
331 os <<
msg.getMessage() <<
" [suppressed " << everyNth <<
" similar messages]";
332 newMessage = std::make_unique<Message>(
msg.getSource(),
msg.getType(), os.str());
333 cmsg = newMessage.get();
348 (*m_defaultStream) << *cmsg << std::endl << std::flush;
384 const char* filename =
msg.getSource().c_str();
385 const char* function_name =
"";
386 const int line_number = msgHash(
msg);
388 ers::LocalContext hlt_context_info(
package_name, filename, line_number, function_name);
398 std::ostringstream oss;
400 ers::HLTMessage ersMsg(hlt_context_info, oss.str());
401 ersMsg.add_qualifier(
"HLT");
404 switch (
msg.getType()) {
405 case MSG::NIL:
break;
406 case MSG::VERBOSE: ers::debug(ersMsg, 2);
break;
407 case MSG::DEBUG: ers::debug(ersMsg, 1);
break;
408 case MSG::INFO: ers::info(ersMsg);
break;
409 case MSG::WARNING: ers::warning(ersMsg);
break;
410 case MSG::ERROR: ers::error(ersMsg);
break;
411 case MSG::FATAL: ers::fatal(ersMsg);
break;
413 std::ostringstream oss;
414 oss <<
"Unknown message severity level: " <<
msg.getType() <<
" Original message was: " << m;
415 ers::error(ers::HLTMessage(ERS_HERE, oss.str()));
431 return m_outputLevel;
438 return it !=
m_thresholdMap.end() ? it->second : m_outputLevel.value();
443 m_outputLevel = new_level;
454 }
else if ( i->second != level ) {
465 const std::vector<std::string>& filter)
const
467 if (filter.empty())
return false;
468 auto it = filter.begin();
469 if (filter.size() == 1 && (*it) ==
"*")
return true;
472 for (; it != filter.end(); ++it) {
473 if ((*it) ==
"*") pass =
true;
474 if (source == (*it))
return true;
475 if (
"!" + source == (*it))
return false;
484 const EventContext::ContextID_t slot =
msg.getEventSlot();
485 const EventContext::ContextEvt_t evt =
msg.getEventNumber();
490 if ( itr->second.first != evt ) {
491 itr->second = {evt,
MsgAry()};
495 const int N = ++itr->second.second.msg[
msg.getType()];
static constexpr std::string levelNames[MSG::NUM_LEVELS]
virtual void lock()=0
Interface to allow an object to lock itself when made const in SG.
OH histogram lock header file.
static const std::string & type()
Incident type.
bool passErsFilter(const std::string &source, const std::vector< std::string > &filter) const
Gaudi::Property< std::string > m_ersFormat
tbb::concurrent_bounded_queue< std::function< void()> > m_messageActionsQueue
void setupLimits(Gaudi::Details::PropertyBase &prop)
virtual int outputLevel() const override
virtual StatusCode finalize() override
void i_reportMessage(const Message &msg, int outputLevel)
Internal implementation of reportMessage(const Message&,int) without lock.
bool passErsLimit(const Message &msg)
std::array< Gaudi::Property< int >, MSG::NUM_LEVELS > m_msgLimit
virtual StatusCode start() override
Gaudi::Property< std::string > m_defaultTimeFormat
std::map< std::string, MsgAry > m_sourceMap
counts per source
std::map< size_t, unsigned int > m_msgHashCount
counts per message hash
std::array< Gaudi::Property< std::vector< std::string > >, MSG::NUM_LEVELS > m_thresholdProp
std::unordered_map< EventContext::ContextID_t, std::pair< EventContext::ContextEvt_t, MsgAry > > m_slotMsgCount
counts per slot and level
std::array< Gaudi::Property< std::vector< std::string > >, MSG::NUM_LEVELS > m_useERS
Special properties to control output to ERS of individual sources.
Gaudi::Property< bool > m_color
std::recursive_mutex m_thresholdMapMutex
virtual void reportMessage(const Message &message) override
TH1I * m_msgCountHist
Message counting per level histogram.
void i_reportERS(const Message &msg) const
Report message to online messaging system (ERS).
bool m_doPublish
are we publishing message statistics?
Gaudi::Property< std::string > m_defaultFormat
ThresholdMap m_thresholdMap
Output level threshold map.
void setupThreshold(Gaudi::Details::PropertyBase &prop)
Gaudi::Property< bool > m_stats
virtual StatusCode stop() override
Gaudi::Property< bool > m_suppressRunningOnly
virtual int messageCount(MSG::Level logLevel) const override
bool m_doSuppress
is suppression currently enabled?
TH2I * m_msgCountSrcHist
Message counting per message source.
Gaudi::Property< int > m_ersEventLimit
Gaudi::Property< unsigned int > m_statLevel
virtual void setOutputLevel(int new_level) override
std::array< int, MSG::NUM_LEVELS > m_msgCount
counts per level
virtual StatusCode reinitialize() override
virtual void handle(const Incident &incident) override
Gaudi::Property< unsigned int > m_eventIDLevel
Gaudi::Property< bool > m_suppress
std::thread m_thread
Thread for asynchronous reporting.
Gaudi::Property< unsigned int > m_publishLevel
virtual StatusCode initialize() override
TrigMessageSvc(const std::string &name, ISvcLocator *svcloc)
Scoped lock to be used for threaded histogram operations.
static char * package_name
DataModel_detail::iterator< DVL > remove_if(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end, Predicate pred)
Specialization of remove_if for DataVector/List.
Private helper class to keep the count of messages of a type (MSG::LEVEL).