Skip to content

Commit 2c634a1

Browse files
authored
Merge pull request #78 from open-telemetry/main
merge from upstream
2 parents 82b495d + 7402ed9 commit 2c634a1

File tree

8 files changed

+181
-32
lines changed

8 files changed

+181
-32
lines changed

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,10 @@ option(WITH_ASYNC_EXPORT_PREVIEW "Whether to enable async export" OFF)
287287
option(WITH_METRICS_EXEMPLAR_PREVIEW
288288
"Whether to enable exemplar within metrics" OFF)
289289

290+
option(OPENTELEMETRY_SKIP_DYNAMIC_LOADING_TESTS
291+
"Whether to build test libraries that are always linked as shared libs"
292+
OFF)
293+
290294
#
291295
# Verify options dependencies
292296
#

api/test/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,7 @@ add_subdirectory(metrics)
1010
add_subdirectory(logs)
1111
add_subdirectory(common)
1212
add_subdirectory(baggage)
13-
add_subdirectory(singleton)
13+
14+
if(NOT OPENTELEMETRY_SKIP_DYNAMIC_LOADING_TESTS)
15+
add_subdirectory(singleton)
16+
endif()

examples/plugin/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@
22
# SPDX-License-Identifier: Apache-2.0
33

44
add_subdirectory(load)
5-
add_subdirectory(plugin)
5+
6+
if(NOT OPENTELEMETRY_SKIP_DYNAMIC_LOADING_TESTS)
7+
add_subdirectory(plugin)
8+
endif()

exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_options.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ struct OPENTELEMETRY_EXPORT PrometheusExporterOptions
2828

2929
// Populating otel_scope_name/otel_scope_labels attributes
3030
bool without_otel_scope = false;
31+
32+
// Option to export metrics without the unit suffix
33+
bool without_units = false;
34+
35+
// Option to export metrics without the type suffix
36+
bool without_type_suffix = false;
3137
};
3238

3339
} // namespace metrics

exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,18 @@ class OPENTELEMETRY_EXPORT_TYPE PrometheusExporterUtils
3232
* @param populate_target_info whether to populate target_info
3333
* @param without_otel_scope whether to populate otel_scope_name and otel_scope_version
3434
* attributes
35+
* @param without_units exporter configuration controlling whether to append unit suffix in
36+
* the exported metrics.
37+
* @param without_type_suffix exporter configuration controlling whether to append type suffix in
38+
* the exported metrics.
3539
* @return a collection of translated metrics that is acceptable by Prometheus
3640
*/
3741
static std::vector<::prometheus::MetricFamily> TranslateToPrometheus(
3842
const sdk::metrics::ResourceMetrics &data,
3943
bool populate_target_info = true,
40-
bool without_otel_scope = false);
44+
bool without_otel_scope = false,
45+
bool without_units = false,
46+
bool without_type_suffix = false);
4147

