LCOV - code coverage report
Current view: top level - /opt/artdaq/srcs/artdaq-mfextensions/ErrorHandler/MessageAnalyzer - ma_rule_engine.cpp (source / functions) Coverage Total Hit
Test: artdaq.info.cleaned Lines: 0.0 % 128 0
Test Date: 2025-09-04 00:45:34 Functions: 0.0 % 11 0

            Line data    Source code
       1              : 
       2              : #include "ErrorHandler/MessageAnalyzer/ma_rule_engine.h"
       3              : 
       4              : #include <cetlib/filepath_maker.h>
       5              : #include <fhiclcpp/make_ParameterSet.h>
       6              : 
       7              : using fhicl::ParameterSet;
       8              : 
       9              : using namespace novadaq::errorhandler;
      10              : 
      11            0 : ma_rule_engine::ma_rule_engine(fhicl::ParameterSet const& pset, alarm_fn_t alarm, cond_match_fn_t cond_match)
      12            0 :     : pset(pset)
      13            0 :     , cmap()
      14            0 :     , cnames()
      15            0 :     , rmap()
      16            0 :     , rnames()
      17            0 :     , alarm_fn(alarm)
      18            0 :     , cond_match_fn(cond_match)
      19            0 :     , events()
      20            0 :     , event_worker_t()
      21            0 :     , EHS(false)
      22              : {
      23            0 :         init_engine();
      24            0 : }
      25              : 
      26            0 : void ma_rule_engine::init_engine()
      27              : {
      28              :         // Error Handling Supervisor -- EHS
      29            0 :         EHS = pset.get<bool>("EHS", false);
      30              : 
      31            0 :         ParameterSet conds = pset.get<ParameterSet>("conditions", fhicl::ParameterSet());
      32            0 :         ParameterSet rules = pset.get<ParameterSet>("rules", fhicl::ParameterSet());
      33              : 
      34            0 :         cnames = conds.get_pset_names();
      35            0 :         rnames = rules.get_pset_names();
      36              : 
      37              :         // go through all conditions
      38            0 :         for (size_t i = 0; i < cnames.size(); ++i)
      39              :         {
      40            0 :                 ParameterSet nulp;
      41              : 
      42            0 :                 ParameterSet cond = conds.get<ParameterSet>(cnames[i]);
      43            0 :                 ParameterSet rate = cond.get<ParameterSet>("rate", nulp);
      44            0 :                 ParameterSet gran = cond.get<ParameterSet>("granularity", nulp);
      45              : 
      46              :                 // decide whether "at_least" or "at_most"
      47            0 :                 int occur{0}, occur_at_most{0}, occur_at_least{0};
      48            0 :                 bool at_most = rate.get_if_present<int>("occur_at_most", occur_at_most);
      49            0 :                 bool at_least = rate.get_if_present<int>("occur_at_least", occur_at_least);
      50              : 
      51              :                 // compatible with the previous "occurence" keyword
      52            0 :                 if (!at_least) at_least = rate.get_if_present<int>("occurence", occur_at_least);
      53              : 
      54            0 :                 if (at_most && at_least)
      55              :                 {
      56              :                         throw std::runtime_error(
      57              :                             "rule_engine::init_engine() cannot have both 'occur_at_least' "
      58            0 :                             "and 'occur_at_most' in the rate entry, in condition " +
      59            0 :                             cnames[i]);
      60              :                 }
      61            0 :                 else if (!at_most && !at_least)
      62              :                 {
      63            0 :                         occur = 1;
      64            0 :                         at_least = true;
      65              :                 }
      66              :                 else
      67              :                 {
      68            0 :                         occur = at_least ? occur_at_least : occur_at_most;
      69              :                 }
      70              : 
      71              :                 // construct the condition object
      72            0 :                 ma_condition c(cond.get<std::string>("description", std::string()), cond.get<std::string>("severity"), cond.get<std::vector<std::string>>("source"),
      73            0 :                                cond.get<std::vector<std::string>>("category", std::vector<std::string>(1, "*")), cond.get<std::string>("regex"), cond.get<std::string>("test", std::string()),
      74            0 :                                cond.get<bool>("persistent", true), occur, at_least, rate.get<int>("timespan", 4372596)  // a random long time
      75              :                                ,
      76            0 :                                gran.get<bool>("per_source", false), gran.get<bool>("per_target", false), gran.get<unsigned int>("target_group", 1), events);
      77              : 
      78              :                 // push the condition to the container, and parse the test function
      79            0 :                 cond_map_t::iterator it = cmap.insert(std::make_pair(cnames[i], c)).first;
      80              : 
      81              :                 // init after the condition has been inserted into the map
      82            0 :                 it->second.init();
      83            0 :         }
      84              : 
      85              :         // go through all rules
      86            0 :         for (size_t i = 0; i < rnames.size(); ++i)
      87              :         {
      88            0 :                 ParameterSet nulp;
      89              : 
      90            0 :                 ParameterSet rule = rules.get<ParameterSet>(rnames[i]);
      91              : 
      92              :                 // construct the rule object
      93            0 :                 ma_rule r(rnames[i], rule.get<std::string>("description", std::string()), rule.get<bool>("repeat_alarm", false), rule.get<int>("holdoff", 0));
      94              : 
      95              :                 // push the rule to the container
      96            0 :                 rule_map_t::iterator it = rmap.insert(std::make_pair(rnames[i], r)).first;
      97              : 
      98              :                 // parse the condition expression and alarm message
      99              :                 // this is done in a two-step method (init the object, push into container
     100              :                 // then parse) because the parse process involves updating the conditions
     101              :                 // notification list which needs the pointer to the ma_rule object. There-
     102              :                 // fore we push the ma_rule object into the container first, then do the
     103              :                 // parse
     104            0 :                 it->second.parse(rule.get<std::string>("expression"), rule.get<std::string>("message"), rule.get<ParameterSet>("action", nulp), &cmap);
     105            0 :         }
     106              : 
     107              :         // for all conditions sort their notification lists
     108            0 :         cond_map_t::iterator it = cmap.begin();
     109            0 :         for (; it != cmap.end(); ++it) it->second.sort_notify_lists();
     110              : 
     111              :         // timing event worker thread
     112            0 :         event_worker_t = boost::thread(&ma_rule_engine::event_worker, this);
     113            0 : }
     114              : 
     115            0 : void ma_rule_engine::event_worker()
     116              : {
     117              :         while (true)
     118              :         {
     119              :                 // get current second
     120            0 :                 time_t now = time(0);
     121              : 
     122              :                 // loop for all past due events, and execute them
     123              :                 {
     124              :                         // scoped lock
     125            0 :                         boost::mutex::scoped_lock lock(events.lock);
     126              : 
     127            0 :                         conds_t status;
     128            0 :                         event_queue_t& eq = events.event_queue();
     129              : 
     130            0 :                         while (!eq.empty() && eq.top().timestamp() < now)
     131              :                         {
     132            0 :                                 ma_timing_event const& e = eq.top();
     133            0 :                                 e.condition().event(e.source_idx(), e.target_idx(), e.timestamp(), status);
     134            0 :                                 eq.pop();
     135              :                         }
     136              : 
     137              :                         // build notify list
     138            0 :                         notify_list_t notify_status;
     139            0 :                         merge_notify_list(notify_status, status, STATUS_NOTIFY);
     140              : 
     141              :                         // rules->evaluate
     142            0 :                         evaluate_rules(notify_status);
     143            0 :                 }
     144              : 
     145            0 :                 sleep(1);
     146            0 :         }
     147              : }
     148              : 
     149            0 : void ma_rule_engine::feed(qt_mf_msg const& msg)
     150              : {
     151              :         // reaction starters
     152            0 :         conds_t status;
     153            0 :         conds_t source;
     154            0 :         conds_t target;
     155              : 
     156              :         // loop through conditions
     157              :         {
     158            0 :                 cond_map_t::iterator it = cmap.begin();
     159            0 :                 for (; it != cmap.end(); ++it)
     160            0 :                         if (it->second.match(msg, status, source, target))
     161            0 :                                 cond_match_fn(it->first);  // callback fn for condition match
     162              :         }
     163              : 
     164              :         // notification mechanism
     165              : 
     166              :         // merge notification lists from reaction starters
     167            0 :         notify_list_t notify_status;
     168            0 :         notify_list_t notify_domain;
     169              : 
     170            0 :         merge_notify_list(notify_status, status, STATUS_NOTIFY);
     171            0 :         merge_notify_list(notify_domain, source, SOURCE_NOTIFY);
     172            0 :         merge_notify_list(notify_domain, target, TARGET_NOTIFY);
     173              : 
     174              :         // update domains
     175            0 :         evaluate_rules_domain(notify_domain);
     176              : 
     177              :         // loop to update status
     178            0 :         evaluate_rules(notify_status);
     179            0 : }
     180              : 
     181            0 : void ma_rule_engine::evaluate_rules_domain(notify_list_t& notify_domain)
     182              : {
     183            0 :         notify_list_t::iterator it = notify_domain.begin();
     184            0 :         for (; it != notify_domain.end(); ++it)
     185            0 :                 (*it)->evaluate_domain();
     186            0 : }
     187              : 
     188            0 : void ma_rule_engine::evaluate_rules(notify_list_t& notify_status)
     189              : {
     190            0 :         notify_list_t::iterator it = notify_status.begin();
     191            0 :         for (; it != notify_status.end(); ++it)
     192              :         {
     193            0 :                 if ((*it)->evaluate())
     194              :                 {
     195              :                         // alarm message
     196            0 :                         alarm_fn((*it)->name(), (*it)->get_alarm_message());
     197              : 
     198              :                         // actions
     199            0 :                         if (EHS)
     200              :                         {
     201            0 :                                 int now_reset_rule = (*it)->act();
     202            0 :                                 if (now_reset_rule > 0)
     203              :                                 {
     204            0 :                                         this->reset_rule((*it)->name());
     205            0 :                                         alarm_fn((*it)->name(), "reseting this rule!");
     206              :                                 }
     207              :                         }
     208              :                 }
     209              :         }
     210            0 : }
     211              : 
     212            0 : void ma_rule_engine::merge_notify_list(notify_list_t& n_list, conds_t const& c_list, notify_t type)
     213              : {
     214            0 :         conds_t::const_iterator it = c_list.begin();
     215            0 :         for (; it != c_list.end(); ++it)
     216              :         {
     217            0 :                 notify_list_t notify((*it)->get_notify_list(type));
     218            0 :                 n_list.merge(notify);
     219            0 :                 n_list.unique();
     220            0 :         }
     221            0 : }
     222              : 
     223              : const ma_condition&
     224            0 : ma_rule_engine::find_cond_by_name(std::string const& name) const
     225              : {
     226            0 :         cond_map_t::const_iterator it = cmap.find(name);
     227            0 :         if (it == cmap.end())
     228            0 :                 throw std::runtime_error("rule_engine::find_cond_by_name() name not found");
     229            0 :         return it->second;
     230              : }
     231              : 
     232              : ma_condition&
     233            0 : ma_rule_engine::find_cond_by_name(std::string const& name)
     234              : {
     235            0 :         cond_map_t::iterator it = cmap.find(name);
     236            0 :         if (it == cmap.end())
     237            0 :                 throw std::runtime_error("rule_engine::find_cond_by_name() name not found");
     238            0 :         return it->second;
     239              : }
     240              : 
     241              : const ma_rule&
     242            0 : ma_rule_engine::find_rule_by_name(std::string const& name) const
     243              : {
     244            0 :         rule_map_t::const_iterator it = rmap.find(name);
     245            0 :         if (it == rmap.end())
     246            0 :                 throw std::runtime_error("rule_engine::find_rule_by_name() name not found");
     247            0 :         return it->second;
     248              : }
     249              : 
     250              : ma_rule&
     251            0 : ma_rule_engine::find_rule_by_name(std::string const& name)
     252              : {
     253            0 :         rule_map_t::iterator it = rmap.find(name);
     254            0 :         if (it == rmap.end())
     255            0 :                 throw std::runtime_error("rule_engine::find_rule_by_name() name not found");
     256            0 :         return it->second;
     257              : }
        

Generated by: LCOV version 2.0-1