Skip to content

Commit

Permalink
extension: Add Span::setTag for setting attributes in OTLP Tracer (en…
Browse files Browse the repository at this point in the history
…voyproxy#21893)

Add Span::setTag for setting attributes on OTLP span

Signed-off-by: Alex Ellis <[email protected]>
  • Loading branch information
AlexanderEllis authored Jun 27, 2022
1 parent 2cc469f commit 363976d
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 1 deletion.
24 changes: 24 additions & 0 deletions source/extensions/tracers/opentelemetry/tracer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,30 @@ void Span::injectContext(Tracing::TraceContext& trace_context,
trace_context.setByReferenceKey(kTraceParent, traceparent_header_value);
}

void Span::setTag(absl::string_view name, absl::string_view value) {
// The attribute key MUST be a non-null and non-empty string.
if (name.empty()) {
return;
}
// Attribute keys MUST be unique.
// If a value already exists for this key, overwrite it.
for (auto& key_value : *span_.mutable_attributes()) {
if (key_value.key() == name) {
key_value.mutable_value()->set_string_value(std::string{value});
return;
}
}
// If we haven't found an existing match already, we can add a new key/value.
opentelemetry::proto::common::v1::KeyValue key_value =
opentelemetry::proto::common::v1::KeyValue();
opentelemetry::proto::common::v1::AnyValue value_proto =
opentelemetry::proto::common::v1::AnyValue();
value_proto.set_string_value(std::string{value});
key_value.set_key(std::string{name});
*key_value.mutable_value() = value_proto;
*span_.add_attributes() = key_value;
}

Tracer::Tracer(OpenTelemetryGrpcTraceExporterPtr exporter, Envoy::TimeSource& time_source,
Random::RandomGenerator& random, Runtime::Loader& runtime,
Event::Dispatcher& dispatcher, OpenTelemetryTracerStats tracing_stats)
Expand Down
2 changes: 1 addition & 1 deletion source/extensions/tracers/opentelemetry/tracer.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class Span : Logger::Loggable<Logger::Id::tracing>, public Tracing::Span {

// Tracing::Span functions
void setOperation(absl::string_view /*operation*/) override{};
void setTag(absl::string_view /*name*/, absl::string_view /*value*/) override{};
void setTag(absl::string_view /*name*/, absl::string_view /*value*/) override;
void log(SystemTime /*timestamp*/, const std::string& /*event*/) override{};
void finishSpan() override;
void injectContext(Envoy::Tracing::TraceContext& /*trace_context*/,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,66 @@ TEST_F(OpenTelemetryDriverTest, SpawnChildSpan) {
EXPECT_EQ(1U, stats_.counter("tracing.opentelemetry.spans_sent").value());
}

TEST_F(OpenTelemetryDriverTest, ExportOTLPSpanWithAttributes) {
setupValidDriver();
Http::TestRequestHeaderMapImpl request_headers{
{":authority", "test.com"}, {":path", "/"}, {":method", "GET"}};
NiceMock<Random::MockRandomGenerator>& mock_random_generator_ =
context_.server_factory_context_.api_.random_;
int64_t generated_int = 1;
EXPECT_CALL(mock_random_generator_, random()).Times(3).WillRepeatedly(Return(generated_int));
SystemTime timestamp = time_system_.systemTime();

Tracing::SpanPtr span = driver_->startSpan(mock_tracing_config_, request_headers, operation_name_,
timestamp, {Tracing::Reason::Sampling, true});
EXPECT_NE(span.get(), nullptr);

span->setTag("first_tag_name", "first_tag_value");
span->setTag("second_tag_name", "second_tag_value");
// Try an empty tag.
span->setTag("", "empty_tag_value");
// Overwrite a tag.
span->setTag("first_tag_name", "first_tag_new_value");

// Note the placeholders for the bytes - cleaner to manually set after.
const std::string request_yaml = R"(
resource_spans:
instrumentation_library_spans:
spans:
trace_id: "AAA"
span_id: "AAA"
name: "test"
kind: SPAN_KIND_SERVER
start_time_unix_nano: {}
end_time_unix_nano: {}
attributes:
- key: "first_tag_name"
value:
string_value: "first_tag_new_value"
- key: "second_tag_name"
value:
string_value: "second_tag_value"
)";
opentelemetry::proto::collector::trace::v1::ExportTraceServiceRequest request_proto;
int64_t timestamp_ns = std::chrono::nanoseconds(timestamp.time_since_epoch()).count();
TestUtility::loadFromYaml(fmt::format(request_yaml, timestamp_ns, timestamp_ns), request_proto);
std::string generated_int_hex = Hex::uint64ToHex(generated_int);
auto* expected_span = request_proto.mutable_resource_spans(0)
->mutable_instrumentation_library_spans(0)
->mutable_spans(0);
expected_span->set_trace_id(
absl::HexStringToBytes(absl::StrCat(generated_int_hex, generated_int_hex)));
expected_span->set_span_id(absl::HexStringToBytes(absl::StrCat(generated_int_hex)));

EXPECT_CALL(runtime_.snapshot_, getInteger("tracing.opentelemetry.min_flush_spans", 5U))
.Times(1)
.WillRepeatedly(Return(1));
EXPECT_CALL(*mock_stream_ptr_,
sendMessageRaw_(Grpc::ProtoBufferEqIgnoreRepeatedFieldOrdering(request_proto), _));
span->finishSpan();
EXPECT_EQ(1U, stats_.counter("tracing.opentelemetry.spans_sent").value());
}

} // namespace OpenTelemetry
} // namespace Tracers
} // namespace Extensions
Expand Down

0 comments on commit 363976d

Please sign in to comment.