diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index 511e481c44..19dc1e88d6 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -1,6 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +#include #include #include #include @@ -13,6 +14,7 @@ #include "prometheus/metric_family.h" #include "prometheus/metric_type.h" +#include "opentelemetry/common/macros.h" #include "opentelemetry/exporters/prometheus/exporter_utils.h" #include "opentelemetry/sdk/metrics/export/metric_producer.h" #include "opentelemetry/sdk/resource/resource.h" @@ -280,11 +282,13 @@ std::string PrometheusExporterUtils::SanitizeNames(std::string name) return name; } +#if OPENTELEMETRY_HAVE_WORKING_REGEX std::regex INVALID_CHARACTERS_PATTERN("[^a-zA-Z0-9]"); std::regex CHARACTERS_BETWEEN_BRACES_PATTERN("\\{(.*?)\\}"); std::regex SANITIZE_LEADING_UNDERSCORES("^_+"); std::regex SANITIZE_TRAILING_UNDERSCORES("_+$"); std::regex SANITIZE_CONSECUTIVE_UNDERSCORES("[_]{2,}"); +#endif std::string PrometheusExporterUtils::GetEquivalentPrometheusUnit( const std::string &raw_metric_unit_name) @@ -360,7 +364,32 @@ std::string PrometheusExporterUtils::GetPrometheusPerUnit(const std::string &per std::string PrometheusExporterUtils::RemoveUnitPortionInBraces(const std::string &unit) { +#if OPENTELEMETRY_HAVE_WORKING_REGEX return std::regex_replace(unit, CHARACTERS_BETWEEN_BRACES_PATTERN, ""); +#else + bool in_braces = false; + std::string cleaned_unit; + cleaned_unit.reserve(unit.size()); + for (auto c : unit) + { + if (in_braces) + { + if (c == '}') + { + in_braces = false; + } + } + else if (c == '{') + { + in_braces = true; + } + else + { + cleaned_unit += c; + } + } + return cleaned_unit; +#endif } std::string PrometheusExporterUtils::ConvertRateExpressedToPrometheusUnit( @@ -389,12 +418,74 @@ std::string PrometheusExporterUtils::ConvertRateExpressedToPrometheusUnit( std::string PrometheusExporterUtils::CleanUpString(const std::string &str) { +#if OPENTELEMETRY_HAVE_WORKING_REGEX std::string cleaned_string = std::regex_replace(str, INVALID_CHARACTERS_PATTERN, "_"); cleaned_string = std::regex_replace(cleaned_string, SANITIZE_CONSECUTIVE_UNDERSCORES, "_"); cleaned_string = std::regex_replace(cleaned_string, SANITIZE_TRAILING_UNDERSCORES, ""); cleaned_string = std::regex_replace(cleaned_string, SANITIZE_LEADING_UNDERSCORES, ""); + return cleaned_string; +#else + std::string cleaned_string = str; + if (cleaned_string.empty()) + { + return cleaned_string; + } + std::transform(cleaned_string.begin(), cleaned_string.end(), cleaned_string.begin(), + [](const char c) { + if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) + { + return c; + } + return '_'; + }); + + std::string::size_type trim_start = 0; + std::string::size_type trim_end = 0; + bool previous_underscore = false; + for (std::string::size_type i = 0; i < cleaned_string.size(); ++i) + { + if (cleaned_string[i] == '_') + { + if (previous_underscore) + { + continue; + } + + previous_underscore = true; + } + else + { + previous_underscore = false; + } + + if (trim_end != i) + { + cleaned_string[trim_end] = cleaned_string[i]; + } + ++trim_end; + } + + while (trim_end > 0 && cleaned_string[trim_end - 1] == '_') + { + --trim_end; + } + while (trim_start < trim_end && cleaned_string[trim_start] == '_') + { + ++trim_start; + } + + // All characters are underscore + if (trim_start >= trim_end) + { + return "_"; + } + if (0 != trim_start || cleaned_string.size() != trim_end) + { + return cleaned_string.substr(trim_start, trim_end - trim_start); + } return cleaned_string; +#endif } std::string PrometheusExporterUtils::MapToPrometheusName(