| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 9c0ff85 commit 3018564
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -20,6 +20,7 @@ | |||
| 20 | 20 | #include <opentelemetry/common/attribute_value.h> | |
| 21 | 21 | #include <opentelemetry/sdk/metrics/data/metric_data.h> | |
| 22 | 22 | #include <opentelemetry/sdk/metrics/export/metric_producer.h> | |
| 23 | + #include <opentelemetry/sdk/resource/semantic_conventions.h> | ||
| 23 | 24 | #include <cctype> | |
| 24 | 25 | ||
| 25 | 26 | namespace google { | |
@@ -28,6 +29,8 @@ namespace otel_internal { | |||
| 28 | 29 | GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN | |
| 29 | 30 | namespace { | |
| 30 | 31 | ||
| 32 | + namespace sc = opentelemetry::sdk::resource::SemanticConventions; | ||
| 33 | + | ||
| 31 | 34 | google::protobuf::Timestamp ToProtoTimestamp( | |
| 32 | 35 | opentelemetry::common::SystemTimestamp ts) { | |
| 33 | 36 | return internal::ToProtoTimestamp( | |
@@ -69,25 +72,46 @@ double AsDouble(opentelemetry::sdk::metrics::ValueType const& v) { | |||
| 69 | 72 | google::api::Metric ToMetric( | |
| 70 | 73 | opentelemetry::sdk::metrics::MetricData const& metric_data, | |
| 71 | 74 | opentelemetry::sdk::metrics::PointAttributes const& attributes, | |
| 75 | + opentelemetry::sdk::resource::Resource const* resource, | ||
| 72 | 76 | std::function<std::string(std::string)> const& name_formatter) { | |
| 73 | - google::api::Metric proto; | ||
| 74 | - proto.set_type(name_formatter(metric_data.instrument_descriptor.name_)); | ||
| 75 | - | ||
| 76 | - auto& labels = *proto.mutable_labels(); | ||
| 77 | - for (auto const& kv : attributes) { | ||
| 78 | - auto key = kv.first; | ||
| 77 | + auto add_label = [](auto& labels, auto key, auto const& value) { | ||
| 79 | 78 | // GCM labels match on the regex: R"([a-zA-Z_][a-zA-Z0-9_]*)". | |
| 80 | - if (key.empty()) continue; | ||
| 79 | + if (key.empty()) return; | ||
| 81 | 80 | if (!std::isalpha(key[0]) && key[0] != '_') { | |
| 82 | 81 | GCP_LOG(INFO) << "Dropping metric label which does not start with " | |
| 83 | 82 | "[A-Za-z_]: " | |
| 84 | 83 | << key; | |
| 85 | - continue; | ||
| 84 | + return; | ||
| 86 | 85 | } | |
| 87 | 86 | for (auto& c : key) { | |
| 88 | 87 | if (!std::isalnum(c)) c = '_'; | |
| 89 | 88 | } | |
| 90 | - labels[std::move(key)] = AsString(kv.second); | ||
| 89 | + labels[std::move(key)] = AsString(value); | ||
| 90 | + }; | ||
| 91 | + | ||
| 92 | + google::api::Metric proto; | ||
| 93 | + proto.set_type(name_formatter(metric_data.instrument_descriptor.name_)); | ||
| 94 | + | ||
| 95 | + auto& labels = *proto.mutable_labels(); | ||
| 96 | + if (resource) { | ||
| 97 | + // Copy several well-known labels from the resource into the metric, if they | ||
| 98 | + // exist. | ||
| 99 | + // | ||
| 100 | + // This avoids duplicate timeseries when multiple instances of a service are | ||
| 101 | + // running on a single monitored resource, for example running multiple | ||
| 102 | + // service processes on a single GCE VM. | ||
| 103 | + auto const& ra = resource->GetAttributes().GetAttributes(); | ||
| 104 | + for (std::string key : { | ||
| 105 | + sc::kServiceName, | ||
| 106 | + sc::kServiceNamespace, | ||
| 107 | + sc::kServiceInstanceId, | ||
| 108 | + }) { | ||
| 109 | + auto it = ra.find(std::move(key)); | ||
| 110 | + if (it != ra.end()) add_label(labels, it->first, it->second); | ||
| 111 | + } | ||
| 112 | + } | ||
| 113 | + for (auto const& kv : attributes) { | ||
| 114 | + add_label(labels, kv.first, kv.second); | ||
| 91 | 115 | } | |
| 92 | 116 | return proto; | |
| 93 | 117 | } | |
@@ -210,7 +234,8 @@ std::vector<google::monitoring::v3::TimeSeries> ToTimeSeries( | |||
| 210 | 234 | if (!ts) continue; | |
| 211 | 235 | ts->set_unit(metric_data.instrument_descriptor.unit_); | |
| 212 | 236 | *ts->mutable_metric() = | |
| 213 | - ToMetric(metric_data, pda.attributes, metrics_name_formatter); | ||
| 237 | + ToMetric(metric_data, pda.attributes, data.resource_, | ||
| 238 | + metrics_name_formatter); | ||
| 214 | 239 | tss.push_back(*std::move(ts)); | |
| 215 | 240 | } | |
| 216 | 241 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -21,6 +21,7 @@ | |||
| 21 | 21 | #include <google/api/monitored_resource.pb.h> | |
| 22 | 22 | #include <google/monitoring/v3/metric_service.pb.h> | |
| 23 | 23 | #include <opentelemetry/sdk/metrics/metric_reader.h> | |
| 24 | + #include <opentelemetry/sdk/resource/resource.h> | ||
| 24 | 25 | #include <functional> | |
| 25 | 26 | #include <string> | |
| 26 | 27 | ||
@@ -37,6 +38,7 @@ auto constexpr kMaxTimeSeriesPerRequest = 200; | |||
| 37 | 38 | google::api::Metric ToMetric( | |
| 38 | 39 | opentelemetry::sdk::metrics::MetricData const& metric_data, | |
| 39 | 40 | opentelemetry::sdk::metrics::PointAttributes const& attributes, | |
| 41 | + opentelemetry::sdk::resource::Resource const* resource, | ||
| 40 | 42 | std::function<std::string(std::string)> const& metrics_name_formatter); | |
| 41 | 43 | ||
| 42 | 44 | google::monitoring::v3::TimeSeries ToTimeSeries( | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -32,6 +32,8 @@ namespace otel_internal { | |||
| 32 | 32 | GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN | |
| 33 | 33 | namespace { | |
| 34 | 34 | ||
| 35 | + namespace sc = opentelemetry::sdk::resource::SemanticConventions; | ||
| 36 | + | ||
| 35 | 37 | using ::google::cloud::testing_util::IsProtoEqual; | |
| 36 | 38 | using ::google::protobuf::TextFormat; | |
| 37 | 39 | using ::testing::_; | |
@@ -133,7 +135,6 @@ auto Interval(std::chrono::system_clock::time_point start, | |||
| 133 | 135 | } | |
| 134 | 136 | ||
| 135 | 137 | auto TestResource() { | |
| 136 | - namespace sc = opentelemetry::sdk::resource::SemanticConventions; | ||
| 137 | 138 | return opentelemetry::sdk::resource::Resource::Create({ | |
| 138 | 139 | {sc::kCloudProvider, "gcp"}, | |
| 139 | 140 | {sc::kCloudPlatform, "gcp_compute_engine"}, | |
@@ -247,13 +248,13 @@ TEST(ToMetric, Simple) { | |||
| 247 | 248 | opentelemetry::sdk::metrics::PointAttributes attributes = { | |
| 248 | 249 | {"key1", "value1"}, {"_key2", "value2"}}; | |
| 249 | 250 | ||
| 250 | - auto metric = ToMetric(md, attributes, PrefixWithWorkload); | ||
| 251 | + auto metric = ToMetric(md, attributes, {}, PrefixWithWorkload); | ||
| 251 | 252 | ||
| 252 | 253 | EXPECT_EQ(metric.type(), "workload.googleapis.com/test"); | |
| 253 | 254 | EXPECT_THAT(metric.labels(), UnorderedElementsAre(Pair("key1", "value1"), | |
| 254 | 255 | Pair("_key2", "value2"))); | |
| 255 | 256 | ||
| 256 | - metric = ToMetric(md, {}, [](std::string s) { | ||
| 257 | + metric = ToMetric(md, {}, {}, [](std::string s) { | ||
| 257 | 258 | std::replace(s.begin(), s.end(), 't', 'T'); | |
| 258 | 259 | return "custom.googleapis.com/" + std::move(s); | |
| 259 | 260 | }); | |
@@ -266,7 +267,7 @@ TEST(ToMetric, BadLabelNames) { | |||
| 266 | 267 | opentelemetry::sdk::metrics::PointAttributes attributes = { | |
| 267 | 268 | {"99", "dropped"}, {"a key-with.bad/characters", "value"}}; | |
| 268 | 269 | ||
| 269 | - auto metric = ToMetric({}, attributes, PrefixWithWorkload); | ||
| 270 | + auto metric = ToMetric({}, attributes, {}, PrefixWithWorkload); | ||
| 270 | 271 | ||
| 271 | 272 | EXPECT_THAT(metric.labels(), | |
| 272 | 273 | UnorderedElementsAre(Pair("a_key_with_bad_characters", "value"))); | |
@@ -276,6 +277,53 @@ TEST(ToMetric, BadLabelNames) { | |||
| 276 | 277 | Contains(AllOf(HasSubstr("Dropping metric label"), HasSubstr("99")))); | |
| 277 | 278 | } | |
| 278 | 279 | ||
| 280 | + TEST(ToMetric, IncludesServiceLabelsFromResource) { | ||
| 281 | + opentelemetry::sdk::metrics::MetricData md; | ||
| 282 | + md.instrument_descriptor.name_ = "test"; | ||
| 283 | + | ||
| 284 | + opentelemetry::sdk::resource::ResourceAttributes resource_attributes = { | ||
| 285 | + {"unused", "unused"}, | ||
| 286 | + {sc::kServiceName, "test-name"}, | ||
| 287 | + {sc::kServiceNamespace, "test-namespace"}, | ||
| 288 | + {sc::kServiceInstanceId, "test-instance"}, | ||
| 289 | + }; | ||
| 290 | + auto resource = | ||
| 291 | + opentelemetry::sdk::resource::Resource::Create(resource_attributes); | ||
| 292 | + | ||
| 293 | + auto metric = ToMetric(md, {}, &resource, PrefixWithWorkload); | ||
| 294 | + EXPECT_THAT( | ||
| 295 | + metric.labels(), | ||
| 296 | + UnorderedElementsAre(Pair("service_name", "test-name"), | ||
| 297 | + Pair("service_namespace", "test-namespace"), | ||
| 298 | + Pair("service_instance_id", "test-instance"))); | ||
| 299 | + } | ||
| 300 | + | ||
| 301 | + TEST(ToMetric, PointAttributesOverServiceResourceAttributes) { | ||
| 302 | + opentelemetry::sdk::metrics::MetricData md; | ||
| 303 | + md.instrument_descriptor.name_ = "test"; | ||
| 304 | + | ||
| 305 | + opentelemetry::sdk::metrics::PointAttributes point_attributes = { | ||
| 306 | + {"service_name", "point-name"}, | ||
| 307 | + {"service_namespace", "point-namespace"}, | ||
| 308 | + {"service_instance_id", "point-instance"}, | ||
| 309 | + }; | ||
| 310 | + | ||
| 311 | + opentelemetry::sdk::resource::ResourceAttributes resource_attributes = { | ||
| 312 | + {sc::kServiceName, "resource-name"}, | ||
| 313 | + {sc::kServiceNamespace, "resource-namespace"}, | ||
| 314 | + {sc::kServiceInstanceId, "resource-instance"}, | ||
| 315 | + }; | ||
| 316 | + auto resource = | ||
| 317 | + opentelemetry::sdk::resource::Resource::Create(resource_attributes); | ||
| 318 | + | ||
| 319 | + auto metric = ToMetric(md, point_attributes, &resource, PrefixWithWorkload); | ||
| 320 | + EXPECT_THAT( | ||
| 321 | + metric.labels(), | ||
| 322 | + UnorderedElementsAre(Pair("service_name", "point-name"), | ||
| 323 | + Pair("service_namespace", "point-namespace"), | ||
| 324 | + Pair("service_instance_id", "point-instance"))); | ||
| 325 | + } | ||
| 326 | + | ||
| 279 | 327 | TEST(SumPointData, Simple) { | |
| 280 | 328 | auto const start = std::chrono::system_clock::now(); | |
| 281 | 329 | auto const end = start + std::chrono::seconds(5); | |
@@ -532,6 +580,7 @@ TEST(ToTimeSeries, Sum) { | |||
| 532 | 580 | ||
| 533 | 581 | opentelemetry::sdk::metrics::ResourceMetrics rm; | |
| 534 | 582 | rm.scope_metric_data_.push_back(std::move(sm)); | |
| 583 | + rm.resource_ = nullptr; | ||
| 535 | 584 | ||
| 536 | 585 | auto tss = ToTimeSeries(rm, PrefixWithWorkload); | |
| 537 | 586 | EXPECT_THAT(tss, ElementsAre(SumTimeSeries(), SumTimeSeries())); | |
@@ -556,6 +605,7 @@ TEST(ToTimeSeries, Gauge) { | |||
| 556 | 605 | ||
| 557 | 606 | opentelemetry::sdk::metrics::ResourceMetrics rm; | |
| 558 | 607 | rm.scope_metric_data_.push_back(std::move(sm)); | |
| 608 | + rm.resource_ = nullptr; | ||
| 559 | 609 | ||
| 560 | 610 | auto tss = ToTimeSeries(rm, PrefixWithWorkload); | |
| 561 | 611 | EXPECT_THAT(tss, ElementsAre(GaugeTimeSeries(), GaugeTimeSeries())); | |
@@ -580,6 +630,7 @@ TEST(ToTimeSeries, Histogram) { | |||
| 580 | 630 | ||
| 581 | 631 | opentelemetry::sdk::metrics::ResourceMetrics rm; | |
| 582 | 632 | rm.scope_metric_data_.push_back(std::move(sm)); | |
| 633 | + rm.resource_ = nullptr; | ||
| 583 | 634 | ||
| 584 | 635 | auto tss = ToTimeSeries(rm, PrefixWithWorkload); | |
| 585 | 636 | EXPECT_THAT(tss, ElementsAre(HistogramTimeSeries(), HistogramTimeSeries())); | |
@@ -604,6 +655,7 @@ TEST(ToTimeSeries, DropIgnored) { | |||
| 604 | 655 | ||
| 605 | 656 | opentelemetry::sdk::metrics::ResourceMetrics rm; | |
| 606 | 657 | rm.scope_metric_data_.push_back(std::move(sm)); | |
| 658 | + rm.resource_ = nullptr; | ||
| 607 | 659 | ||
| 608 | 660 | auto tss = ToTimeSeries(rm, PrefixWithWorkload); | |
| 609 | 661 | EXPECT_THAT(tss, IsEmpty()); | |
@@ -634,6 +686,7 @@ TEST(ToTimeSeries, Combined) { | |||
| 634 | 686 | ||
| 635 | 687 | opentelemetry::sdk::metrics::ResourceMetrics rm; | |
| 636 | 688 | rm.scope_metric_data_.push_back(std::move(sm)); | |
| 689 | + rm.resource_ = nullptr; | ||
| 637 | 690 | ||
| 638 | 691 | auto tss = ToTimeSeries( | |
| 639 | 692 | rm, [](std::string const& s) { return "custom.googleapis.com/" + s; }); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments