mirror of
https://github.com/falcosecurity/falco.git
synced 2025-09-04 08:04:49 +00:00
cleanup(userspace/falco): address reviewers comments
* renaming to `metrics` for technical clarity * adopt Prometheus like metrics interval settings Co-authored-by: Jason Dellaluce <jasondellaluce@gmail.com> Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
This commit is contained in:
@@ -54,7 +54,7 @@ endif()
|
|||||||
|
|
||||||
set(SCAP_HOST_ROOT_ENV_VAR_NAME "HOST_ROOT")
|
set(SCAP_HOST_ROOT_ENV_VAR_NAME "HOST_ROOT")
|
||||||
set(SCAP_HOSTNAME_ENV_VAR "FALCO_HOSTNAME")
|
set(SCAP_HOSTNAME_ENV_VAR "FALCO_HOSTNAME")
|
||||||
set(SINSP_AGENT_CGROUP_MEM_PATH_ENV_VAR "FALCO_CGROUP_MEM")
|
set(SINSP_AGENT_CGROUP_MEM_PATH_ENV_VAR "FALCO_CGROUP_MEM_PATH")
|
||||||
|
|
||||||
if(NOT LIBSCAP_DIR)
|
if(NOT LIBSCAP_DIR)
|
||||||
set(LIBSCAP_DIR "${FALCOSECURITY_LIBS_SOURCE_DIR}")
|
set(LIBSCAP_DIR "${FALCOSECURITY_LIBS_SOURCE_DIR}")
|
||||||
|
99
falco.yaml
99
falco.yaml
@@ -566,83 +566,90 @@ base_syscalls:
|
|||||||
custom_set: []
|
custom_set: []
|
||||||
repair: false
|
repair: false
|
||||||
|
|
||||||
# stats_v2: periodic stats and resource utilization metrics, initial release
|
# metrics: periodic stats and resource utilization metrics, initial release
|
||||||
#
|
#
|
||||||
# --- [Description]
|
# --- [Description]
|
||||||
#
|
#
|
||||||
# stats_v2 reflects a stats re-design from the ground up. Falco now natively supports
|
# `metrics` reflects a stats/metrics re-design from the ground up. Falco natively supports
|
||||||
# resource utilization metrics and enhanced specialized metrics to monitor Falco's
|
# resource utilization metrics and enhanced specialized metrics to monitor Falco's
|
||||||
# performance in production. The new metrics are exposed as monotonic counters or snapshots
|
# performance in production. Metrics are exposed as monotonic counters or snapshots
|
||||||
# emitted at a pre-defined interval. Each metric is captured in the same consolidated log message.
|
# emitted at a pre-defined interval. Each metric is captured in the same consolidated log message.
|
||||||
# In addition, relevant wrapper fields are added, allowing you to perform sophisticated and customized
|
# In addition, relevant wrapper fields are added, allowing the end user to perform customized
|
||||||
# statistical analyses and correlations. Lastly, the new stats framework can be easily extended
|
# statistical analyses and correlations. Lastly, the metrics framework can be easily extended in the future.
|
||||||
# with new metrics.
|
|
||||||
#
|
#
|
||||||
# Notice: Schema and output field names are not guaranteed to be stable
|
# Notice: Schema and output field names are not guaranteed to be stable
|
||||||
# and might change until stats_v2 reaches a stable release.
|
# and might change until `metrics` reaches a stable release.
|
||||||
#
|
#
|
||||||
# --- [Usage]
|
# --- [Usage]
|
||||||
#
|
#
|
||||||
# Disabled by default.
|
# Disabled by default.
|
||||||
#
|
#
|
||||||
# Env variable `-E FALCO_HOSTNAME=myhostname` customizes hostname in case
|
# Env variable `-E FALCO_HOSTNAME=myhostname` customizes hostname for Kubernetes
|
||||||
# you deploy in Kubernetes where the hostname can be equivalent to the pod name.
|
# deployments where the hostname can be equivalent to the pod name.
|
||||||
#
|
#
|
||||||
# `stats_interval_preset`:
|
# `interval`:
|
||||||
# preset 0: default -> means skip, not enabled
|
# Define the stats interval following the Prometheus time duration definitions.
|
||||||
# preset 1: 15 <min> -> 900000 <msec>
|
# https://prometheus.io/docs/prometheus/latest/querying/basics/#time-durations
|
||||||
# preset 2: 30 <min> -> 1800000 <msec>
|
|
||||||
# preset 3: 1 <hr> -> 3600000 <msec> - We recommend this option for large production environments
|
|
||||||
# preset 4: 4 <hrs> -> 14400000 <msec>
|
|
||||||
# preset 5: 6 <hrs> -> 21600000 <msec>
|
|
||||||
# preset 6: 12 <hrs> -> 43200000 <msec>
|
|
||||||
#
|
#
|
||||||
# `stats_interval_ms`:
|
# Time durations are specified as a number, followed immediately by one of the following units:
|
||||||
# If greater than 0 it overrides `stats_interval_preset`.
|
# ms - milliseconds
|
||||||
# We recommend this option for testing and debugging only,
|
# s - seconds
|
||||||
# use small intervals with caution also for debugging.
|
# m - minutes
|
||||||
|
# h - hours
|
||||||
|
# d - days - assuming a day has always 24h
|
||||||
|
# w - weeks - assuming a week has always 7d
|
||||||
|
# y - years - assuming a year has always 365d
|
||||||
#
|
#
|
||||||
# `stats_internal_rule`:
|
# Example of a valid time duration: 1h30m20s10ms
|
||||||
# Emit new stats as rule `Falco internal: resource utilization stats metrics`.
|
|
||||||
# We recommend this option for a seamless performance monitoring especially
|
|
||||||
# if you preserve Falco logs in a data lake. Can be used in conjunction with
|
|
||||||
# `stats_filename` and Prometheus exporter support is planned for the future.
|
|
||||||
#
|
#
|
||||||
# `stats_filename`:
|
# A minimum of 100ms is enforced, however we recommend choosing one of the following intervals for production:
|
||||||
# Append stats to a `jsonl` file. Use with caution in production and log rotate file.
|
# 15m
|
||||||
# Can be used in conjunction with `stats_internal_rule` and Prometheus exporter
|
# 30m
|
||||||
# support is planned for the future.
|
# 1h
|
||||||
|
# 4h
|
||||||
|
# 6h
|
||||||
#
|
#
|
||||||
# `include_resource_utilization`:
|
# `output_rule`:
|
||||||
|
# Emit metrics as rule `Falco internal: resource utilization stats metrics`.
|
||||||
|
# We recommend this option for seamless performance monitoring especially
|
||||||
|
# if Falco logs are preserved in a data lake.
|
||||||
|
# Note: This option requires setting `log_level` at minimum to `info`.
|
||||||
|
#
|
||||||
|
# `output_file`:
|
||||||
|
# Append stats to a `jsonl` file. Use with caution in production, Falco does not rotate the file.
|
||||||
|
#
|
||||||
|
# `resource_utilization_enabled`:
|
||||||
# Emit CPU and memory usages. CPU usage is percentage of one CPU,
|
# Emit CPU and memory usages. CPU usage is percentage of one CPU,
|
||||||
# can be normalized to total number of CPUs to determine overall usage.
|
# can be normalized to total number of CPUs to determine overall usage.
|
||||||
# Memory metrics are currently kept in raw units, `kb` for RSS, PSS and VSZ
|
# Memory metrics are currently kept in raw units, `kb` for RSS, PSS and VSZ
|
||||||
# or `bytes` for container_memory_used. Use `convert_memory_to_mb` to
|
# or `bytes` for container_memory_used. Use `convert_memory_to_mb` to
|
||||||
# uniformly convert each memory metric to MB.
|
# uniformly convert each memory metric to MB.
|
||||||
# `-E FALCO_CGROUP_MEM=customfile` let's you customize the container_memory_used
|
# `-E FALCO_CGROUP_MEM_PATH=customfile` let's you customize the container_memory_used
|
||||||
# file which defaults to Kubernetes `/sys/fs/cgroup/memory/memory.usage_in_bytes`.
|
# file which defaults to Kubernetes `/sys/fs/cgroup/memory/memory.usage_in_bytes` that is
|
||||||
|
# similar to Kubernetes `container_memory_working_set_bytes` of the Falco container.
|
||||||
#
|
#
|
||||||
# `include_kernel_evts_counters`:
|
# `kernel_event_counters_enabled`:
|
||||||
# Emit kernel side event and drop counters, compare to `syscall_event_drops`,
|
# Emit kernel side event and drop counters, compare to `syscall_event_drops`,
|
||||||
# however this option reflects monotonic counters since Falco start
|
# however this option reflects monotonic counters since Falco start,
|
||||||
# flushed at a constant stats interval and therefore can be an alternative.
|
# exported at a constant stats interval and therefore can be regarded as an alternative.
|
||||||
|
# kernel event conters are prefixed with `n_` e.g. `n_evts`, `n_drops`, `n_drops_buffer_total` ...
|
||||||
#
|
#
|
||||||
# `include_libbpf_stats`:
|
# `libbpf_stats_enabled`:
|
||||||
# Exposes `bpftool prog show` like stats, e.g. number of invocations
|
# Exposes `bpftool prog show` like stats, e.g. number of invocations
|
||||||
# of each bpf program Falco attached as well as time spent in each program in nanoseconds.
|
# of each bpf program Falco attached as well as time spent in each program in nanoseconds.
|
||||||
# Requires kernels >= 5.1 plus kernel config `bpf_stats_enabled`.
|
# Requires kernels >= 5.1 plus kernel config `bpf_stats_enabled`.
|
||||||
# This option or equivalent stats are not supported for non `*bpf*` drivers.
|
# This option or equivalent stats are not supported for non `*bpf*` drivers.
|
||||||
|
# Note that currently `libbpf` does not support stats granularity at the bpf tail call level.
|
||||||
#
|
#
|
||||||
# todo: Prometheus export option
|
# todo: Prometheus export option
|
||||||
# todo: syscall counters option
|
# todo: userspace_syscall_event_counters_enabled option
|
||||||
|
|
||||||
stats_v2:
|
metrics:
|
||||||
enabled: false
|
enabled: false
|
||||||
stats_interval_preset: 3
|
interval: 1h
|
||||||
stats_interval_ms: 0
|
output_rule: true
|
||||||
stats_internal_rule: true
|
# output_file: /tmp/falco_stats.jsonl
|
||||||
# stats_filename: /tmp/falco_stats.jsonl
|
resource_utilization_enabled: true
|
||||||
include_resource_utilization: true
|
kernel_event_counters_enabled: true
|
||||||
include_kernel_evts_counters: true
|
libbpf_stats_enabled: true
|
||||||
include_libbpf_stats: true
|
|
||||||
convert_memory_to_mb: true
|
convert_memory_to_mb: true
|
||||||
|
@@ -15,6 +15,7 @@ set(FALCO_ENGINE_SOURCE_FILES
|
|||||||
falco_engine.cpp
|
falco_engine.cpp
|
||||||
falco_load_result.cpp
|
falco_load_result.cpp
|
||||||
falco_utils.cpp
|
falco_utils.cpp
|
||||||
|
falco_metrics.cpp
|
||||||
json_evt.cpp
|
json_evt.cpp
|
||||||
evttype_index_ruleset.cpp
|
evttype_index_ruleset.cpp
|
||||||
formats.cpp
|
formats.cpp
|
||||||
|
145
userspace/engine/falco_metrics.cpp
Normal file
145
userspace/engine/falco_metrics.cpp
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2023 The Falco Authors.
|
||||||
|
|
||||||
|
This file is part of falco.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
#include <cstring>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
#include "falco_utils.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "banned.h" // This raises a compilation error when certain functions are used
|
||||||
|
|
||||||
|
#include <re2/re2.h>
|
||||||
|
|
||||||
|
// these follow the POSIX standard
|
||||||
|
#define RGX_PROMETHEUS_TIME_DURATION_PATTERN "([0-9]+[a-z]+)"
|
||||||
|
#define RGX_PROMETHEUS_NUMBER_PATTERN "([0-9]+)"
|
||||||
|
#define RGX_PROMETHEUS_UNIT_PATTERN "([a-z]+)"
|
||||||
|
|
||||||
|
// using pre-compiled regex for better performance
|
||||||
|
static re2::RE2 s_rgx_prometheus_time_duration(RGX_PROMETHEUS_TIME_DURATION_PATTERN, re2::RE2::POSIX);
|
||||||
|
static re2::RE2 s_rgx_prometheus_number(RGX_PROMETHEUS_NUMBER_PATTERN, re2::RE2::POSIX);
|
||||||
|
static re2::RE2 s_rgx_prometheus_unit(RGX_PROMETHEUS_UNIT_PATTERN, re2::RE2::POSIX);
|
||||||
|
|
||||||
|
// Prometheus time durations: https://prometheus.io/docs/prometheus/latest/querying/basics/#time-durations
|
||||||
|
#define PROMETHEUS_UNIT_Y "y" ///> assuming a year has always 365d
|
||||||
|
#define PROMETHEUS_UNIT_W "w" ///> assuming a week has always 7d
|
||||||
|
#define PROMETHEUS_UNIT_D "d" ///> assuming a day has always 24h
|
||||||
|
#define PROMETHEUS_UNIT_H "h" ///> hour
|
||||||
|
#define PROMETHEUS_UNIT_M "m" ///> minute
|
||||||
|
#define PROMETHEUS_UNIT_S "s" ///> second
|
||||||
|
#define PROMETHEUS_UNIT_MS "ms" ///> millisecond
|
||||||
|
|
||||||
|
// standard time unit conversions to milliseconds
|
||||||
|
#define SECOND_TO_MS 1000
|
||||||
|
#define MINUTE_TO_MS SECOND_TO_MS * 60
|
||||||
|
#define HOUR_TO_MS MINUTE_TO_MS * 60
|
||||||
|
#define DAY_TO_MS HOUR_TO_MS * 24
|
||||||
|
#define WEEK_TO_MS DAY_TO_MS * 7
|
||||||
|
#define YEAR_TO_MS WEEK_TO_MS * 365
|
||||||
|
|
||||||
|
namespace falco
|
||||||
|
{
|
||||||
|
namespace metrics
|
||||||
|
{
|
||||||
|
|
||||||
|
uint64_t parse_metrics_interval(std::string interval_str)
|
||||||
|
{
|
||||||
|
uint64_t interval = 0;
|
||||||
|
/* Sanitize user input, remove possible whitespaces. */
|
||||||
|
interval_str.erase(remove_if(interval_str.begin(), interval_str.end(), isspace), interval_str.end());
|
||||||
|
|
||||||
|
if(!interval_str.empty())
|
||||||
|
{
|
||||||
|
/* Option 1: Passing interval directly in ms. Will be deprecated in the future. */
|
||||||
|
if(std::all_of(interval_str.begin(), interval_str.end(), ::isdigit))
|
||||||
|
{
|
||||||
|
/* todo: deprecate for Falco 0.36. */
|
||||||
|
interval = std::stoull(interval_str, nullptr, 0);
|
||||||
|
std::cerr << "Metrics interval was passed as numeric value without Prometheus time unit, this option will no longer be supported starting Falco 0.36" << std::endl;
|
||||||
|
}
|
||||||
|
/* Option 2: Passing a Prometheus time duration.
|
||||||
|
* https://prometheus.io/docs/prometheus/latest/querying/basics/#time-durations
|
||||||
|
*/
|
||||||
|
else
|
||||||
|
{
|
||||||
|
re2::StringPiece input(interval_str);
|
||||||
|
std::string r;
|
||||||
|
std::string cur_interval_str;
|
||||||
|
uint64_t cur_interval;
|
||||||
|
std::string cur_unit;
|
||||||
|
bool valid = true;
|
||||||
|
/* Note that parsing is done at start up only. */
|
||||||
|
while(re2::RE2::FindAndConsume(&input, s_rgx_prometheus_time_duration, &r))
|
||||||
|
{
|
||||||
|
RE2::Extract(r, s_rgx_prometheus_number, "\\1", &cur_interval_str);
|
||||||
|
cur_interval = std::stoull(cur_interval_str, nullptr, 0);
|
||||||
|
if(cur_interval > 0)
|
||||||
|
{
|
||||||
|
RE2::Extract(r, s_rgx_prometheus_unit, "\\1", &cur_unit);
|
||||||
|
if(cur_unit == PROMETHEUS_UNIT_MS)
|
||||||
|
{
|
||||||
|
interval += cur_interval;
|
||||||
|
}
|
||||||
|
else if(cur_unit == PROMETHEUS_UNIT_S)
|
||||||
|
{
|
||||||
|
interval += cur_interval * SECOND_TO_MS;
|
||||||
|
}
|
||||||
|
else if(cur_unit == PROMETHEUS_UNIT_M)
|
||||||
|
{
|
||||||
|
interval += cur_interval * MINUTE_TO_MS;
|
||||||
|
}
|
||||||
|
else if(cur_unit == PROMETHEUS_UNIT_H)
|
||||||
|
{
|
||||||
|
interval += cur_interval * HOUR_TO_MS;
|
||||||
|
}
|
||||||
|
else if(cur_unit == PROMETHEUS_UNIT_D)
|
||||||
|
{
|
||||||
|
interval += cur_interval * DAY_TO_MS;
|
||||||
|
}
|
||||||
|
else if(cur_unit == PROMETHEUS_UNIT_W)
|
||||||
|
{
|
||||||
|
interval += cur_interval * WEEK_TO_MS;
|
||||||
|
}
|
||||||
|
else if(cur_unit == PROMETHEUS_UNIT_Y)
|
||||||
|
{
|
||||||
|
interval += cur_interval * YEAR_TO_MS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!valid)
|
||||||
|
{
|
||||||
|
// invalidate if any invalid unit or no corresponding numeric value was found
|
||||||
|
interval = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace metrics
|
||||||
|
} // namespace falco
|
49
userspace/engine/falco_metrics.h
Normal file
49
userspace/engine/falco_metrics.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2023The Falco Authors.
|
||||||
|
|
||||||
|
This file is part of falco.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define likely(x) __builtin_expect(!!(x), 1)
|
||||||
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
|
#else
|
||||||
|
#define likely(x) (x)
|
||||||
|
#define unlikely(x) (x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace falco
|
||||||
|
{
|
||||||
|
namespace metrics
|
||||||
|
{
|
||||||
|
|
||||||
|
uint64_t parse_metrics_interval(std::string interval_str);
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace metrics
|
||||||
|
} // namespace falco
|
@@ -401,50 +401,41 @@ static std::shared_ptr<stats_writer> init_stats_writer(const options& opts, std:
|
|||||||
{
|
{
|
||||||
auto statsw = std::make_shared<stats_writer>(outputs, config);
|
auto statsw = std::make_shared<stats_writer>(outputs, config);
|
||||||
std::string err;
|
std::string err;
|
||||||
uint64_t stats_interval_ms = 0;
|
uint64_t interval = 0;
|
||||||
if (config->m_stats_v2_enabled && config->m_stats_v2_stats_interval_preset > 0)
|
|
||||||
{
|
|
||||||
uint16_t index = config->m_stats_v2_stats_interval_preset;
|
|
||||||
if(index <= MAX_STATS_PRESET_INDEX)
|
|
||||||
{
|
|
||||||
/* Index 0 reserved, milliseconds representation for 15min, 30min, 1hr, 4hrs, 6hrs, 12hrs. */
|
|
||||||
std::vector<uint64_t> vect{0LLU, 900000LU, 1800000LU, 3600000LU, 14400000LU, 21600000LU, 43200000LU};
|
|
||||||
stats_interval_ms = vect[index];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// todo: warning message
|
|
||||||
stats_interval_ms = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Continue cmd args support and old defaults for backward compatibility, scheduled for deprecation. */
|
/* Continue cmd args support and old defaults for backward compatibility, scheduled for deprecation. */
|
||||||
if (stats_interval_ms == 0 && opts.stats_interval > 0)
|
if(!config->m_metrics_enabled && opts.stats_interval > 0)
|
||||||
{
|
{
|
||||||
stats_interval_ms = opts.stats_interval;
|
interval = opts.stats_interval;
|
||||||
}
|
}
|
||||||
/* New config. Exact stats_interval_ms in falco.yaml overrides presets. */
|
/* New metrics and configs over falco.yaml. */
|
||||||
if (config->m_stats_v2_enabled && config->m_stats_v2_stats_interval_ms > 0)
|
else if(config->m_metrics_enabled && config->m_metrics_interval > 0)
|
||||||
{
|
{
|
||||||
stats_interval_ms = config->m_stats_v2_stats_interval_ms;
|
interval = config->m_metrics_interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stats_interval_ms > 0)
|
/* Enforce minimum bound of 100ms. */
|
||||||
|
if(interval > 100)
|
||||||
{
|
{
|
||||||
if (!stats_writer::init_ticker(stats_interval_ms, err))
|
if(!stats_writer::init_ticker(interval, err))
|
||||||
{
|
{
|
||||||
throw falco_exception(err);
|
throw falco_exception(err);
|
||||||
}
|
}
|
||||||
|
/* Only support new info message for new metrics and configs over falco.yaml. */
|
||||||
|
if(config->m_metrics_enabled)
|
||||||
|
{
|
||||||
|
falco_logger::log(LOG_INFO, "Setting metrics interval to " + config->m_metrics_interval_str + ", equivalent to " + std::to_string(interval) + " (ms)\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Continue cmd args support for backward compatibility, scheduled for deprecation. */
|
/* Continue cmd args support for backward compatibility, scheduled for deprecation. */
|
||||||
if (!config->m_stats_v2_enabled && !opts.stats_filename.empty())
|
if(!config->m_metrics_enabled && !opts.output_file.empty())
|
||||||
{
|
{
|
||||||
statsw.reset(new stats_writer(opts.stats_filename, outputs, config));
|
statsw.reset(new stats_writer(opts.output_file, outputs, config));
|
||||||
}
|
}
|
||||||
/* New config. */
|
/* New metrics and configs over falco.yaml. */
|
||||||
else if (config->m_stats_v2_enabled && !config->m_stats_v2_stats_filename.empty())
|
else if(config->m_metrics_enabled && !config->m_metrics_output_file.empty())
|
||||||
{
|
{
|
||||||
statsw.reset(new stats_writer(config->m_stats_v2_stats_filename, outputs, config));
|
statsw.reset(new stats_writer(config->m_metrics_output_file, outputs, config));
|
||||||
}
|
}
|
||||||
return statsw;
|
return statsw;
|
||||||
}
|
}
|
||||||
|
@@ -219,7 +219,7 @@ void options::define(cxxopts::Options& opts)
|
|||||||
("p,print", "Add additional information to each falco notification's output.\nWith -pc or -pcontainer will use a container-friendly format.\nWith -pk or -pkubernetes will use a kubernetes-friendly format.\nAdditionally, specifying -pc/-pk will change the interpretation of %container.info in rule output fields.", cxxopts::value(print_additional), "<output_format>")
|
("p,print", "Add additional information to each falco notification's output.\nWith -pc or -pcontainer will use a container-friendly format.\nWith -pk or -pkubernetes will use a kubernetes-friendly format.\nAdditionally, specifying -pc/-pk will change the interpretation of %container.info in rule output fields.", cxxopts::value(print_additional), "<output_format>")
|
||||||
("P,pidfile", "When run as a daemon, write pid to specified file", cxxopts::value(pidfilename)->default_value("/var/run/falco.pid"), "<pid_file>")
|
("P,pidfile", "When run as a daemon, write pid to specified file", cxxopts::value(pidfilename)->default_value("/var/run/falco.pid"), "<pid_file>")
|
||||||
("r", "Rules file/directory (defaults to value set in configuration file, or /etc/falco_rules.yaml). This option can be passed multiple times to read from multiple files/directories.", cxxopts::value<std::vector<std::string>>(), "<rules_file>")
|
("r", "Rules file/directory (defaults to value set in configuration file, or /etc/falco_rules.yaml). This option can be passed multiple times to read from multiple files/directories.", cxxopts::value<std::vector<std::string>>(), "<rules_file>")
|
||||||
("s", "If specified, append statistics related to Falco's reading/processing of events to this file (only useful in live mode).", cxxopts::value(stats_filename), "<stats_file>")
|
("s", "If specified, append statistics related to Falco's reading/processing of events to this file (only useful in live mode).", cxxopts::value(output_file), "<stats_file>")
|
||||||
("stats-interval", "When using -s <stats_file>, write statistics every <msec> ms. This uses signals, so don't recommend intervals below 200 ms. Defaults to 5000 (5 seconds).", cxxopts::value(stats_interval)->default_value("5000"), "<msec>")
|
("stats-interval", "When using -s <stats_file>, write statistics every <msec> ms. This uses signals, so don't recommend intervals below 200 ms. Defaults to 5000 (5 seconds).", cxxopts::value(stats_interval)->default_value("5000"), "<msec>")
|
||||||
("S,snaplen", "Capture the first <len> bytes of each I/O buffer. By default, the first 80 bytes are captured. Use this option with caution, it can generate huge trace files.", cxxopts::value(snaplen)->default_value("0"), "<len>")
|
("S,snaplen", "Capture the first <len> bytes of each I/O buffer. By default, the first 80 bytes are captured. Use this option with caution, it can generate huge trace files.", cxxopts::value(snaplen)->default_value("0"), "<len>")
|
||||||
("support", "Print support information including version, rules files used, etc. and exit.", cxxopts::value(print_support)->default_value("false"))
|
("support", "Print support information including version, rules files used, etc. and exit.", cxxopts::value(print_support)->default_value("false"))
|
||||||
|
@@ -70,7 +70,7 @@ public:
|
|||||||
std::string pidfilename;
|
std::string pidfilename;
|
||||||
// Rules list as passed by the user, via cmdline option '-r'
|
// Rules list as passed by the user, via cmdline option '-r'
|
||||||
std::list<std::string> rules_filenames;
|
std::list<std::string> rules_filenames;
|
||||||
std::string stats_filename;
|
std::string output_file;
|
||||||
uint64_t stats_interval;
|
uint64_t stats_interval;
|
||||||
uint64_t snaplen;
|
uint64_t snaplen;
|
||||||
bool print_support;
|
bool print_support;
|
||||||
|
@@ -26,6 +26,7 @@ limitations under the License.
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "falco_utils.h"
|
#include "falco_utils.h"
|
||||||
|
#include "falco_metrics.h"
|
||||||
|
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
@@ -60,7 +61,7 @@ falco_configuration::falco_configuration():
|
|||||||
m_cpus_for_each_syscall_buffer(2),
|
m_cpus_for_each_syscall_buffer(2),
|
||||||
m_syscall_drop_failed_exit(false),
|
m_syscall_drop_failed_exit(false),
|
||||||
m_base_syscalls_repair(false),
|
m_base_syscalls_repair(false),
|
||||||
m_stats_v2_enabled(false)
|
m_metrics_enabled(false)
|
||||||
{
|
{
|
||||||
init({});
|
init({});
|
||||||
}
|
}
|
||||||
@@ -339,15 +340,15 @@ void falco_configuration::load_yaml(const std::string& config_name, const yaml_h
|
|||||||
config.get_sequence<std::unordered_set<std::string>>(m_base_syscalls_custom_set, std::string("base_syscalls.custom_set"));
|
config.get_sequence<std::unordered_set<std::string>>(m_base_syscalls_custom_set, std::string("base_syscalls.custom_set"));
|
||||||
m_base_syscalls_repair = config.get_scalar<bool>("base_syscalls.repair", false);
|
m_base_syscalls_repair = config.get_scalar<bool>("base_syscalls.repair", false);
|
||||||
|
|
||||||
m_stats_v2_enabled = config.get_scalar<bool>("stats_v2.enabled", false);
|
m_metrics_enabled = config.get_scalar<bool>("metrics.enabled", false);
|
||||||
m_stats_v2_stats_interval_preset = config.get_scalar<uint16_t>("stats_v2.stats_interval_preset", 0);
|
m_metrics_interval_str = config.get_scalar<std::string>("metrics.interval", "0");
|
||||||
m_stats_v2_stats_interval_ms = config.get_scalar<uint64_t>("stats_v2.stats_interval_ms", 0);
|
m_metrics_interval = falco::metrics::parse_metrics_interval(m_metrics_interval_str);
|
||||||
m_stats_v2_stats_internal_rule = config.get_scalar<bool>("stats_v2.stats_internal_rule", true);
|
m_metrics_stats_rule_enabled = config.get_scalar<bool>("metrics.stats_rule_enabled", true);
|
||||||
m_stats_v2_stats_filename = config.get_scalar<std::string>("stats_v2.stats_filename", "");
|
m_metrics_output_file = config.get_scalar<std::string>("metrics.output_file", "");
|
||||||
m_stats_v2_include_resource_utilization = config.get_scalar<bool>("stats_v2.include_resource_utilization", true);
|
m_metrics_resource_utilization_enabled = config.get_scalar<bool>("metrics.resource_utilization_enabled", true);
|
||||||
m_stats_v2_include_kernel_evts_counters = config.get_scalar<bool>("stats_v2.include_kernel_evts_counters", true);
|
m_metrics_kernel_event_counters_enabled = config.get_scalar<bool>("metrics.kernel_event_counters_enabled", true);
|
||||||
m_stats_v2_include_libbpf_stats = config.get_scalar<bool>("stats_v2.include_libbpf_stats", true);
|
m_metrics_libbpf_stats_enabled = config.get_scalar<bool>("metrics.libbpf_stats_enabled", true);
|
||||||
m_stats_v2_convert_memory_to_mb = config.get_scalar<bool>("stats_v2.convert_memory_to_mb", true);
|
m_metrics_convert_memory_to_mb = config.get_scalar<bool>("metrics.convert_memory_to_mb", true);
|
||||||
|
|
||||||
std::vector<std::string> load_plugins;
|
std::vector<std::string> load_plugins;
|
||||||
|
|
||||||
|
@@ -112,16 +112,16 @@ public:
|
|||||||
std::unordered_set<std::string> m_base_syscalls_custom_set;
|
std::unordered_set<std::string> m_base_syscalls_custom_set;
|
||||||
bool m_base_syscalls_repair;
|
bool m_base_syscalls_repair;
|
||||||
|
|
||||||
// stats_v2 configs
|
// metrics configs
|
||||||
bool m_stats_v2_enabled;
|
bool m_metrics_enabled;
|
||||||
uint16_t m_stats_v2_stats_interval_preset;
|
std::string m_metrics_interval_str;
|
||||||
uint64_t m_stats_v2_stats_interval_ms;
|
uint64_t m_metrics_interval;
|
||||||
bool m_stats_v2_stats_internal_rule;
|
bool m_metrics_stats_rule_enabled;
|
||||||
std::string m_stats_v2_stats_filename;
|
std::string m_metrics_output_file;
|
||||||
bool m_stats_v2_include_resource_utilization;
|
bool m_metrics_resource_utilization_enabled;
|
||||||
bool m_stats_v2_include_kernel_evts_counters;
|
bool m_metrics_kernel_event_counters_enabled;
|
||||||
bool m_stats_v2_include_libbpf_stats;
|
bool m_metrics_libbpf_stats_enabled;
|
||||||
bool m_stats_v2_convert_memory_to_mb;
|
bool m_metrics_convert_memory_to_mb;
|
||||||
|
|
||||||
std::vector<plugin_config> m_plugins;
|
std::vector<plugin_config> m_plugins;
|
||||||
|
|
||||||
|
@@ -26,6 +26,7 @@ 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
|
||||||
@@ -157,7 +158,7 @@ stats_writer::collector::collector(std::shared_ptr<stats_writer> writer)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, std::string> stats_writer::collector::get_stats_v2_output_fields_wrapper(std::shared_ptr<sinsp> inspector, uint64_t now, std::string src, uint64_t num_evts, double stats_snapshot_time_delta_sec)
|
std::map<std::string, std::string> stats_writer::collector::get_metrics_output_fields_wrapper(std::shared_ptr<sinsp> inspector, uint64_t now, std::string src, uint64_t num_evts, double stats_snapshot_time_delta_sec)
|
||||||
{
|
{
|
||||||
std::map<std::string, std::string> output_fields;
|
std::map<std::string, std::string> output_fields;
|
||||||
const scap_agent_info* agent_info = inspector->get_agent_info();
|
const scap_agent_info* agent_info = inspector->get_agent_info();
|
||||||
@@ -203,7 +204,7 @@ std::map<std::string, std::string> stats_writer::collector::get_stats_v2_output_
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, std::string> stats_writer::collector::get_stats_v2_output_fields_additional(std::shared_ptr<sinsp> inspector, std::map<std::string, std::string> output_fields, double stats_snapshot_time_delta_sec, std::string src)
|
std::map<std::string, std::string> stats_writer::collector::get_metrics_output_fields_additional(std::shared_ptr<sinsp> inspector, std::map<std::string, std::string> output_fields, double stats_snapshot_time_delta_sec, std::string src)
|
||||||
{
|
{
|
||||||
const scap_agent_info* agent_info = inspector->get_agent_info();
|
const scap_agent_info* agent_info = inspector->get_agent_info();
|
||||||
const scap_machine_info* machine_info = inspector->get_machine_info();
|
const scap_machine_info* machine_info = inspector->get_machine_info();
|
||||||
@@ -212,7 +213,7 @@ std::map<std::string, std::string> stats_writer::collector::get_stats_v2_output_
|
|||||||
/* Resource utilization, CPU and memory usage etc. */
|
/* Resource utilization, CPU and memory usage etc. */
|
||||||
uint32_t nstats = 0;
|
uint32_t nstats = 0;
|
||||||
int32_t rc = 0;
|
int32_t rc = 0;
|
||||||
if (m_writer->m_config->m_stats_v2_include_resource_utilization)
|
if (m_writer->m_config->m_metrics_resource_utilization_enabled)
|
||||||
{
|
{
|
||||||
const scap_stats_v2* utilization;
|
const scap_stats_v2* utilization;
|
||||||
auto buffer = inspector->get_sinsp_stats_v2_buffer();
|
auto buffer = inspector->get_sinsp_stats_v2_buffer();
|
||||||
@@ -225,7 +226,7 @@ std::map<std::string, std::string> stats_writer::collector::get_stats_v2_output_
|
|||||||
switch(utilization[stat].type)
|
switch(utilization[stat].type)
|
||||||
{
|
{
|
||||||
case STATS_VALUE_TYPE_U64:
|
case STATS_VALUE_TYPE_U64:
|
||||||
if (m_writer->m_config->m_stats_v2_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[utilization[stat].name] = std::to_string(utilization[stat].value.u64 / (double)1024 / (double)1024);
|
||||||
}
|
}
|
||||||
@@ -235,7 +236,7 @@ std::map<std::string, std::string> stats_writer::collector::get_stats_v2_output_
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case STATS_VALUE_TYPE_U32:
|
case STATS_VALUE_TYPE_U32:
|
||||||
if (m_writer->m_config->m_stats_v2_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[utilization[stat].name] = std::to_string(utilization[stat].value.u32 / (double)1024);
|
||||||
}
|
}
|
||||||
@@ -264,11 +265,11 @@ std::map<std::string, std::string> stats_writer::collector::get_stats_v2_output_
|
|||||||
rc = 0;
|
rc = 0;
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
|
|
||||||
if (m_writer->m_config->m_stats_v2_include_kernel_evts_counters)
|
if (m_writer->m_config->m_metrics_kernel_event_counters_enabled)
|
||||||
{
|
{
|
||||||
flags |= PPM_SCAP_STATS_KERNEL_COUNTERS;
|
flags |= PPM_SCAP_STATS_KERNEL_COUNTERS;
|
||||||
}
|
}
|
||||||
if (m_writer->m_config->m_stats_v2_include_libbpf_stats && !inspector->check_current_engine(KMOD_ENGINE) && (machine_info->flags & PPM_BPF_STATS_ENABLED))
|
if (m_writer->m_config->m_metrics_libbpf_stats_enabled && !inspector->check_current_engine(KMOD_ENGINE) && (machine_info->flags & PPM_BPF_STATS_ENABLED))
|
||||||
{
|
{
|
||||||
flags |= PPM_SCAP_STATS_LIBBPF_STATS;
|
flags |= PPM_SCAP_STATS_LIBBPF_STATS;
|
||||||
}
|
}
|
||||||
@@ -316,7 +317,7 @@ std::map<std::string, std::string> stats_writer::collector::get_stats_v2_output_
|
|||||||
|
|
||||||
void stats_writer::collector::collect(std::shared_ptr<sinsp> inspector, const std::string &src, uint64_t num_evts)
|
void stats_writer::collector::collect(std::shared_ptr<sinsp> inspector, const std::string &src, uint64_t num_evts)
|
||||||
{
|
{
|
||||||
if (m_writer->m_config->m_stats_v2_enabled || m_writer->has_output())
|
if (m_writer->m_config->m_metrics_enabled || m_writer->has_output())
|
||||||
{
|
{
|
||||||
/* Collect stats / metrics once per ticker period. */
|
/* Collect stats / metrics once per ticker period. */
|
||||||
auto tick = stats_writer::get_ticker();
|
auto tick = stats_writer::get_ticker();
|
||||||
@@ -332,15 +333,15 @@ void stats_writer::collector::collect(std::shared_ptr<sinsp> inspector, const st
|
|||||||
double stats_snapshot_time_delta_sec = (stats_snapshot_time_delta / (double)ONE_SECOND_IN_NS);
|
double stats_snapshot_time_delta_sec = (stats_snapshot_time_delta / (double)ONE_SECOND_IN_NS);
|
||||||
|
|
||||||
/* Get respective metrics output_fields. */
|
/* Get respective metrics output_fields. */
|
||||||
std::map<std::string, std::string> output_fields = stats_writer::collector::get_stats_v2_output_fields_wrapper(inspector, now, src, num_evts, stats_snapshot_time_delta_sec);
|
std::map<std::string, std::string> output_fields = stats_writer::collector::get_metrics_output_fields_wrapper(inspector, now, src, num_evts, stats_snapshot_time_delta_sec);
|
||||||
output_fields = stats_writer::collector::get_stats_v2_output_fields_additional(inspector, output_fields, stats_snapshot_time_delta_sec, src);
|
output_fields = stats_writer::collector::get_metrics_output_fields_additional(inspector, output_fields, stats_snapshot_time_delta_sec, src);
|
||||||
|
|
||||||
/* Pipe to respective output. */
|
/* Pipe to respective output. */
|
||||||
if (m_writer->m_config->m_stats_v2_enabled && m_writer->m_config->m_stats_v2_stats_internal_rule && m_writer->m_outputs)
|
if (m_writer->m_config->m_metrics_enabled && m_writer->m_config->m_metrics_stats_rule_enabled && m_writer->m_outputs)
|
||||||
{
|
{
|
||||||
std::string rule = "Falco internal: resource utilization stats metrics";
|
std::string rule = "Falco internal: resource utilization stats metrics";
|
||||||
std::string msg = "";
|
std::string msg = "";
|
||||||
m_writer->m_outputs->handle_msg(now, falco_common::PRIORITY_DEBUG, msg, rule, output_fields);
|
m_writer->m_outputs->handle_msg(now, falco_common::PRIORITY_INFORMATIONAL, msg, rule, output_fields);
|
||||||
}
|
}
|
||||||
if (m_writer->has_output())
|
if (m_writer->has_output())
|
||||||
{
|
{
|
||||||
|
@@ -63,14 +63,14 @@ public:
|
|||||||
void collect(std::shared_ptr<sinsp> inspector, const std::string& src, uint64_t num_evts);
|
void collect(std::shared_ptr<sinsp> inspector, const std::string& src, uint64_t num_evts);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Collect snapshot stats v2 wrapper fields as internal rule formatted output fields.
|
\brief Collect snapshot metrics wrapper fields as internal rule formatted output fields.
|
||||||
*/
|
*/
|
||||||
std::map<std::string, std::string> get_stats_v2_output_fields_wrapper(std::shared_ptr<sinsp> inspector, uint64_t now, std::string src, uint64_t num_evts, double stats_snapshot_time_delta_sec);
|
std::map<std::string, std::string> get_metrics_output_fields_wrapper(std::shared_ptr<sinsp> inspector, uint64_t now, std::string src, uint64_t num_evts, double stats_snapshot_time_delta_sec);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Collect snapshot stats v2 syscalls related metrics as internal rule formatted output fields.
|
\brief Collect snapshot metrics syscalls related metrics as internal rule formatted output fields.
|
||||||
*/
|
*/
|
||||||
std::map<std::string, std::string> get_stats_v2_output_fields_additional(std::shared_ptr<sinsp> inspector, std::map<std::string, std::string> output_fields, double stats_snapshot_time_delta_sec, std::string src);
|
std::map<std::string, std::string> get_metrics_output_fields_additional(std::shared_ptr<sinsp> inspector, std::map<std::string, std::string> output_fields, double stats_snapshot_time_delta_sec, std::string src);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<stats_writer> m_writer;
|
std::shared_ptr<stats_writer> m_writer;
|
||||||
|
Reference in New Issue
Block a user