-
Notifications
You must be signed in to change notification settings - Fork 884
Add experimental support for log extended attributes #7123
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
Add experimental support for log extended attributes #7123
Conversation
// TODO (jack-berg): uncomment when extended attributes are promoted from incubator to API | ||
// default ExtendedAttributeKey<T> asExtendedAttributeKey() { | ||
// return InternalAttributeKeyImpl.toExtendedAttributeKey(this); | ||
// } |
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.
This is a big loss. In the original prototype, I had a helper method to directly on AttributeKey
for converting to ExtendedAttributeKey
. This allowed the AttributeKey
to internally keep a cached copy of the corresponding ExtendedAttributeKey
, making conversions in both directions very cheap.
As long as ExtendedAttributes
are experimental, we can't have this API. This means we need to a different strategy for converting / caching. I've opted for keeping a static ConcurrentHashMap
cache in InternalExtendedAttributeKey. The problem is that the map can grow unbounded if a user puts high cardinality data into attribute keys. Not as elegant as caching directly in AttributeKey
implementation.
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.
Per a conversation in a java sig (several weeks ago I think), performance isn't a priority while this is experimental. Therefore, I've removed the unbounded cache for now.
LONG_ARRAY, | ||
DOUBLE_ARRAY, | ||
// Extended types unique to ExtendedAttributes | ||
EXTENDED_ATTRIBUTES; |
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.
- Dropped arrays of maps for now, per this comment: Sketch out ExtendedAttributes #6983 (comment)
- Renamed from MAP -> EXTENDED_ATTRIBUTES per this comment: Sketch out ExtendedAttributes #6983 (comment)
Should we consider adding support for byte arrays?
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.
I don't think it has to be now. Users will base64 encode or json stuff anyway. 🤷🏻
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.
Yeah users will always have that ability, but having direct representation for a type a signal that there is a recommended way of representing the data. This encourages more consistency than being opinionated, which will produce a bit of a free for all in terms of what instrumentations produce and what backends receive.
Still, I'm happy to punt on these questions for now and let semantic conventions develop more guidance.
api/incubator/src/main/java/io/opentelemetry/api/incubator/common/ExtendedAttributes.java
Show resolved
Hide resolved
|
||
/** Return an ExtendedAttributeKey equivalent to the {@code attributeKey}. */ | ||
// TODO (jack-berg): remove once AttributeKey.asExtendedAttributeKey is available | ||
static <T> ExtendedAttributeKey<T> fromAttributeKey(AttributeKey<T> attributeKey) { |
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.
Per this comment, the conversion from AttributeKey -> ExtendedAttributeKey unfortunately lives on ExtendedAttributeKey instead of on AttributeKey.
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.
That totally seems like the kind of thing that will take some usage to determine if/how annoying it might be.
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.
Its preferable to live on AttributeKey
from a performance perspective, since the AttributeKey
implementation can cache the equivalent ExtendedAttributeKey
reference.
Once its available on AttributeKey
, it could here as well as syntactic sugar. This static implementation could just call attributeKey.asExtendedAttributeKey()
to obtain the cached copy.
public final class InternalExtendedAttributeKeyImpl<T> implements ExtendedAttributeKey<T> { | ||
|
||
private static final ConcurrentHashMap<AttributeKey<?>, ExtendedAttributeKey<?>> | ||
ATTRIBUTE_KEY_CACHE = new ConcurrentHashMap<>(); |
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.
Per this comment, keeping an unbounded cache mapping AttributeKey -> ExtendedAttributeKey.
For converting from ExtendedAttributeKey -> AttributeKey, we keep a reference to the AttributeKey as a field on ExtendedAttributeKey. See line 31.
|
||
@Test | ||
@SuppressWarnings("SystemOut") | ||
void extendedAttributesUsage() { |
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.
The tests in this file demonstrate key usage patterns.
int attributeSize = | ||
INCUBATOR_AVAILABLE | ||
? IncubatingUtil.extendedAttributesSize(logRecordData) | ||
: logRecordData.getAttributes().size(); |
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.
Jumping through hoops so serialization logic forks based on whether opentelemetry-api-incubator
(and ExtendedAttributes) is / isn't available.
Codecov ReportAttention: Patch coverage is
❌ Your patch status has failed because the patch coverage (74.13%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #7123 +/- ##
============================================
- Coverage 89.92% 89.62% -0.30%
- Complexity 6721 6864 +143
============================================
Files 765 780 +15
Lines 20277 20715 +438
Branches 1985 2018 +33
============================================
+ Hits 18234 18566 +332
- Misses 1448 1511 +63
- Partials 595 638 +43 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
...mon/src/test/java/io/opentelemetry/exporter/internal/otlp/logs/LogsRequestMarshalerTest.java
Show resolved
Hide resolved
sdk/common/src/main/java/io/opentelemetry/sdk/internal/ExtendedAttributesMap.java
Outdated
Show resolved
Hide resolved
...ters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/TestDataExporter.java
Show resolved
Hide resolved
…y-java into experimental-extended-attributes
...bator/src/main/java/io/opentelemetry/api/incubator/common/ArrayBackedExtendedAttributes.java
Show resolved
Hide resolved
if (data.size() == 2 && data.get(0) != null) { | ||
return new ArrayBackedExtendedAttributes(data.toArray()); | ||
} | ||
return ArrayBackedExtendedAttributes.sortAndFilterToAttributes(data.toArray()); |
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.
The sorting feels like part of the building, so what about moving the method into this builder class instead?
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.
Yeah this whole function is essential a named constructor, since the constructor itself was private.
For what its worth, this whole class is a "copy / paste / modify" of ArrayBackedAttributes, so I didn't look too critically at the implementation.
What do you think about a followup PR where I cleanup minor pattern quirks like this in both ArrayBackedAttributes and ExtendedArrayBackedAttributes?
.../src/main/java/io/opentelemetry/api/incubator/internal/InternalExtendedAttributeKeyImpl.java
Show resolved
Hide resolved
api/incubator/src/main/java/io/opentelemetry/api/incubator/logs/ExtendedLogRecordBuilder.java
Show resolved
Hide resolved
api/incubator/src/test/java/io/opentelemetry/api/incubator/common/ExtendedAttributesTest.java
Show resolved
Hide resolved
...ubator/src/test/java/io/opentelemetry/api/incubator/logs/ExtendedLogsBridgeApiUsageTest.java
Show resolved
Hide resolved
...common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogStatelessMarshaler.java
Show resolved
Hide resolved
...common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogStatelessMarshaler.java
Outdated
Show resolved
Hide resolved
sdk/common/src/main/java/io/opentelemetry/sdk/internal/ExtendedAttributesMap.java
Show resolved
Hide resolved
sdk/common/src/main/java/io/opentelemetry/sdk/internal/ExtendedAttributesMap.java
Show resolved
Hide resolved
sdk/common/src/main/java/io/opentelemetry/sdk/internal/ExtendedAttributesMap.java
Show resolved
Hide resolved
sdk/logs/src/main/java/io/opentelemetry/sdk/logs/ExtendedSdkLogRecordData.java
Show resolved
Hide resolved
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.
Looking really good. I'm a bit surprised and bummed that it required this much code, but with the incubator and explicit extension separation, it seems like maybe there's no great way around it.
I left a few comments, but I think this is close to being a good first pass. Thanks @jack-berg !!!
Next question, of course, is when do we get it out of incubator? 😅
Same. I think its a tradeoff between more code and better API ergonomics. We could do it more succinctly, but the user API ergonomic story suffers. With this, we pay the price with more code to maintain, but help out the user with improved API ergonomics. At least that's what I tell myself. 😅 |
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.
🚀
…y-java into experimental-extended-attributes
Hi @jack-berg, I'm working on open-telemetry/opentelemetry-java-instrumentation#8354 and I'm basing my changes on the new incubating extended attributes API. Would you be interested in some usability feedback? Also, I think there's no way to fully test log records carrying extended attributes at the moment, am I missing something? I could use the implicit conversion to normal attributes, but that scrapes away maps. Is this addition planned already? Can I help somehow? |
Yes definitely! Care to open an issue to track?
Yes there is a way. Its a bit obscure to follow the code (a consequence of the steps we take to separate to allow the SDK to work whether or not
|
Supersedes #6983. This PR moves all the experimental stuff to
opentelemetry-api-incubator
, and significantly reshuffles things to make it all work while retaining only a compileOnly dependency on the incubator.