Skip to content

Commit 809fc1b

Browse files
author
Douglas Barker
committed
[OTLP EXPORTER] include instrumentation scope attributes in otlp messages for metrics and traces
1 parent 150256c commit 809fc1b

File tree

9 files changed

+132
-19
lines changed

9 files changed

+132
-19
lines changed

exporters/otlp/include/opentelemetry/exporters/otlp/otlp_populate_attribute_utils.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "opentelemetry/common/attribute_value.h"
77
#include "opentelemetry/nostd/string_view.h"
88
#include "opentelemetry/sdk/common/attribute_utils.h"
9+
#include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h"
910
#include "opentelemetry/sdk/resource/resource.h"
1011
#include "opentelemetry/version.h"
1112

@@ -20,6 +21,7 @@ namespace v1
2021
{
2122
class AnyValue;
2223
class KeyValue;
24+
class InstrumentationScope;
2325
} // namespace v1
2426
} // namespace common
2527

@@ -49,6 +51,10 @@ class OtlpPopulateAttributeUtils
4951
static void PopulateAttribute(opentelemetry::proto::resource::v1::Resource *proto,
5052
const opentelemetry::sdk::resource::Resource &resource) noexcept;
5153

54+
static void PopulateAttribute(opentelemetry::proto::common::v1::InstrumentationScope *proto,
55+
const opentelemetry::sdk::instrumentationscope::InstrumentationScope
56+
&instrumentation_scope) noexcept;
57+
5258
static void PopulateAnyValue(opentelemetry::proto::common::v1::AnyValue *proto_value,
5359
const opentelemetry::common::AttributeValue &value) noexcept;
5460

exporters/otlp/src/otlp_metric_utils.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,8 @@ void OtlpMetricUtils::PopulateResourceMetrics(
242242
OtlpPopulateAttributeUtils::PopulateAttribute(resource_metrics->mutable_resource(),
243243
*(data.resource_));
244244

245+
resource_metrics->set_schema_url(data.resource_->GetSchemaURL());
246+
245247
for (auto &scope_metrics : data.scope_metric_data_)
246248
{
247249
if (scope_metrics.scope_ == nullptr)
@@ -252,7 +254,9 @@ void OtlpMetricUtils::PopulateResourceMetrics(
252254
proto::common::v1::InstrumentationScope *scope = scope_lib_metrics->mutable_scope();
253255
scope->set_name(scope_metrics.scope_->GetName());
254256
scope->set_version(scope_metrics.scope_->GetVersion());
255-
resource_metrics->set_schema_url(scope_metrics.scope_->GetSchemaURL());
257+
scope_lib_metrics->set_schema_url(scope_metrics.scope_->GetSchemaURL());
258+
259+
OtlpPopulateAttributeUtils::PopulateAttribute(scope, *scope_metrics.scope_);
256260

257261
for (auto &metric_data : scope_metrics.metric_data_)
258262
{

exporters/otlp/src/otlp_populate_attribute_utils.cc

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "opentelemetry/nostd/utility.h"
1616
#include "opentelemetry/nostd/variant.h"
1717
#include "opentelemetry/sdk/common/attribute_utils.h"
18+
#include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h"
1819
#include "opentelemetry/sdk/resource/resource.h"
1920
#include "opentelemetry/version.h"
2021

@@ -315,6 +316,22 @@ void OtlpPopulateAttributeUtils::PopulateAttribute(
315316
}
316317
}
317318

319+
void OtlpPopulateAttributeUtils::PopulateAttribute(
320+
opentelemetry::proto::common::v1::InstrumentationScope *proto,
321+
const opentelemetry::sdk::instrumentationscope::InstrumentationScope
322+
&instrumentation_scope) noexcept
323+
{
324+
if (nullptr == proto)
325+
{
326+
return;
327+
}
328+
329+
for (const auto &kv : instrumentation_scope.GetAttributes())
330+
{
331+
OtlpPopulateAttributeUtils::PopulateAttribute(proto->add_attributes(), kv.first, kv.second);
332+
}
333+
}
334+
318335
} // namespace otlp
319336
} // namespace exporter
320337
OPENTELEMETRY_END_NAMESPACE

exporters/otlp/src/otlp_recordable.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ proto::common::v1::InstrumentationScope OtlpRecordable::GetProtoInstrumentationS
107107
{
108108
instrumentation_scope.set_name(instrumentation_scope_->GetName());
109109
instrumentation_scope.set_version(instrumentation_scope_->GetVersion());
110+
OtlpPopulateAttributeUtils::PopulateAttribute(&instrumentation_scope, *instrumentation_scope_);
110111
}
111112
return instrumentation_scope;
112113
}

