-
Notifications
You must be signed in to change notification settings - Fork 579
[OTLP EXPORTER] fix OTLP recordable attribute spec compliance #4166
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,9 +1,12 @@ | ||||||||||||||||||||||||||
| // Copyright The OpenTelemetry Authors | ||||||||||||||||||||||||||
| // SPDX-License-Identifier: Apache-2.0 | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| #include "opentelemetry/exporters/otlp/otlp_log_recordable.h" | ||||||||||||||||||||||||||
| #include <cstdint> | ||||||||||||||||||||||||||
| #include <string> | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| #include "opentelemetry/common/attribute_value.h" | ||||||||||||||||||||||||||
| #include "opentelemetry/common/timestamp.h" | ||||||||||||||||||||||||||
| #include "opentelemetry/exporters/otlp/otlp_log_recordable.h" | ||||||||||||||||||||||||||
| #include "opentelemetry/exporters/otlp/otlp_populate_attribute_utils.h" | ||||||||||||||||||||||||||
| #include "opentelemetry/logs/severity.h" | ||||||||||||||||||||||||||
| #include "opentelemetry/nostd/span.h" | ||||||||||||||||||||||||||
|
|
@@ -18,6 +21,8 @@ | |||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // clang-format off | ||||||||||||||||||||||||||
| #include "opentelemetry/exporters/otlp/protobuf_include_prefix.h" // IWYU pragma: keep | ||||||||||||||||||||||||||
| #include <google/protobuf/repeated_ptr_field.h> | ||||||||||||||||||||||||||
| #include "opentelemetry/proto/common/v1/common.pb.h" | ||||||||||||||||||||||||||
| #include "opentelemetry/proto/logs/v1/logs.pb.h" | ||||||||||||||||||||||||||
| #include "opentelemetry/exporters/otlp/protobuf_include_suffix.h" // IWYU pragma: keep | ||||||||||||||||||||||||||
| // clang-format on | ||||||||||||||||||||||||||
|
|
@@ -194,7 +199,7 @@ void OtlpLogRecordable::SetSeverity(opentelemetry::logs::Severity severity) noex | |||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| void OtlpLogRecordable::SetBody(const opentelemetry::common::AttributeValue &message) noexcept | ||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||
| OtlpPopulateAttributeUtils::PopulateAnyValue(proto_record_.mutable_body(), message, true); | ||||||||||||||||||||||||||
| OtlpPopulateAttributeUtils::PopulateAnyValue(proto_record_.mutable_body(), message); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| void OtlpLogRecordable::SetEventId(int64_t /* id */, nostd::string_view event_name) noexcept | ||||||||||||||||||||||||||
|
|
@@ -236,7 +241,15 @@ void OtlpLogRecordable::SetTraceFlags(const opentelemetry::trace::TraceFlags &tr | |||||||||||||||||||||||||
| void OtlpLogRecordable::SetAttribute(opentelemetry::nostd::string_view key, | ||||||||||||||||||||||||||
| const opentelemetry::common::AttributeValue &value) noexcept | ||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||
| OtlpPopulateAttributeUtils::PopulateAttribute(proto_record_.add_attributes(), key, value, true); | ||||||||||||||||||||||||||
| for (auto &attr : *proto_record_.mutable_attributes()) | ||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||
| if (attr.key() == key) | ||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we use a hash map (e.g., unordered_map) to track existing keys? The current linear scan on every SetAttribute call is O(n) per insertion—O(n²) total—and the overhead compounds quickly at scale. It's not just the number of attributes: string comparison cost grows with key length. Each loop iteration does a full character-by-character comparison, whereas a hash map typically checks hash codes first, only falling back to full comparison on collisions.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This implements the hash map for attribute keys. Compared to the linear search (1525b4c), the performance is better in the max attributes case by -5.5us or -31%, but worse for the nominal attribute case (6 attributes) by ~220 ns or +37%.
|
||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||
| OtlpPopulateAttributeUtils::PopulateAttribute(&attr, key, value); | ||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| OtlpPopulateAttributeUtils::PopulateAttribute(proto_record_.add_attributes(), key, value); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| void OtlpLogRecordable::SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Benchmark comparison:
This check to avoid duplicating attribute keys adds overhead:
This can be mitigated a few ways 1) add a SetAttributes method that takes key value iterable and does not check existing keys on creation of the span, 2) do not check attribute keys during span recording and perform deduplication when creating the protobuf request message on export.
branch:
dbarker:add_otlp_recordable_benchmark(#4165)branch:
dbarker:fix_otlp_attribute_spec_compliance(this PR #4166)