4248
private:
4349
/**
@@ -63,7 +69,9 @@ class OPENTELEMETRY_EXPORT_TYPE PrometheusExporterUtils
6369

6470
static std::string MapToPrometheusName(const std::string &name,
6571
const std::string &unit,
66-
::prometheus::MetricType prometheus_type);
72+
::prometheus::MetricType prometheus_type,
73+
bool without_units,
74+
bool without_type_suffix);
6775

6876
/**
6977
* A utility function that returns the equivalent Prometheus name for the provided OTLP metric

exporters/prometheus/src/exporter_options.cc

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,33 @@ inline bool GetPrometheusPopulateTargetInfo()
4848
return exists ? setting : true;
4949
}
5050

51+
inline bool GetPrometheusWithoutUnits()
52+
{
53+
constexpr char kPrometheusWithoutUnits[] = "OTEL_CPP_PROMETHEUS_EXPORTER_WITHOUT_UNITS";
54+
bool setting;
55+
const auto exists =
56+
opentelemetry::sdk::common::GetBoolEnvironmentVariable(kPrometheusWithoutUnits, setting);
57+
58+
return exists ? setting : false;
59+
}
60+
61+
inline bool GetPrometheusWithoutTypeSuffix()
62+
{
63+
constexpr char kPrometheusWithoutTypeSuffix[] =
64+
"OTEL_CPP_PROMETHEUS_EXPORTER_WITHOUT_TYPE_SUFFIX";
65+
bool setting;
66+
const auto exists =
67+
opentelemetry::sdk::common::GetBoolEnvironmentVariable(kPrometheusWithoutTypeSuffix, setting);
68+
69+
return exists ? setting : false;
70+
}
71+
5172
PrometheusExporterOptions::PrometheusExporterOptions()
5273
: url(GetPrometheusDefaultHttpEndpoint()),
5374
populate_target_info(GetPrometheusPopulateTargetInfo()),
54-
without_otel_scope(GetPrometheusWithoutOtelScope())
75+
without_otel_scope(GetPrometheusWithoutOtelScope()),
76+
without_units(GetPrometheusWithoutUnits()),
77+
without_type_suffix(GetPrometheusWithoutTypeSuffix())
5578
{}
5679

5780
} // namespace metrics

exporters/prometheus/src/exporter_utils.cc

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,15 @@ std::string SanitizeLabel(std::string label_key)
102102
* Helper function to convert OpenTelemetry metrics data collection
103103
* to Prometheus metrics data collection
104104
*
105-
* @param records a collection of metrics in OpenTelemetry
105+
* @param data a collection of metrics in OpenTelemetry
106106
* @return a collection of translated metrics that is acceptable by Prometheus
107107
*/
108108
std::vector<prometheus_client::MetricFamily> PrometheusExporterUtils::TranslateToPrometheus(
109109
const sdk::metrics::ResourceMetrics &data,
110110
bool populate_target_info,
111-
bool without_otel_scope)
111+
bool without_otel_scope,
112+
bool without_units,
113+
bool without_type_suffix)
112114
{
113115

114116
// initialize output vector
@@ -150,7 +152,8 @@ std::vector<prometheus_client::MetricFamily> PrometheusExporterUtils::TranslateT
150152
}
151153
const prometheus_client::MetricType type = TranslateType(kind, is_monotonic);
152154
metric_family.name = MapToPrometheusName(metric_data.instrument_descriptor.name_,
153-
metric_data.instrument_descriptor.unit_, type);
155+
metric_data.instrument_descriptor.unit_, type,
156+
without_units, without_type_suffix);
154157
metric_family.type = type;
155158
const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope =
156159
without_otel_scope ? nullptr : instrumentation_info.scope_;
@@ -492,34 +495,43 @@ std::string PrometheusExporterUtils::CleanUpString(const std::string &str)
492495
std::string PrometheusExporterUtils::MapToPrometheusName(
493496
const std::string &name,
494497
const std::string &unit,
495-
prometheus_client::MetricType prometheus_type)
498+
prometheus_client::MetricType prometheus_type,
499+
bool without_units,
500+
bool without_type_suffix)
496501
{
497-
auto sanitized_name = SanitizeNames(name);
498-
std::string prometheus_equivalent_unit = GetEquivalentPrometheusUnit(unit);
499-
500-
// Append prometheus unit if not null or empty.
501-
if (!prometheus_equivalent_unit.empty() &&
502-
sanitized_name.find(prometheus_equivalent_unit) == std::string::npos)
503-
{
504-
sanitized_name += "_" + prometheus_equivalent_unit;
505-
}
506-
507-
// Special case - counter
508-
if (prometheus_type == prometheus_client::MetricType::Counter)
509-
{
510-
auto t_pos = sanitized_name.rfind("_total");
511-
bool ends_with_total = t_pos == sanitized_name.size() - 6;
512-
if (!ends_with_total)
502+
auto sanitized_name = SanitizeNames(name);
503+
// append unit suffixes
504+
if (!without_units)
505+
{
506+
std::string prometheus_equivalent_unit = GetEquivalentPrometheusUnit(unit);
507+
// Append prometheus unit if not null or empty.
508+
if (!prometheus_equivalent_unit.empty() &&
509+
sanitized_name.find(prometheus_equivalent_unit) == std::string::npos)
513510
{
514-
sanitized_name += "_total";
511+
sanitized_name += "_" + prometheus_equivalent_unit;
512+
}
513+
// Special case - gauge
514+
if (unit == "1" && prometheus_type == prometheus_client::MetricType::Gauge &&
515+
sanitized_name.find("ratio") == std::string::npos)
516+
{
517+
// this is replacing the unit name
518+
sanitized_name += "_ratio";
515519
}
516520
}
517521

518-
// Special case - gauge
519-
if (unit == "1" && prometheus_type == prometheus_client::MetricType::Gauge &&
520-
sanitized_name.find("ratio") == std::string::npos)
522+
// append type suffixes
523+
if (!without_type_suffix)
521524
{
522-
sanitized_name += "_ratio";
525+
// Special case - counter
526+
if (prometheus_type == prometheus_client::MetricType::Counter)
527+
{
528+
auto t_pos = sanitized_name.rfind("_total");
529+
bool ends_with_total = t_pos == sanitized_name.size() - 6;
530+
if (!ends_with_total)
531+
{
532+
sanitized_name += "_total";
533+
}
534+
}
523535
}
524536

525537
return CleanUpString(SanitizeNames(sanitized_name));

exporters/prometheus/test/exporter_utils_test.cc

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,12 @@ class SanitizeNameTester
5454
}
5555
static std::string mapToPrometheusName(const std::string &name,
5656
const std::string &unit,
57-
prometheus_client::MetricType prometheus_type)
57+
prometheus_client::MetricType prometheus_type,
58+
bool without_units = false,
59+
bool without_type_suffix = false)
5860
{
59-
return PrometheusExporterUtils::MapToPrometheusName(name, unit, prometheus_type);
61+
return PrometheusExporterUtils::MapToPrometheusName(name, unit, prometheus_type, without_units,
62+
without_type_suffix);
6063
}
6164
};
6265
} // namespace metrics
@@ -419,6 +422,93 @@ TEST(PrometheusExporterUtils, ConvertRateExpressedToPrometheusUnit)
419422
"_per_minute");
420423
}
421424

