cleanup(userspace): move parse_prometheus_interval to falco_utils

Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
This commit is contained in:
Melissa Kilby 2023-05-20 16:29:31 +00:00 committed by poiana
parent f2318a9ac5
commit fcecde845d
7 changed files with 116 additions and 198 deletions

View File

@ -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

View File

@ -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 <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 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

View File

@ -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 <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

View File

@ -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 <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 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);

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -26,7 +26,6 @@ limitations under the License.
#include <sys/stat.h>
#include <unistd.h>
#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<bool>("metrics.enabled", false);
m_metrics_interval_str = config.get_scalar<std::string>("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<bool>("metrics.output_rule", false);
m_metrics_output_file = config.get_scalar<std::string>("metrics.output_file", "");
m_metrics_resource_utilization_enabled = config.get_scalar<bool>("metrics.resource_utilization_enabled", true);