mirror of
https://github.com/falcosecurity/falco.git
synced 2025-09-10 02:59:38 +00:00
cleanup(userspace/falco): new consistent metrics output fields classes falco. and scap.
* Ensure each metric field name more consistently adheres to the grammar used in Falco rules: * `falco.`: new field class representing userspace counters, statistics, resource utilization, or necessary information fields * `scap.`: new field class represents counters and statistics mostly obtained from Falco's kernel instrumentation before events are sent to userspace, but can include scap userspace stats as well * minor cleanup Co-authored-by: Jason Dellaluce <jasondellaluce@gmail.com> Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
This commit is contained in:
@@ -409,7 +409,7 @@ static falco::app::run_result init_stats_writer(
|
|||||||
/* Enforce minimum bound of 100ms. */
|
/* Enforce minimum bound of 100ms. */
|
||||||
if(config->m_metrics_interval < 100)
|
if(config->m_metrics_interval < 100)
|
||||||
{
|
{
|
||||||
return falco::app::run_result::fatal("Metrics interval must have a minimum value of 100ms");
|
return falco::app::run_result::fatal("Metrics interval must have a minimum value of 100ms and reflect a Prometheus compliant time duration format: https://prometheus.io/docs/prometheus/latest/querying/basics/#time-durations. ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(std::all_of(config->m_metrics_interval_str.begin(), config->m_metrics_interval_str.end(), ::isdigit))
|
if(std::all_of(config->m_metrics_interval_str.begin(), config->m_metrics_interval_str.end(), ::isdigit))
|
||||||
@@ -422,6 +422,9 @@ static falco::app::run_result init_stats_writer(
|
|||||||
falco_logger::log(LOG_WARNING, "Metrics are enabled with no output configured, no snapshot will be collected");
|
falco_logger::log(LOG_WARNING, "Metrics are enabled with no output configured, no snapshot will be collected");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
falco_logger::log(LOG_INFO, "Setting metrics interval to " + config->m_metrics_interval_str + ", equivalent to " + std::to_string(config->m_metrics_interval) + " (ms)\n");
|
||||||
|
|
||||||
auto res = falco::app::run_result::ok();
|
auto res = falco::app::run_result::ok();
|
||||||
res.success = stats_writer::init_ticker(config->m_metrics_interval, res.errstr);
|
res.success = stats_writer::init_ticker(config->m_metrics_interval, res.errstr);
|
||||||
res.proceed = res.success;
|
res.proceed = res.success;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (C) 2022 The Falco Authors.
|
Copyright (C) 2023 The Falco Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -26,7 +26,6 @@ limitations under the License.
|
|||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "banned.h" // This raises a compilation error when certain functions are used
|
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||||
#include "config_falco.h"
|
#include "config_falco.h"
|
||||||
#include <re2/re2.h>
|
|
||||||
|
|
||||||
// note: ticker_t is an uint16_t, which is enough because we don't care about
|
// note: ticker_t is an uint16_t, which is enough because we don't care about
|
||||||
// overflows here. Threads calling stats_writer::handle() will just
|
// overflows here. Threads calling stats_writer::handle() will just
|
||||||
@@ -201,20 +200,20 @@ void stats_writer::collector::get_metrics_output_fields_wrapper(
|
|||||||
|
|
||||||
/* Wrapper fields useful for statistical analyses and attributions. Always enabled. */
|
/* Wrapper fields useful for statistical analyses and attributions. Always enabled. */
|
||||||
output_fields["evt.time"] = std::to_string(now); /* Some ETLs may prefer a consistent timestamp within output_fields. */
|
output_fields["evt.time"] = std::to_string(now); /* Some ETLs may prefer a consistent timestamp within output_fields. */
|
||||||
output_fields["version"] = FALCO_VERSION;
|
output_fields["falco.version"] = FALCO_VERSION;
|
||||||
output_fields["start_ts"] = std::to_string(agent_info->start_ts_epoch);
|
output_fields["falco.start_ts"] = std::to_string(agent_info->start_ts_epoch);
|
||||||
output_fields["duration_sec"] = std::to_string((now - agent_info->start_ts_epoch) / ONE_SECOND_IN_NS);
|
output_fields["falco.duration_sec"] = std::to_string((now - agent_info->start_ts_epoch) / ONE_SECOND_IN_NS);
|
||||||
output_fields["kernel_release"] = agent_info->uname_r;
|
output_fields["falco.kernel_release"] = agent_info->uname_r;
|
||||||
output_fields["host_boot_ts"] = std::to_string(machine_info->boot_ts_epoch);
|
output_fields["falco.host_boot_ts"] = std::to_string(machine_info->boot_ts_epoch);
|
||||||
output_fields["hostname"] = machine_info->hostname; /* Explicitly add hostname to log msg in case hostname rule output field is disabled. */
|
output_fields["falco.hostname"] = machine_info->hostname; /* Explicitly add hostname to log msg in case hostname rule output field is disabled. */
|
||||||
output_fields["host_num_cpus"] = std::to_string(machine_info->num_cpus);
|
output_fields["falco.host_num_cpus"] = std::to_string(machine_info->num_cpus);
|
||||||
|
|
||||||
output_fields["src"] = src;
|
output_fields["evt.source"] = src;
|
||||||
for (size_t i = 0; i < sizeof(all_driver_engines) / sizeof(const char*); i++)
|
for (size_t i = 0; i < sizeof(all_driver_engines) / sizeof(const char*); i++)
|
||||||
{
|
{
|
||||||
if (inspector->check_current_engine(all_driver_engines[i]))
|
if (inspector->check_current_engine(all_driver_engines[i]))
|
||||||
{
|
{
|
||||||
output_fields["driver"] = all_driver_engines[i];
|
output_fields["scap.engine_name"] = all_driver_engines[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -223,10 +222,10 @@ void stats_writer::collector::get_metrics_output_fields_wrapper(
|
|||||||
if (m_last_num_evts != 0 && stats_snapshot_time_delta_sec > 0)
|
if (m_last_num_evts != 0 && stats_snapshot_time_delta_sec > 0)
|
||||||
{
|
{
|
||||||
/* Successfully processed userspace event rate. */
|
/* Successfully processed userspace event rate. */
|
||||||
output_fields["u.evts_rate_sec"] = std::to_string((num_evts - m_last_num_evts) / (double)stats_snapshot_time_delta_sec);
|
output_fields["falco.evts_rate_sec"] = std::to_string((num_evts - m_last_num_evts) / (double)stats_snapshot_time_delta_sec);
|
||||||
}
|
}
|
||||||
output_fields["u.num_evts"] = std::to_string(num_evts);
|
output_fields["falco.num_evts"] = std::to_string(num_evts);
|
||||||
output_fields["u.num_evts_prev"] = std::to_string(m_last_num_evts);
|
output_fields["falco.num_evts_prev"] = std::to_string(m_last_num_evts);
|
||||||
m_last_num_evts = num_evts;
|
m_last_num_evts = num_evts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,31 +250,33 @@ void stats_writer::collector::get_metrics_output_fields_additional(
|
|||||||
{
|
{
|
||||||
for(uint32_t stat = 0; stat < nstats; stat++)
|
for(uint32_t stat = 0; stat < nstats; stat++)
|
||||||
{
|
{
|
||||||
|
char metric_name[STATS_NAME_MAX] = "falco.";
|
||||||
|
strncat(metric_name, utilization[stat].name, sizeof(metric_name) - strlen(metric_name));
|
||||||
switch(utilization[stat].type)
|
switch(utilization[stat].type)
|
||||||
{
|
{
|
||||||
case STATS_VALUE_TYPE_U64:
|
case STATS_VALUE_TYPE_U64:
|
||||||
|
|
||||||
if (m_writer->m_config->m_metrics_convert_memory_to_mb && strncmp(utilization[stat].name, "container_memory_used", 21) == 0)
|
if (m_writer->m_config->m_metrics_convert_memory_to_mb && strncmp(utilization[stat].name, "container_memory_used", 21) == 0)
|
||||||
{
|
{
|
||||||
output_fields[utilization[stat].name] = std::to_string(utilization[stat].value.u64 / (double)1024 / (double)1024);
|
output_fields[metric_name] = std::to_string(utilization[stat].value.u64 / (double)1024 / (double)1024);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
output_fields[utilization[stat].name] = std::to_string(utilization[stat].value.u64);
|
output_fields[metric_name] = std::to_string(utilization[stat].value.u64);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case STATS_VALUE_TYPE_U32:
|
case STATS_VALUE_TYPE_U32:
|
||||||
if (m_writer->m_config->m_metrics_convert_memory_to_mb && strncmp(utilization[stat].name, "memory_", 7) == 0)
|
if (m_writer->m_config->m_metrics_convert_memory_to_mb && strncmp(utilization[stat].name, "memory_", 7) == 0)
|
||||||
{
|
{
|
||||||
output_fields[utilization[stat].name] = std::to_string(utilization[stat].value.u32 / (double)1024);
|
output_fields[metric_name] = std::to_string(utilization[stat].value.u32 / (double)1024);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
output_fields[utilization[stat].name] = std::to_string(utilization[stat].value.u32);
|
output_fields[metric_name] = std::to_string(utilization[stat].value.u32);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case STATS_VALUE_TYPE_D:
|
case STATS_VALUE_TYPE_D:
|
||||||
output_fields[utilization[stat].name] = std::to_string(utilization[stat].value.d);
|
output_fields[metric_name] = std::to_string(utilization[stat].value.d);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -311,45 +312,53 @@ void stats_writer::collector::get_metrics_output_fields_additional(
|
|||||||
for(uint32_t stat = 0; stat < nstats; stat++)
|
for(uint32_t stat = 0; stat < nstats; stat++)
|
||||||
{
|
{
|
||||||
// todo: as we expand scap_stats_v2 prefix may be pushed to scap or we may need to expand
|
// todo: as we expand scap_stats_v2 prefix may be pushed to scap or we may need to expand
|
||||||
// functionality here for example if we add userspace syscall counters that should be prefixed w/ `u.`
|
// functionality here for example if we add userspace syscall counters that should be prefixed w/ `falco.`
|
||||||
char metric_name[STATS_NAME_MAX] = "k.";
|
char metric_name[STATS_NAME_MAX] = "scap.";
|
||||||
size_t dest_len = strlen(metric_name);
|
strncat(metric_name, stats_v2[stat].name, sizeof(metric_name) - strlen(metric_name));
|
||||||
switch(stats_v2[stat].type)
|
switch(stats_v2[stat].type)
|
||||||
{
|
{
|
||||||
case STATS_VALUE_TYPE_U64:
|
case STATS_VALUE_TYPE_U64:
|
||||||
if (strncmp(stats_v2[stat].name, "n_evts", 6) == 0)
|
if (strncmp(stats_v2[stat].name, "n_evts", 6) == 0)
|
||||||
{
|
{
|
||||||
n_evts = stats_v2[stat].value.u64;
|
n_evts = stats_v2[stat].value.u64;
|
||||||
output_fields["k.evts_rate_sec"] = std::to_string(0);
|
|
||||||
if (m_last_n_evts != 0 && stats_snapshot_time_delta_sec > 0)
|
if (m_last_n_evts != 0 && stats_snapshot_time_delta_sec > 0)
|
||||||
{
|
{
|
||||||
/* n_evts is total number of kernel side events. */
|
/* n_evts is total number of kernel side events. */
|
||||||
output_fields["k.evts_rate_sec"] = std::to_string((n_evts - m_last_n_evts) / stats_snapshot_time_delta_sec);
|
output_fields["scap.evts_rate_sec"] = std::to_string((n_evts - m_last_n_evts) / stats_snapshot_time_delta_sec);
|
||||||
}
|
}
|
||||||
output_fields["k.n_evts_prev"] = std::to_string(m_last_n_evts);
|
else
|
||||||
|
{
|
||||||
|
output_fields["scap.evts_rate_sec"] = std::to_string(0);
|
||||||
|
}
|
||||||
|
output_fields["scap.n_evts_prev"] = std::to_string(m_last_n_evts);
|
||||||
}
|
}
|
||||||
else if (strncmp(stats_v2[stat].name, "n_drops", 7) == 0)
|
else if (strncmp(stats_v2[stat].name, "n_drops", 7) == 0)
|
||||||
{
|
{
|
||||||
n_drops = stats_v2[stat].value.u64;
|
n_drops = stats_v2[stat].value.u64;
|
||||||
output_fields["k.evts_drop_rate_sec"] = std::to_string(0);
|
|
||||||
if (m_last_n_drops != 0 && stats_snapshot_time_delta_sec > 0)
|
if (m_last_n_drops != 0 && stats_snapshot_time_delta_sec > 0)
|
||||||
{
|
{
|
||||||
/* n_drops is total number of kernel side event drops. */
|
/* n_drops is total number of kernel side event drops. */
|
||||||
output_fields["k.evts_drop_rate_sec"] = std::to_string((n_drops - m_last_n_drops) / stats_snapshot_time_delta_sec);
|
output_fields["scap.evts_drop_rate_sec"] = std::to_string((n_drops - m_last_n_drops) / stats_snapshot_time_delta_sec);
|
||||||
}
|
}
|
||||||
output_fields["k.n_drops_prev"] = std::to_string(m_last_n_drops);
|
else
|
||||||
|
{
|
||||||
|
output_fields["scap.evts_drop_rate_sec"] = std::to_string(0);
|
||||||
|
}
|
||||||
|
output_fields["scap.n_drops_prev"] = std::to_string(m_last_n_drops);
|
||||||
}
|
}
|
||||||
strncat(metric_name, stats_v2[stat].name, sizeof(stats_v2[stat].name) - dest_len);
|
|
||||||
output_fields[metric_name] = std::to_string(stats_v2[stat].value.u64);
|
output_fields[metric_name] = std::to_string(stats_v2[stat].value.u64);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output_fields["k.n_drops_perc"] = std::to_string(0);
|
|
||||||
if((n_evts - m_last_n_evts) > 0)
|
if((n_evts - m_last_n_evts) > 0)
|
||||||
{
|
{
|
||||||
output_fields["k.n_drops_perc"] = std::to_string((100.0 * (n_drops - m_last_n_drops)) / (n_evts - m_last_n_evts));
|
output_fields["scap.n_drops_perc"] = std::to_string((100.0 * (n_drops - m_last_n_drops)) / (n_evts - m_last_n_evts));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
output_fields["scap.n_drops_perc"] = std::to_string(0);
|
||||||
}
|
}
|
||||||
m_last_n_evts = n_evts;
|
m_last_n_evts = n_evts;
|
||||||
m_last_n_drops = n_drops;
|
m_last_n_drops = n_drops;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (C) 2022 The Falco Authors.
|
Copyright (C) 2023 The Falco Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -26,8 +26,6 @@ limitations under the License.
|
|||||||
#include "falco_outputs.h"
|
#include "falco_outputs.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
|
|
||||||
#define MAX_STATS_PRESET_INDEX 6
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Writes stats samples collected from inspectors into a given output.
|
\brief Writes stats samples collected from inspectors into a given output.
|
||||||
Users must use a stats_writer::collector in order to collect and write stats
|
Users must use a stats_writer::collector in order to collect and write stats
|
||||||
|
Reference in New Issue
Block a user