exporters/otlp/src/otlp_recordable_utils.cc

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ void OtlpRecordableUtils::PopulateRequest(
107107
proto::common::v1::InstrumentationScope instrumentation_scope_proto;
108108
instrumentation_scope_proto.set_name(input_scope_spans.first->GetName());
109109
instrumentation_scope_proto.set_version(input_scope_spans.first->GetVersion());
110+
OtlpPopulateAttributeUtils::PopulateAttribute(&instrumentation_scope_proto,
111+
*input_scope_spans.first);
112+
110113
*scope_spans->mutable_scope() = instrumentation_scope_proto;
111114
scope_spans->set_schema_url(input_scope_spans.first->GetSchemaURL());
112115
}
@@ -170,11 +173,7 @@ void OtlpRecordableUtils::PopulateRequest(
170173
proto_scope->set_name(input_scope_log.first->GetName());
171174
proto_scope->set_version(input_scope_log.first->GetVersion());
172175

173-
for (auto &scope_attribute : input_scope_log.first->GetAttributes())
174-
{
175-
OtlpPopulateAttributeUtils::PopulateAttribute(
176-
proto_scope->add_attributes(), scope_attribute.first, scope_attribute.second);
177-
}
176+
OtlpPopulateAttributeUtils::PopulateAttribute(proto_scope, *input_scope_log.first);
178177
}
179178
output_scope_log->set_schema_url(input_scope_log.first->GetSchemaURL());
180179
}

exporters/otlp/test/otlp_file_exporter_test.cc

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,27 @@ class OtlpFileExporterTestPeer : public ::testing::Test
108108
new sdk::trace::TracerProvider(std::move(processor), resource));
109109

110110
std::string report_trace_id;
111+
112+
const std::string instrumentation_scope_name{"test"};
113+
const std::string instrumentation_scope_version{"1.2.3"};
114+
const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"};
115+
116+
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
117+
const std::vector<std::pair<std::string, opentelemetry::common::AttributeValue>>
118+
instrumentation_scope_attributes{{"scope_key1", "scope_value"},
119+
{ "scope_key2",
120+
2 }};
121+
auto tracer = provider->GetTracer(instrumentation_scope_name, instrumentation_scope_version,
122+
schema_url, instrumentation_scope_attributes);
123+
#else
124+
auto tracer =
125+
provider->GetTracer(instrumentation_scope_name, instrumentation_scope_version, schema_url);
126+
#endif
111127

112-
char trace_id_hex[2 * trace_api::TraceId::kSize] = {0};
113-
auto tracer = provider->GetTracer("test");
114128
auto parent_span = tracer->StartSpan("Test parent span");
115129

130+
char trace_id_hex[2 * trace_api::TraceId::kSize] = {0};
131+
116132
trace_api::StartSpanOptions child_span_opts = {};
117133
child_span_opts.parent = parent_span->GetContext();
118134

@@ -138,8 +154,21 @@ class OtlpFileExporterTestPeer : public ::testing::Test
138154
{
139155
auto resource_span = *check_json["resourceSpans"].begin();
140156
auto scope_span = *resource_span["scopeSpans"].begin();
157+
auto scope = scope_span["scope"];
141158
auto span = *scope_span["spans"].begin();
142-
auto received_trace_id = span["traceId"].get<std::string>();
159+
160+
const std::string received_schema_url = scope_span["schemaUrl"].get<std::string>();
161+
const std::string received_instrumentation_scope_name = scope["name"].get<std::string>();
162+
const std::string received_instrumentation_scope_version = scope["version"].get<std::string>();
163+
const auto received_trace_id = span["traceId"].get<std::string>();
164+
165+
#if OPENTELEMETRY_ABI_VERSION_NO >= 2
166+
const auto scope_attributes_json = scope["attributes"];
167+
EXPECT_EQ(scope_attributes_json.size(), instrumentation_scope_attributes.size()) << scope_attributes_json;
168+
#endif
169+
EXPECT_EQ(received_schema_url, schema_url);
170+
EXPECT_EQ(received_instrumentation_scope_name, instrumentation_scope_name);
171+
EXPECT_EQ(received_instrumentation_scope_version, instrumentation_scope_version);
143172
EXPECT_EQ(received_trace_id, report_trace_id);
144173
}
145174
else

