refactor(userspace/engine): make stats manager thread-safe for on_event method

Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
This commit is contained in:
Jason Dellaluce 2022-06-21 16:50:04 +00:00 committed by poiana
parent 3839fdca1e
commit 1b8847c06b
3 changed files with 56 additions and 21 deletions

View File

@ -194,6 +194,15 @@ std::unique_ptr<load_result> falco_engine::load_rules(const std::string &rules_c
m_rule_loader.compile(cfg, m_rules); m_rule_loader.compile(cfg, m_rules);
} }
if (cfg.res->successful())
{
m_rule_stats_manager.clear();
for (const auto &r : m_rules)
{
m_rule_stats_manager.on_rule_loaded(r);
}
}
return std::move(cfg.res); return std::move(cfg.res);
} }

View File

@ -45,37 +45,48 @@ void stats_manager::format(
out += "Rule counts by severity:\n"; out += "Rule counts by severity:\n";
for (size_t i = 0; i < m_by_priority.size(); i++) for (size_t i = 0; i < m_by_priority.size(); i++)
{ {
if (m_by_priority[i] > 0) auto val = m_by_priority[i].get()->load();
if (val > 0)
{ {
falco_common::format_priority( falco_common::format_priority(
(falco_common::priority_type) i, fmt, true); (falco_common::priority_type) i, fmt, true);
transform(fmt.begin(), fmt.end(), fmt.begin(), ::toupper); transform(fmt.begin(), fmt.end(), fmt.begin(), ::toupper);
out += " " + fmt; out += " " + fmt + ": " + to_string(val) + "\n";
out += ": " + to_string(m_by_priority[i]) + "\n";
} }
} }
out += "Triggered rules by rule name:\n"; out += "Triggered rules by rule name:\n";
for (size_t i = 0; i < m_by_rule_id.size(); i++) for (size_t i = 0; i < m_by_rule_id.size(); i++)
{ {
if (m_by_rule_id[i] > 0) auto val = m_by_rule_id[i].get()->load();
if (val > 0)
{ {
out += " " + rules.at(i)->name; out += " " + rules.at(i)->name + ": " + to_string(val) + "\n";
out += ": " + to_string(m_by_rule_id[i]) + "\n";
} }
} }
} }
void stats_manager::on_rule_loaded(const falco_rule& rule)
{
while (m_by_rule_id.size() <= rule.id)
{
m_by_rule_id.emplace_back();
m_by_rule_id[m_by_rule_id.size() - 1].reset(new atomic<uint64_t>(0));
}
while (m_by_priority.size() <= (size_t) rule.priority)
{
m_by_priority.emplace_back();
m_by_priority[m_by_priority.size() - 1].reset(new atomic<uint64_t>(0));
}
}
void stats_manager::on_event(const falco_rule& rule) void stats_manager::on_event(const falco_rule& rule)
{ {
if (m_by_rule_id.size() <= rule.id) if (m_by_rule_id.size() <= rule.id
|| m_by_priority.size() <= (size_t) rule.priority)
{ {
m_by_rule_id.resize(rule.id + 1, (uint64_t) 0); throw falco_exception("rule id or priority is out of boubnds");
} }
if (m_by_priority.size() <= (size_t) rule.priority) m_total.fetch_add(1, std::memory_order_relaxed);
{ m_by_rule_id[rule.id]->fetch_add(1, std::memory_order_relaxed);
m_by_priority.resize((size_t) rule.priority + 1, (uint64_t) 0); m_by_priority[(size_t) rule.priority]->fetch_add(1, std::memory_order_relaxed);
}
m_total++;
m_by_rule_id[rule.id]++;
m_by_priority[(size_t) rule.priority]++;
} }

View File

@ -18,11 +18,16 @@ limitations under the License.
#include <vector> #include <vector>
#include <string> #include <string>
#include <atomic>
#include <memory>
#include "falco_rule.h" #include "falco_rule.h"
#include "indexed_vector.h" #include "indexed_vector.h"
/*! /*!
\brief Manager for the internal statistics of the rule engine \brief Manager for the internal statistics of the rule engine.
The on_event() is thread-safe and non-blocking, and it can be used
concurrently across many callers in parallel.
All the other methods are not thread safe.
*/ */
class stats_manager class stats_manager
{ {
@ -36,19 +41,29 @@ public:
virtual void clear(); virtual void clear();
/*! /*!
\brief Callback for when a given rule matches an event \brief Callback for when a new rule is loaded in the engine.
Rules must be passed through this method before submitting them as
an argument of on_event().
*/
virtual void on_rule_loaded(const falco_rule& rule);
/*!
\brief Callback for when a given rule matches an event.
This method is thread-safe.
\throws falco_exception if rule has not been passed to
on_rule_loaded() first
*/ */
virtual void on_event(const falco_rule& rule); virtual void on_event(const falco_rule& rule);
/*! /*!
\brief Formats the internal statistics into the out string \brief Formats the internal statistics into the out string.
*/ */
virtual void format( virtual void format(
const indexed_vector<falco_rule>& rules, const indexed_vector<falco_rule>& rules,
std::string& out) const; std::string& out) const;
private: private:
uint64_t m_total; atomic<uint64_t> m_total;
std::vector<uint64_t> m_by_priority; std::vector<std::unique_ptr<atomic<uint64_t>>> m_by_priority;
std::vector<uint64_t> m_by_rule_id; std::vector<std::unique_ptr<atomic<uint64_t>>> m_by_rule_id;
}; };