diff --git a/userspace/engine/CMakeLists.txt b/userspace/engine/CMakeLists.txt index 32c8c406..7ee9a1b9 100644 --- a/userspace/engine/CMakeLists.txt +++ b/userspace/engine/CMakeLists.txt @@ -15,7 +15,6 @@ set(FALCO_ENGINE_SOURCE_FILES falco_engine.cpp falco_load_result.cpp falco_utils.cpp - falco_metrics.cpp json_evt.cpp evttype_index_ruleset.cpp formats.cpp diff --git a/userspace/engine/falco_metrics.cpp b/userspace/engine/falco_metrics.cpp deleted file mode 100644 index 02368057..00000000 --- a/userspace/engine/falco_metrics.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* -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 -#include - -#include "falco_utils.h" -#include "utils.h" -#include "banned.h" // This raises a compilation error when certain functions are used - -#include - -// 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 DAY_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); - } - /* 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 \ No newline at end of file diff --git a/userspace/engine/falco_metrics.h b/userspace/engine/falco_metrics.h deleted file mode 100644 index 82664139..00000000 --- a/userspace/engine/falco_metrics.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -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 -#include -#include -#include -#include -#include -#include -#include -#include - -#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 diff --git a/userspace/engine/falco_utils.cpp b/userspace/engine/falco_utils.cpp index 53e71e42..ac9b6972 100644 --- a/userspace/engine/falco_utils.cpp +++ b/userspace/engine/falco_utils.cpp @@ -23,12 +23,123 @@ limitations under the License. #include "utils.h" #include "banned.h" // This raises a compilation error when certain functions are used +#include + +// 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 DAY_TO_MS * 365 + namespace falco { namespace utils { +uint64_t parse_prometheus_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); + } + /* 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; +} + std::string wrap_text(const std::string& in, uint32_t indent, uint32_t line_len) { std::istringstream is(in); diff --git a/userspace/engine/falco_utils.h b/userspace/engine/falco_utils.h index 73a6e006..9c149b08 100644 --- a/userspace/engine/falco_utils.h +++ b/userspace/engine/falco_utils.h @@ -43,6 +43,8 @@ namespace falco namespace utils { +uint64_t parse_prometheus_interval(std::string interval_str); + std::string wrap_text(const std::string& in, uint32_t indent, uint32_t linelen); void readfile(const std::string& filename, std::string& data); diff --git a/userspace/falco/app/actions/load_config.cpp b/userspace/falco/app/actions/load_config.cpp index 6f153081..52bd8794 100644 --- a/userspace/falco/app/actions/load_config.cpp +++ b/userspace/falco/app/actions/load_config.cpp @@ -15,7 +15,7 @@ limitations under the License. */ #include "actions.h" -#include "falco_metrics.h" +#include "falco_utils.h" using namespace falco::app; using namespace falco::app::actions; @@ -35,7 +35,7 @@ static void apply_deprecated_options( if (!opts.stats_interval.empty()) { cfg->m_metrics_interval_str = opts.stats_interval; - cfg->m_metrics_interval = falco::metrics::parse_metrics_interval(cfg->m_metrics_interval_str); + cfg->m_metrics_interval = falco::utils::parse_prometheus_interval(cfg->m_metrics_interval_str); } } } diff --git a/userspace/falco/configuration.cpp b/userspace/falco/configuration.cpp index 3b77f363..0e8b8665 100644 --- a/userspace/falco/configuration.cpp +++ b/userspace/falco/configuration.cpp @@ -26,7 +26,6 @@ limitations under the License. #include #include #include "falco_utils.h" -#include "falco_metrics.h" #include "configuration.h" #include "logger.h" @@ -350,7 +349,7 @@ void falco_configuration::load_yaml(const std::string& config_name, const yaml_h m_metrics_enabled = config.get_scalar("metrics.enabled", false); m_metrics_interval_str = config.get_scalar("metrics.interval", "5000"); - m_metrics_interval = falco::metrics::parse_metrics_interval(m_metrics_interval_str); + m_metrics_interval = falco::utils::parse_prometheus_interval(m_metrics_interval_str); m_metrics_stats_rule_enabled = config.get_scalar("metrics.output_rule", false); m_metrics_output_file = config.get_scalar("metrics.output_file", ""); m_metrics_resource_utilization_enabled = config.get_scalar("metrics.resource_utilization_enabled", true);