4 #include <QProgressDialog>
6 #include "cetlib/filepath_maker.h"
7 #include "fhiclcpp/make_ParameterSet.h"
8 #include "fhiclcpp/ParameterSet.h"
10 #include "mfextensions/Binaries/mvdlg.hh"
17 process_fname(std::string& fname)
19 size_t sub_start = fname.find(
"${");
20 size_t sub_end = fname.find(
"}");
22 const size_t npos = std::string::npos;
24 if ((sub_start == npos && sub_end != npos)
25 || (sub_start != npos && sub_end == npos)
26 || (sub_start > sub_end))
28 throw std::runtime_error(
"Unrecognized configuration file. Use default configuration instead.");
31 if (sub_start == npos)
return;
33 std::string env = std::string(getenv(fname.substr(sub_start + 2, sub_end - sub_start - 2).c_str()));
34 fname.replace(sub_start, sub_end - sub_start + 1, env);
39 static fhicl::ParameterSet
40 readConf(std::string
const& fname)
42 if (fname.empty())
return fhicl::ParameterSet();
44 std::string filename = fname;
45 process_fname(filename);
47 std::string env(
"FHICL_FILE_PATH=");
49 if (filename[0] ==
'/')
58 char* mfe_path = getenv(
"MFEXTENSIONS_DIR");
59 if (mfe_path) env.append(
":").append(mfe_path).append(
"/config");
61 putenv((
char *)env.c_str());
65 cet::filepath_lookup policy(
"FHICL_FILE_PATH");
68 fhicl::ParameterSet pset;
69 fhicl::make_ParameterSet(filename, policy, pset);
74 msgViewerDlg::msgViewerDlg(std::string
const& conf, QDialog* parent)
90 , sup_menu(new QMenu(this))
91 , thr_menu(new QMenu(this))
92 , receivers_(readConf(conf).get<fhicl::ParameterSet>(
"receivers", fhicl::ParameterSet()))
100 fhicl::ParameterSet pset = readConf(conf);
106 btnSuppression->setMenu(sup_menu);
107 btnThrottling->setMenu(thr_menu);
110 connect(btnPause, SIGNAL(clicked()),
this, SLOT(pause()));
111 connect(btnExit, SIGNAL(clicked()),
this, SLOT(exit()));
112 connect(btnClear, SIGNAL(clicked()),
this, SLOT(clear()));
114 connect(btnRMode, SIGNAL(clicked()),
this, SLOT(renderMode()));
115 connect(btnDisplayMode, SIGNAL(clicked()),
this, SLOT(shortMode()));
117 connect(btnSearch, SIGNAL(clicked()),
this, SLOT(searchMsg()));
118 connect(btnSearchClear,
119 SIGNAL(clicked()),
this, SLOT(searchClear()));
121 connect(btnFilter, SIGNAL(clicked()),
this, SLOT(setFilter()));
123 connect(btnError, SIGNAL(clicked()),
this, SLOT(setSevError()));
124 connect(btnWarning, SIGNAL(clicked()),
this, SLOT(setSevWarning()));
125 connect(btnInfo, SIGNAL(clicked()),
this, SLOT(setSevInfo()));
126 connect(btnDebug, SIGNAL(clicked()),
this, SLOT(setSevDebug()));
129 , SIGNAL(triggered(QAction*))
131 , SLOT(setSuppression(QAction*)));
134 , SIGNAL(triggered(QAction*))
136 , SLOT(setThrottling(QAction*)));
139 , SIGNAL(valueChanged(
int))
141 , SLOT(changeSeverity(
int)));
144 , SIGNAL(newMessage(mf::MessageFacilityMsg
const &))
146 , SLOT(onNewMsg(mf::MessageFacilityMsg
const &)));
148 connect(tabWidget, SIGNAL(currentChanged(
int)),
this, SLOT(tabWidgetCurrentChanged(
int)));
149 connect(tabWidget, SIGNAL(tabCloseRequested(
int)),
this, SLOT(tabCloseRequested(
int)));
150 MsgFilterDisplay allMessages;
151 allMessages.txtDisplay = txtMessages;
152 msgFilters_.push_back(allMessages);
155 QTabBar *tabBar = tabWidget->findChild<QTabBar *>();
156 tabBar->setTabButton(0, QTabBar::RightSide, 0);
157 tabBar->setTabButton(0, QTabBar::LeftSide, 0);
159 if (simpleRender) btnRMode->setChecked(
true);
160 else btnRMode->setChecked(
false);
162 btnRMode->setEnabled(
false);
164 changeSeverity(sevThresh);
166 QTextDocument* doc =
new QTextDocument(txtMessages);
167 txtMessages->setDocument(doc);
172 msgViewerDlg::~msgViewerDlg()
178 static void str_to_suppress(std::vector<std::string>
const& vs, std::vector<suppress>& s, QMenu* menu)
184 act = menu->addAction(
"None");
185 act->setEnabled(
false);
189 s.reserve(vs.size());
191 for (
size_t i = 0; i < vs.size(); ++i)
194 act = menu->addAction(QString(vs[i].c_str()));
195 act->setCheckable(
true);
196 act->setChecked(
true);
197 QVariant v = qVariantFromValue((
void*)&s[i]);
202 static void pset_to_throttle(std::vector<fhicl::ParameterSet>
const& ps, std::vector<throttle>& t, QMenu* menu)
208 act = menu->addAction(
"None");
209 act->setEnabled(
false);
213 t.reserve(ps.size());
215 for (
size_t i = 0; i < ps.size(); ++i)
217 std::string name = ps[i].get<std::string>(
"name");
219 , ps[i].get<int>(
"limit", -1)
220 , ps[i].get<long>(
"timespan", -1)));
221 act = menu->addAction(QString(name.c_str()));
222 act->setCheckable(
true);
223 act->setChecked(
true);
224 QVariant v = qVariantFromValue((
void*)&t[i]);
229 void msgViewerDlg::parseConf(fhicl::ParameterSet
const& conf)
231 fhicl::ParameterSet nulp;
235 fhicl::ParameterSet sup = conf.get<fhicl::ParameterSet>(
"suppress", nulp);
237 auto sup_host = sup.get<std::vector<std::string>>(
"hosts", std::vector<std::string>());
238 auto sup_app = sup.get<std::vector<std::string>>(
"applications", std::vector<std::string>());
239 auto sup_cat = sup.get<std::vector<std::string>>(
"categories", std::vector<std::string>());
241 str_to_suppress(sup_host, e_sup_host, sup_menu);
242 sup_menu->addSeparator();
244 str_to_suppress(sup_app, e_sup_app, sup_menu);
245 sup_menu->addSeparator();
247 str_to_suppress(sup_cat, e_sup_cat, sup_menu);
250 auto thr = conf.get<fhicl::ParameterSet>(
"throttle", nulp);
252 auto thr_host = thr.get<std::vector<fhicl::ParameterSet>>(
"hosts", std::vector<fhicl::ParameterSet>());
253 auto thr_app = thr.get<std::vector<fhicl::ParameterSet>>(
"applications", std::vector<fhicl::ParameterSet>());
254 auto thr_cat = thr.get<std::vector<fhicl::ParameterSet>>(
"categories", std::vector<fhicl::ParameterSet>());
256 pset_to_throttle(thr_host, e_thr_host, thr_menu);
257 thr_menu->addSeparator();
259 pset_to_throttle(thr_app, e_thr_app, thr_menu);
260 thr_menu->addSeparator();
262 pset_to_throttle(thr_cat, e_thr_cat, thr_menu);
264 auto lvl = conf.get<std::string>(
"threshold",
"INFO");
265 if (lvl ==
"DEBUG" || lvl ==
"debug" || lvl ==
"0") { sevThresh = SDEBUG; }
266 if (lvl ==
"INFO" || lvl ==
"info" || lvl ==
"1") { sevThresh = SINFO; }
267 if (lvl ==
"WARN" || lvl ==
"warn" || lvl ==
"2") { sevThresh = SWARNING; }
268 if (lvl ==
"ERROR" || lvl ==
"error" || lvl ==
"3") { sevThresh = SERROR; }
271 bool msgViewerDlg::msg_throttled(mf::MessageFacilityMsg
const& mfmsg)
277 for (
size_t i = 0; i < e_sup_host.size(); ++i)
278 if (e_sup_host[i].match(mfmsg.hostname()))
281 for (
size_t i = 0; i < e_sup_app.size(); ++i)
282 if (e_sup_app[i].match(mfmsg.application()))
285 for (
size_t i = 0; i < e_sup_cat.size(); ++i)
286 if (e_sup_cat[i].match(mfmsg.category()))
295 for (
size_t i = 0; i < e_thr_host.size(); ++i)
296 if (e_thr_host[i].reach_limit(mfmsg.hostname(), mfmsg.timestamp()))
299 for (
size_t i = 0; i < e_thr_app.size(); ++i)
300 if (e_thr_app[i].reach_limit(mfmsg.application(), mfmsg.timestamp()))
303 for (
size_t i = 0; i < e_thr_cat.size(); ++i)
304 if (e_thr_cat[i].reach_limit(mfmsg.category(), mfmsg.timestamp()))
312 void msgViewerDlg::writeSettings()
314 QSettings settings(
"ARTDAQ",
"MsgViewer");
316 settings.beginGroup(
"MainWindow");
317 settings.setValue(
"size", size());
318 settings.setValue(
"pos", pos());
322 void msgViewerDlg::readSettings()
324 QSettings settings(
"ARTDAQ",
"MsgViewer");
326 settings.beginGroup(
"MainWindow");
327 QPoint pos = settings.value(
"pos", QPoint(100, 100)).toPoint();
328 QSize size = settings.value(
"size", QSize(660, 760)).toSize();
334 void msgViewerDlg::onNewMsg(mf::MessageFacilityMsg
const& mfmsg)
341 lcdMsgs->display(nMsgs);
344 if (msg_throttled(mfmsg))
346 lcdSuppressionCount->display(nSupMsgs);
347 lcdThrottlingCount->display(nThrMsgs);
352 msg_pool_.emplace_back(mfmsg);
353 msgs_t::iterator it = --msg_pool_.end();
356 unsigned int flag = update_index(it);
359 if (flag & LIST_APP) updateList<msg_iters_map_t>(lwApplication, app_msgs_);
360 if (flag & LIST_CAT) updateList<msg_iters_map_t>(lwCategory, cat_msgs_);
361 if (flag & LIST_HOST) updateList<msg_iters_map_t>(lwHost, host_msgs_);
363 for (
size_t d = 0; d < msgFilters_.size(); ++d)
365 bool hostMatch = msgFilters_[d].hostFilter.contains(it->host(), Qt::CaseInsensitive) || msgFilters_[d].hostFilter.size() == 0;
366 bool appMatch = msgFilters_[d].appFilter.contains(it->app(), Qt::CaseInsensitive) || msgFilters_[d].appFilter.size() == 0;
367 bool catMatch = msgFilters_[d].catFilter.contains(it->cat(), Qt::CaseInsensitive) || msgFilters_[d].catFilter.size() == 0;
370 if (hostMatch && appMatch && catMatch)
372 msgFilters_[d].msgs.push_back(it);
378 unsigned int msgViewerDlg::update_index(msgs_t::iterator it)
380 QString
const& app = it->app();
381 QString
const& cat = it->cat();
382 QString
const& host = it->host();
384 unsigned int update = 0x0;
386 if (cat_msgs_.find(cat) == cat_msgs_.end()) update |= LIST_CAT;
387 if (host_msgs_.find(host) == host_msgs_.end()) update |= LIST_HOST;
388 if (app_msgs_.find(app) == app_msgs_.end()) update |= LIST_APP;
390 cat_msgs_[cat].push_back(it);
391 host_msgs_[host].push_back(it);
392 app_msgs_[app].push_back(it);
398 void msgViewerDlg::displayMsg(msgs_t::const_iterator it,
int display)
400 if (it->sev() < sevThresh)
return;
402 msgFilters_[display].nDisplayMsgs++;
403 if (display == tabWidget->currentIndex())
405 lcdDisplayedMsgs->display(msgFilters_[display].nDisplayMsgs);
408 auto txt = it->text(shortMode_);
409 msgFilters_[display].txtDisplay->append(txt);
410 msgFilters_[display].txtDisplay->moveCursor(QTextCursor::End);
413 void msgViewerDlg::displayMsg(
int display)
416 msgFilters_[display].txtDisplay->clear();
417 msgFilters_[display].nDisplayMsgs = 0;
419 msg_iters_t::const_iterator it;
421 n = msgFilters_[display].msgs.size();
422 it = msgFilters_[display].msgs.begin();
423 QProgressDialog progress(
"Fetching data...",
"Cancel"
424 , 0, n / 1000,
this);
426 progress.setWindowModality(Qt::WindowModal);
427 progress.setMinimumDuration(2000);
434 for (; it != msgFilters_[display].msgs.end(); ++it, ++i)
436 if (it->get()->sev() >= sevThresh)
438 txt += it->get()->text(shortMode_);
439 ++msgFilters_[display].nDisplayMsgs;
446 progress.setValue(prog);
448 msgFilters_[display].txtDisplay->append(txt);
452 if (progress.wasCanceled())
456 if (display == tabWidget->currentIndex())
458 lcdDisplayedMsgs->display(msgFilters_[display].nDisplayMsgs);
461 msgFilters_[display].txtDisplay->append(txt);
462 msgFilters_[display].txtDisplay->moveCursor(QTextCursor::End);
467 void msgViewerDlg::updateDisplays()
469 for (
size_t ii = 0; ii < msgFilters_.size(); ++ii)
475 template <
typename M>
476 bool msgViewerDlg::updateList(QListWidget* lw, M
const& map)
478 bool nonSelectedBefore = (lw->currentRow() == -1);
479 bool nonSelectedAfter =
true;
481 QString item = nonSelectedBefore ?
"" : lw->currentItem()->text();
485 typename M::const_iterator it = map.begin();
487 while (it != map.end())
489 lw->addItem(it->first);
490 if (!nonSelectedBefore && nonSelectedAfter)
492 if (item == it->first)
494 lw->setCurrentRow(row);
495 nonSelectedAfter =
false;
502 if (!nonSelectedBefore && nonSelectedAfter)
return true;
507 msg_iters_t msgViewerDlg::list_intersect(msg_iters_t
const& l1, msg_iters_t
const& l2)
510 msg_iters_t::const_iterator it1 = l1.begin();
511 msg_iters_t::const_iterator it2 = l2.begin();
513 while (it1 != l1.end() && it2 != l2.end())
515 if (*it1 < *it2) { ++it1; }
516 else if (*it2 < *it1) { ++it2; }
519 output.push_back(*it1);
525 TRACE(10,
"list_intersect: output list has %zu entries", output.size());
529 std::string sev_to_string(sev_code_t s)
545 void msgViewerDlg::setFilter()
547 auto hostFilter = toQStringList(lwHost->selectedItems());
548 auto appFilter = toQStringList(lwApplication->selectedItems());
549 auto catFilter = toQStringList(lwCategory->selectedItems());
551 lwHost->setCurrentRow(-1, QItemSelectionModel::Clear);
552 lwApplication->setCurrentRow(-1, QItemSelectionModel::Clear);
553 lwCategory->setCurrentRow(-1, QItemSelectionModel::Clear);
555 if (hostFilter.isEmpty()
556 && appFilter.isEmpty()
557 && catFilter.isEmpty())
563 QString catFilterExpression =
"";
564 QString hostFilterExpression =
"";
565 QString appFilterExpression =
"";
568 for (
auto app = 0; app < appFilter.size(); ++app)
570 msg_iters_map_t::const_iterator it = app_msgs_.find(appFilter[app]);
571 appFilterExpression += QString(first ?
"" :
" || ") + appFilter[app];
573 if (it != app_msgs_.end())
575 msg_iters_t temp(it->second);
576 TRACE(10,
"setFilter: app " + appFilter[app].toStdString() +
" has %zu messages", temp.size());
580 TRACE(10,
"setFilter: result contains %zu messages", result.size());
583 if (!hostFilter.isEmpty())
585 msg_iters_t hostResult;
586 for (
auto host = 0; host < hostFilter.size(); ++host)
588 hostFilterExpression += QString(first ?
"" :
" || ") + hostFilter[host];
590 msg_iters_map_t::const_iterator it = host_msgs_.find(hostFilter[host]);
591 if (it != host_msgs_.end())
593 msg_iters_t temp(it->second);
594 TRACE(10,
"setFilter: host " + hostFilter[host].toStdString() +
" has %zu messages", temp.size());
595 hostResult.merge(temp);
598 if (result.empty()) { result = hostResult; }
599 else { result = list_intersect(result, hostResult); }
600 TRACE(10,
"setFilter: result contains %zu messages", result.size());
604 if (!catFilter.isEmpty())
606 msg_iters_t catResult;
607 for (
auto cat = 0; cat < catFilter.size(); ++cat)
609 catFilterExpression += QString(first ?
"" :
" || ") + catFilter[cat];
611 msg_iters_map_t::const_iterator it = cat_msgs_.find(catFilter[cat]);
612 if (it != cat_msgs_.end())
614 msg_iters_t temp(it->second);
615 TRACE(10,
"setFilter: cat " + catFilter[cat].toStdString() +
" has %zu messages", temp.size());
616 catResult.merge(temp);
619 if (result.empty()) { result = catResult; }
620 else { result = list_intersect(result, catResult); }
621 TRACE(10,
"setFilter: result contains %zu messages", result.size());
625 auto nFilterExpressions = (appFilterExpression !=
"" ? 1 : 0) + (hostFilterExpression !=
"" ? 1 : 0) + (catFilterExpression !=
"" ? 1 : 0);
626 QString filterExpression =
"";
627 if (nFilterExpressions == 1)
629 filterExpression = catFilterExpression + hostFilterExpression + appFilterExpression;
633 filterExpression =
"(" + (catFilterExpression !=
"" ? catFilterExpression +
") && (" :
"")
634 + hostFilterExpression
635 + (hostFilterExpression !=
"" && appFilterExpression !=
"" ?
") && (" :
"")
636 + appFilterExpression +
")";
641 auto newTabTitle = QString(
"Filter ") + QString::number(++nFilters);
642 QWidget* newTab =
new QWidget();
644 QTextEdit* txtDisplay =
new QTextEdit(newTab);
645 QTextDocument* doc =
new QTextDocument(txtDisplay);
646 txtDisplay->setDocument(doc);
648 QVBoxLayout* layout =
new QVBoxLayout();
649 layout->addWidget(txtDisplay);
650 layout->setContentsMargins(0, 0, 0, 0);
651 newTab->setLayout(layout);
653 MsgFilterDisplay filteredMessages;
654 filteredMessages.msgs = result;
655 filteredMessages.hostFilter = hostFilter;
656 filteredMessages.appFilter = appFilter;
657 filteredMessages.catFilter = catFilter;
658 filteredMessages.txtDisplay = txtDisplay;
659 filteredMessages.nDisplayMsgs = result.size();
660 msgFilters_.push_back(filteredMessages);
662 tabWidget->addTab(newTab, newTabTitle);
663 tabWidget->setTabToolTip(tabWidget->count() - 1, filterExpression);
664 tabWidget->setCurrentIndex(tabWidget->count() - 1);
666 displayMsg(msgFilters_.size() - 1);
669 void msgViewerDlg::pause()
674 btnPause->setText(
"Resume");
680 btnPause->setText(
"Pause");
684 void msgViewerDlg::exit()
689 void msgViewerDlg::clear()
691 int ret = QMessageBox::question(
this, tr(
"Message Viewer"), tr(
"Are you sure you want to clear all received messages?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
694 case QMessageBox::Yes:
702 updateList<msg_iters_map_t>(lwApplication, app_msgs_);
703 updateList<msg_iters_map_t>(lwCategory, cat_msgs_);
704 updateList<msg_iters_map_t>(lwHost, host_msgs_);
705 for (
auto& display : msgFilters_)
707 display.txtDisplay->clear();
708 display.msgs.clear();
709 display.nDisplayMsgs = 0;
712 lcdMsgs->display(nMsgs);
713 lcdDisplayedMsgs->display(0);
715 case QMessageBox::No:
721 void msgViewerDlg::shortMode()
726 btnDisplayMode->setText(
"Long View");
731 btnDisplayMode->setText(
"Compact View");
736 void msgViewerDlg::changeSeverity(
int sev)
752 default: setSevDebug();
758 void msgViewerDlg::setSevError()
761 btnError->setChecked(
true);
762 btnWarning->setChecked(
false);
763 btnInfo->setChecked(
false);
764 btnDebug->setChecked(
false);
765 vsSeverity->setValue(sevThresh);
768 void msgViewerDlg::setSevWarning()
770 sevThresh = SWARNING;
771 btnError->setChecked(
false);
772 btnWarning->setChecked(
true);
773 btnInfo->setChecked(
false);
774 btnDebug->setChecked(
false);
775 vsSeverity->setValue(sevThresh);
778 void msgViewerDlg::setSevInfo()
781 btnError->setChecked(
false);
782 btnWarning->setChecked(
false);
783 btnInfo->setChecked(
true);
784 btnDebug->setChecked(
false);
785 vsSeverity->setValue(sevThresh);
788 void msgViewerDlg::setSevDebug()
791 btnError->setChecked(
false);
792 btnWarning->setChecked(
false);
793 btnInfo->setChecked(
false);
794 btnDebug->setChecked(
true);
795 vsSeverity->setValue(sevThresh);
798 void msgViewerDlg::renderMode()
800 simpleRender = !simpleRender;
804 btnRMode->setChecked(
true);
805 for (
auto display : msgFilters_)
807 display.txtDisplay->setPlainText(display.txtDisplay->toPlainText());
812 btnRMode->setChecked(
false);
817 void msgViewerDlg::searchMsg()
819 QString search = editSearch->text();
821 if (search.isEmpty())
824 auto display = tabWidget->currentIndex();
825 if (search != searchStr)
827 msgFilters_[display].txtDisplay->moveCursor(QTextCursor::Start);
828 if (!msgFilters_[display].txtDisplay->find(search))
830 msgFilters_[display].txtDisplay->moveCursor(QTextCursor::End);
838 if (!msgFilters_[display].txtDisplay->find(search))
840 msgFilters_[display].txtDisplay->moveCursor(QTextCursor::Start);
841 if (!msgFilters_[display].txtDisplay->find(search))
843 msgFilters_[display].txtDisplay->moveCursor(QTextCursor::End);
850 void msgViewerDlg::searchClear()
852 auto display = tabWidget->currentIndex();
853 editSearch->setText(
"");
855 msgFilters_[display].txtDisplay->find(
"");
856 msgFilters_[display].txtDisplay->moveCursor(QTextCursor::End);
859 void msgViewerDlg::setSuppression(QAction* act)
861 bool status = act->isChecked();
866 void msgViewerDlg::setThrottling(QAction* act)
868 bool status = act->isChecked();
873 void msgViewerDlg::tabWidgetCurrentChanged(
int newTab)
875 lcdDisplayedMsgs->display(msgFilters_[newTab].nDisplayMsgs);
877 lwHost->setCurrentRow(-1, QItemSelectionModel::Clear);
878 lwApplication->setCurrentRow(-1, QItemSelectionModel::Clear);
879 lwCategory->setCurrentRow(-1, QItemSelectionModel::Clear);
881 for (
auto host : msgFilters_[newTab].hostFilter)
883 auto items = lwHost->findItems(host, Qt::MatchExactly);
884 if (items.size() > 0)
886 items[0]->setSelected(
true);
889 for (
auto app : msgFilters_[newTab].appFilter)
891 auto items = lwApplication->findItems(app, Qt::MatchExactly);
892 if (items.size() > 0)
894 items[0]->setSelected(
true);
897 for (
auto cat : msgFilters_[newTab].catFilter)
899 auto items = lwCategory->findItems(cat, Qt::MatchExactly);
900 if (items.size() > 0)
902 items[0]->setSelected(
true);
907 void msgViewerDlg::tabCloseRequested(
int tabIndex)
909 if (tabIndex == 0 || static_cast<size_t>(tabIndex) >= msgFilters_.size())
return;
911 auto widget = tabWidget->widget(tabIndex);
912 tabWidget->removeTab(tabIndex);
915 msgFilters_.erase(msgFilters_.begin() + tabIndex);
918 void msgViewerDlg::closeEvent(QCloseEvent* event)
923 QStringList msgViewerDlg::toQStringList(QList<QListWidgetItem *> in)
927 for (
auto i = 0; i < in.size(); ++i)
929 out << in[i]->text();
Suppress messages based on a regular expression
void use(bool flag)
Set whether the suppression is active
Throttle messages based on name and time limits. Separate from MessageFacility limiting.