Skip to content

Commit a5e0212

Browse files
committed
impl(otel): copy service resource labels into metric labels
1 parent aa062cf commit a5e0212

File tree

2 files changed

+70
-1
lines changed

2 files changed

+70
-1
lines changed

google/cloud/opentelemetry/internal/time_series.cc

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
#include "absl/types/optional.h"
1516
#include "google/cloud/opentelemetry/internal/time_series.h"
1617
#include "google/cloud/opentelemetry/internal/monitored_resource.h"
1718
#include "google/cloud/internal/absl_str_replace_quiet.h"
@@ -20,14 +21,32 @@
2021
#include <opentelemetry/common/attribute_value.h>
2122
#include <opentelemetry/sdk/metrics/data/metric_data.h>
2223
#include <opentelemetry/sdk/metrics/export/metric_producer.h>
24+
#include <opentelemetry/sdk/resource/semantic_conventions.h>
2325
#include <cctype>
26+
#include <string>
27+
#include <unordered_map>
28+
#include <vector>
2429

2530
namespace google {
2631
namespace cloud {
2732
namespace otel_internal {
2833
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
2934
namespace {
3035

36+
struct OTelKeyMatch {
37+
std::vector<std::string> otel_keys;
38+
absl::optional<std::string> fallback = absl::nullopt;
39+
};
40+
41+
std::unordered_map<std::string, OTelKeyMatch> const kExtraLabelsLookup = {
42+
{"service_name",
43+
{{opentelemetry::sdk::resource::SemanticConventions::kServiceName}}},
44+
{"service_namespace",
45+
{{opentelemetry::sdk::resource::SemanticConventions::kServiceNamespace}}},
46+
{"service_instance_id",
47+
{{opentelemetry::sdk::resource::SemanticConventions::
48+
kServiceInstanceId}}}};
49+
3150
google::protobuf::Timestamp ToProtoTimestamp(
3251
opentelemetry::common::SystemTimestamp ts) {
3352
return internal::ToProtoTimestamp(
@@ -215,7 +234,7 @@ std::vector<google::monitoring::v3::TimeSeries> ToTimeSeries(
215234
}
216235
}
217236
}
218-
return tss;
237+
return WithExtraLabels(data, tss);
219238
}
220239

221240
std::vector<google::monitoring::v3::CreateTimeSeriesRequest> ToRequests(
@@ -236,6 +255,41 @@ std::vector<google::monitoring::v3::CreateTimeSeriesRequest> ToRequests(
236255
return requests;
237256
}
238257

258+
std::vector<google::monitoring::v3::TimeSeries> WithExtraLabels(
259+
opentelemetry::sdk::metrics::ResourceMetrics const& data,
260+
std::vector<google::monitoring::v3::TimeSeries>& tss) {
261+
if (!data.resource_) {
262+
return tss;
263+
}
264+
265+
opentelemetry::sdk::resource::ResourceAttributes const& attributes =
266+
data.resource_->GetAttributes();
267+
for (auto const& kv : kExtraLabelsLookup) {
268+
auto const& oks = kv.second.otel_keys;
269+
auto found = std::find_first_of(
270+
oks.begin(), oks.end(), attributes.begin(), attributes.end(),
271+
[](auto const& key, auto const& attr) { return key == attr.first; });
272+
273+
std::string value;
274+
if (found != oks.end()) {
275+
value = AsString(attributes.at(*found));
276+
} else if (kv.second.fallback) {
277+
value = *kv.second.fallback;
278+
}
279+
if (value.empty()) {
280+
continue;
281+
}
282+
283+
for (auto& ts : tss) {
284+
auto& labels = *((*ts.mutable_metric()).mutable_labels());
285+
if (labels.find(kv.first) == labels.end()) {
286+
labels[kv.first] = value;
287+
}
288+
}
289+
}
290+
return tss;
291+
}
292+
239293
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
240294
} // namespace otel_internal
241295
} // namespace cloud

google/cloud/opentelemetry/internal/time_series.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <google/api/monitored_resource.pb.h>
2222
#include <google/monitoring/v3/metric_service.pb.h>
2323
#include <opentelemetry/sdk/metrics/metric_reader.h>
24+
#include <opentelemetry/sdk/resource/resource.h>
2425
#include <functional>
2526
#include <string>
2627

@@ -89,6 +90,20 @@ std::vector<google::monitoring::v3::CreateTimeSeriesRequest> ToRequests(
8990
std::string const& project, google::api::MonitoredResource const& mr_proto,
9091
std::vector<google::monitoring::v3::TimeSeries> tss);
9192

93+
/**
94+
* Copy some resource labels into metric labels.
95+
*
96+
* Some resource labels need to be copied into metric labels as they are not
97+
* directly accepted by Google Cloud Monitoring as resource labels.
98+
*
99+
* For example, service resource labels need to be copied into metric labels.
100+
* See:
101+
* https://github.com/GoogleCloudPlatform/opentelemetry-operations-go/blob/main/exporter/collector/breaking-changes.md#labels
102+
*/
103+
std::vector<google::monitoring::v3::TimeSeries> WithExtraLabels(
104+
opentelemetry::sdk::metrics::ResourceMetrics const& data,
105+
std::vector<google::monitoring::v3::TimeSeries>& tss);
106+
92107
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
93108
} // namespace otel_internal
94109
} // namespace cloud

0 commit comments

Comments
 (0)