mirror of
https://github.com/falcosecurity/falco.git
synced 2025-07-19 09:06:48 +00:00
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:
parent
3839fdca1e
commit
1b8847c06b
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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]++;
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
};
|
};
|
Loading…
Reference in New Issue
Block a user