Skip to content

Commit

Permalink
[EXPORTER] Prometheus: Add unit to names, convert to word (#2213)
Browse files Browse the repository at this point in the history
  • Loading branch information
esigo authored Nov 22, 2023
1 parent 9b89843 commit 71d0e50
Show file tree
Hide file tree
Showing 3 changed files with 454 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <string>
#include <vector>
#include "opentelemetry/metrics/provider.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/sdk/metrics/meter.h"
#include "opentelemetry/version.h"

Expand Down Expand Up @@ -35,7 +36,17 @@ class PrometheusExporterUtils

private:
/**
* Append key-value pair to prometheus labels.
* Sanitize the given metric name or label according to Prometheus rule.
*
* This function is needed because names in OpenTelemetry can contain
* alphanumeric characters, '_', '.', and '-', whereas in Prometheus the
* name should only contain alphanumeric characters and '_'.
* @param name name
*/
static std::string SanitizeNames(std::string name);

/**
* Sanitize the given metric name or label according to Prometheus rule.
*
* @param name label name
* @param value label value
Expand All @@ -45,6 +56,79 @@ class PrometheusExporterUtils
std::string value,
std::vector<::prometheus::ClientMetric::Label> *labels);

static std::string MapToPrometheusName(const std::string &name,
const std::string &unit,
::prometheus::MetricType prometheus_type);

/**
* A utility function that returns the equivalent Prometheus name for the provided OTLP metric
* unit.
*
* @param raw_metric_unitName The raw metric unit for which Prometheus metric unit needs to be
* computed.
* @return the computed Prometheus metric unit equivalent of the OTLP metric unit
*/
static std::string GetEquivalentPrometheusUnit(const std::string &raw_metric_unitName);

/**
* This method retrieves the expanded Prometheus unit name for known abbreviations. OTLP metrics
* use the c/s notation as specified at <a href="https://ucum.org/ucum.html">UCUM</a>. The list of
* mappings is adopted from <a
* href="https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/9a9d4778bbbf242dba233db28e2fbcfda3416959/pkg/translator/prometheus/normalize_name.go#L30">OpenTelemetry
* Collector Contrib</a>.
*
* @param unit_abbreviation The unit that name that needs to be expanded/converted to Prometheus
* units.
* @return The expanded/converted unit name if known, otherwise returns the input unit name as-is.
*/
static std::string GetPrometheusUnit(const std::string &unit_abbreviation);

/**
* This method retrieves the expanded Prometheus unit name to be used with "per" units for known
* units. For example: s => per second (singular)
*
* @param per_unit_abbreviation The unit abbreviation used in a 'per' unit.
* @return The expanded unit equivalent to be used in 'per' unit if the input is a known unit,
* otherwise returns the input as-is.
*/
static std::string GetPrometheusPerUnit(const std::string &per_unit_abbreviation);

/**
* Replaces all characters that are not a letter or a digit with '_' to make the resulting string
* Prometheus compliant. This method also removes leading and trailing underscores - this is done
* to keep the resulting unit similar to what is produced from the collector's implementation.
*
* @param str The string input that needs to be made Prometheus compliant.
* @return the cleaned-up Prometheus compliant string.
*/
static std::string CleanUpString(const std::string &str);

/**
* This method is used to convert the units expressed as a rate via '/' symbol in their name to
* their expanded text equivalent. For instance, km/h => km_per_hour. The method operates on the
* input by splitting it in 2 parts - before and after '/' symbol and will attempt to expand any
* known unit abbreviation in both parts. Unknown abbreviations & unsupported characters will
* remain unchanged in the final output of this function.
*
* @param rate_expressed_unit The rate unit input that needs to be converted to its text
* equivalent.
* @return The text equivalent of unit expressed as rate. If the input does not contain '/', the
* function returns it as-is.
*/
static std::string ConvertRateExpressedToPrometheusUnit(const std::string &rate_expressed_unit);

/**
* This method drops all characters enclosed within '{}' (including the curly braces) by replacing
* them with an empty string. Note that this method will not produce the intended effect if there
* are nested curly braces within the outer enclosure of '{}'.
*
* <p>For instance, {packet{s}s} => s}.
*
* @param unit The input unit from which text within curly braces needs to be removed.
* @return The resulting unit after removing the text within '{}'.
*/
static std::string RemoveUnitPortionInBraces(const std::string &unit);

static opentelemetry::sdk::metrics::AggregationType getAggregationType(
const opentelemetry::sdk::metrics::PointType &point_type);

Expand All @@ -58,6 +142,7 @@ class PrometheusExporterUtils
* Add a target_info metric to collect resource attributes
*/
static void SetTarget(const sdk::metrics::ResourceMetrics &data,
std::chrono::nanoseconds time,
const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope,
std::vector<::prometheus::MetricFamily> *output);

Expand All @@ -70,6 +155,7 @@ class PrometheusExporterUtils
const opentelemetry::sdk::metrics::PointAttributes &labels,
const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope,
::prometheus::MetricType type,
std::chrono::nanoseconds time,
::prometheus::MetricFamily *metric_family,
const opentelemetry::sdk::resource::Resource *resource);

Expand All @@ -83,6 +169,7 @@ class PrometheusExporterUtils
const std::vector<uint64_t> &counts,
const opentelemetry::sdk::metrics::PointAttributes &labels,
const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope,
std::chrono::nanoseconds time,
::prometheus::MetricFamily *metric_family,
const opentelemetry::sdk::resource::Resource *resource);

Expand All @@ -92,6 +179,7 @@ class PrometheusExporterUtils
static void SetMetricBasic(
::prometheus::ClientMetric &metric,
const opentelemetry::sdk::metrics::PointAttributes &labels,
std::chrono::nanoseconds time,
const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope,
const opentelemetry::sdk::resource::Resource *resource);

Expand Down Expand Up @@ -122,6 +210,9 @@ class PrometheusExporterUtils
const std::vector<double> &boundaries,
const std::vector<uint64_t> &counts,
::prometheus::ClientMetric *metric);

// For testing
friend class SanitizeNameTester;
};
} // namespace metrics
} // namespace exporter
Expand Down
Loading

2 comments on commit 71d0e50

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark 'OpenTelemetry-cpp sdk Benchmark'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 2.

Benchmark suite Current: 71d0e50 Previous: 9b89843 Ratio
BM_BaselineBuffer/1 6298344.135284424 ns/iter 2442542.07611084 ns/iter 2.58

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark 'OpenTelemetry-cpp api Benchmark'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 2.

Benchmark suite Current: 71d0e50 Previous: 9b89843 Ratio
BM_ThreadYieldSpinLockThrashing/4/process_time/real_time 136.54088973999023 ms/iter 59.90898609161377 ms/iter 2.28

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.