exporters/otlp/test/otlp_file_log_record_exporter_test.cc

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,15 @@ class OtlpFileLogRecordExporterTestPeer : public ::testing::Test
100100
char span_id_hex[2 * opentelemetry::trace::SpanId::kSize] = {0};
101101
opentelemetry::trace::SpanId span_id{span_id_bin};
102102

103+
const std::string instrumentation_scope_name{"opentelelemtry_library"};
104+
const std::string instrumentation_scope_version{"1.2.3"};
103105
const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"};
104-
auto logger = provider->GetLogger("test", "opentelelemtry_library", "", schema_url,
105-
{{"scope_key1", "scope_value"}, {"scope_key2", 2}});
106+
const std::vector<std::pair<std::string, opentelemetry::common::AttributeValue>>
107+
instrumentation_scope_attributes{{"scope_key1", "scope_value"},
108+
{ "scope_key2",
109+
2 }};
110+
111+
auto logger = provider->GetLogger("test", instrumentation_scope_name, instrumentation_scope_version, schema_url, instrumentation_scope_attributes);
106112

107113
trace_id.ToLowerBase16(MakeSpan(trace_id_hex));
108114
report_trace_id.assign(trace_id_hex, sizeof(trace_id_hex));
@@ -143,16 +149,27 @@ class OtlpFileLogRecordExporterTestPeer : public ::testing::Test
143149
auto scope_logs = *resource_logs["scopeLogs"].begin();
144150
auto scope = scope_logs["scope"];
145151
auto log = *scope_logs["logRecords"].begin();
146-
auto received_trace_id = log["traceId"].get<std::string>();
147-
auto received_span_id = log["spanId"].get<std::string>();
152+
153+
const auto received_schema_url = scope_logs["schemaUrl"].get<std::string>();
154+
const auto received_instrumentation_scope_name = scope["name"].get<std::string>();
155+
const auto received_instrumentation_scope_version = scope["version"].get<std::string>();
156+
const auto received_instrumentation_scope_attributes = scope["attributes"];
157+
const auto received_trace_id = log["traceId"].get<std::string>();
158+
const auto received_span_id = log["spanId"].get<std::string>();
159+
160+
EXPECT_EQ(received_instrumentation_scope_attributes.size(), instrumentation_scope_attributes.size())
161+
<< received_instrumentation_scope_attributes;
162+
EXPECT_EQ(received_schema_url, schema_url);
163+
EXPECT_EQ(received_instrumentation_scope_name, instrumentation_scope_name);
164+
EXPECT_EQ(received_instrumentation_scope_version, instrumentation_scope_version);
165+
148166
EXPECT_EQ(received_trace_id, report_trace_id);
149167
EXPECT_EQ(received_span_id, report_span_id);
150168
EXPECT_EQ("Log message", log["body"]["stringValue"].get<std::string>());
151169
EXPECT_LE(15, log["attributes"].size());
152170