425+
TEST(PromentheusExporterUtils, PrometheusNameMapping)
426+
{
427+
// General test cases on unit expansions and name sanitization
428+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
429+
"sample_metric___name", "g", prometheus::MetricType::Counter),
430+
"sample_metric_name_grams_total");
431+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
432+
"sample_metric_name", "s", prometheus::MetricType::Counter),
433+
"sample_metric_name_seconds_total");
434+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
435+
"sample_metric_name", "s", prometheus::MetricType::Gauge),
436+
"sample_metric_name_seconds");
437+
// Test without_units & without_type_suffix with Counters and unit = 1
438+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
439+
"sample_metric_name", "1", prometheus::MetricType::Counter),
440+
"sample_metric_name_total");
441+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
442+
"sample_metric_name", "1", prometheus::MetricType::Counter, true, false),
443+
"sample_metric_name_total");
444+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
445+
"sample_metric_name", "1", prometheus::MetricType::Counter, false, true),
446+
"sample_metric_name");
447+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
448+
"sample_metric_name", "1", prometheus::MetricType::Counter, true, true),
449+
"sample_metric_name");
450+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
451+
"sample_metric_name", "1", prometheus::MetricType::Counter, true, true),
452+
"sample_metric_name");
453+
// Test without_units & without_type_suffix with Counters and non-special units
454+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
455+
"sample_metric_name", "%", prometheus::MetricType::Counter),
456+
"sample_metric_name_percent_total");
457+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
458+
"sample_metric_name", "m", prometheus::MetricType::Counter, true, false),
459+
"sample_metric_name_total");
460+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
461+
"sample_metric_name", "By", prometheus::MetricType::Counter, false, true),
462+
"sample_metric_name_bytes");
463+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
464+
"sample_metric_name", "s", prometheus::MetricType::Counter, true, true),
465+
"sample_metric_name");
466+
// Special case Gauges & ratio
467+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
468+
"sample_metric_name", "1", prometheus::MetricType::Gauge),
469+
"sample_metric_name_ratio");
470+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
471+
"sample_metric_name", "1", prometheus::MetricType::Gauge, false, true),
472+
"sample_metric_name_ratio");
473+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
474+
"sample_metric_name", "1", prometheus::MetricType::Gauge, true, false),
475+
"sample_metric_name");
476+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
477+
"sample_metric_name", "1", prometheus::MetricType::Gauge, true, true),
478+
"sample_metric_name");
479+
// Test without_type_suffix affects only counters
480+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
481+
"sample_metric_name", "Hz", prometheus::MetricType::Counter),
482+
"sample_metric_name_hertz_total");
483+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
484+
"sample_metric_name", "Hz", prometheus::MetricType::Counter, false, true),
485+
"sample_metric_name_hertz");
486+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
487+
"sample_metric_name", "Hz", prometheus::MetricType::Gauge),
488+
"sample_metric_name_hertz");
489+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
490+
"sample_metric_name", "Hz", prometheus::MetricType::Gauge, false, true),
491+
"sample_metric_name_hertz");
492+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
493+
"sample_metric_name", "Hz", prometheus::MetricType::Histogram),
494+
"sample_metric_name_hertz");
495+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
496+
"sample_metric_name", "Hz", prometheus::MetricType::Histogram, false, true),
497+
"sample_metric_name_hertz");
498+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
499+
"sample_metric_name", "Hz", prometheus::MetricType::Summary),
500+
"sample_metric_name_hertz");
501+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
502+
"sample_metric_name", "Hz", prometheus::MetricType::Summary, false, true),
503+
"sample_metric_name_hertz");
504+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
505+
"sample_metric_name", "Hz", prometheus::MetricType::Info),
506+
"sample_metric_name_hertz");
507+
ASSERT_EQ(exporter::metrics::SanitizeNameTester::mapToPrometheusName(
508+
"sample_metric_name", "Hz", prometheus::MetricType::Info, false, true),
509+
"sample_metric_name_hertz");
510+
}
511+
422512
TEST_F(AttributeCollisionTest, JoinsCollidingKeys)
423513
{
424514
CheckTranslation({{"foo.a", "value1"}, {"foo_a", "value2"}}, {{"foo_a", "value1;value2"},

0 commit comments

Comments
 (0)