153171
bool check_scope_attribute = false;
154-
auto scope_attributes = scope["attributes"];
155-
for (auto &attribute : scope_attributes)
172+
for (auto &attribute : received_instrumentation_scope_attributes)
156173
{
157174
if (!attribute.is_object())
158175
{

exporters/otlp/test/otlp_file_metric_exporter_test.cc

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,19 @@ class OtlpFileMetricExporterTestPeer : public ::testing::Test
8888
auto resource = opentelemetry::sdk::resource::Resource::Create(
8989
opentelemetry::sdk::resource::ResourceAttributes{});
9090
data.resource_ = &resource;
91-
auto scope = opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create(
92-
"library_name", "1.5.0");
91+
92+
const std::string instrumentation_scope_name{"library_name"};
93+
const std::string instrumentation_scope_version{"1.5.0"};
94+
const std::string instrumentation_scope_schema_url{"https://opentelemetry.io/schemas/1.2.0"};
95+
const std::vector<std::pair<std::string, opentelemetry::common::AttributeValue>>
96+
instrumentation_scope_attributes{{"scope_key1", "scope_value"},
97+
{ "scope_key2",
98+
2 }};
99+
100+
auto scope = opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create(
101+
instrumentation_scope_name, instrumentation_scope_version, instrumentation_scope_schema_url,
102+
instrumentation_scope_attributes);
103+
93104
opentelemetry::sdk::metrics::MetricData metric_data{
94105
opentelemetry::sdk::metrics::InstrumentDescriptor{
95106
"metrics_library_name", "metrics_description", "metrics_unit",
@@ -100,6 +111,7 @@ class OtlpFileMetricExporterTestPeer : public ::testing::Test
100111
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>{
101112
{opentelemetry::sdk::metrics::PointAttributes{{"a1", "b1"}}, sum_point_data},
102113
{opentelemetry::sdk::metrics::PointAttributes{{"a2", "b2"}}, sum_point_data2}}};
114+
103115
data.scope_metric_data_ = std::vector<opentelemetry::sdk::metrics::ScopeMetrics>{
104116
{scope.get(), std::vector<opentelemetry::sdk::metrics::MetricData>{metric_data}}};
105117

@@ -111,15 +123,18 @@ class OtlpFileMetricExporterTestPeer : public ::testing::Test
111123
output.flush();
112124
output.sync();
113125
auto check_json_text = output.str();
126+
114127
if (!check_json_text.empty())
115128
{
116129
auto check_json = nlohmann::json::parse(check_json_text, nullptr, false);
117130

118131
auto resource_metrics = *check_json["resourceMetrics"].begin();
119132
auto scope_metrics = *resource_metrics["scopeMetrics"].begin();
120133
auto scope = scope_metrics["scope"];
121-
EXPECT_EQ("library_name", scope["name"].get<std::string>());
122-
EXPECT_EQ("1.5.0", scope["version"].get<std::string>());
134+
135+
EXPECT_EQ(instrumentation_scope_schema_url, scope_metrics["schemaUrl"].get<std::string>());
136+
EXPECT_EQ(instrumentation_scope_name, scope["name"].get<std::string>());
137+
EXPECT_EQ(instrumentation_scope_version, scope["version"].get<std::string>());
123138

124139
auto metric = *scope_metrics["metrics"].begin();
125140
EXPECT_EQ("metrics_library_name", metric["name"].get<std::string>());

exporters/otlp/test/otlp_recordable_test.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,31 @@ TEST(OtlpRecordable, SetInstrumentationLibraryWithSchemaURL)
119119
EXPECT_EQ(expected_schema_url, rec.GetInstrumentationLibrarySchemaURL());
120120
}
121121

122+
TEST(OtlpRecordable, SetInstrumentationScopeWithAttributes)
123+
{
124+
exporter::otlp::OtlpRecordable rec;
125+
const std::string expected_attribute_key{"test_key"};
126+
const std::string expected_attribute_value{"test_value"};
127+
128+
auto inst_lib = trace_sdk::InstrumentationScope::Create(
129+
"test", "v1", "", {{expected_attribute_key, expected_attribute_value}});
130+
131+
ASSERT_EQ(inst_lib->GetAttributes().size(), 1);
132+
133+
rec.SetInstrumentationScope(*inst_lib);
134+
135+
const auto proto_instr_libr = rec.GetProtoInstrumentationScope();
136+
137+
ASSERT_EQ(proto_instr_libr.attributes_size(), 1);
138+
139+
const auto &proto_attributes = proto_instr_libr.attributes(0);
140+
141+
ASSERT_TRUE(proto_attributes.value().has_string_value());
142+
143+
EXPECT_EQ(expected_attribute_key, proto_attributes.key());
144+
EXPECT_EQ(expected_attribute_value, proto_attributes.value().string_value());
145+
}
146+
122147
TEST(OtlpRecordable, SetStartTime)
123148
{
124149
OtlpRecordable rec;

0 commit comments

Comments
 (0)