-
Notifications
You must be signed in to change notification settings - Fork 864
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
Work in Progress on some Trace API tweaks #1130
Work in Progress on some Trace API tweaks #1130
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1130 +/- ##
=========================================
Coverage 84.17% 84.17%
Complexity 1153 1153
=========================================
Files 149 149
Lines 4449 4449
Branches 394 394
=========================================
Hits 3745 3745
Misses 557 557
Partials 147 147 Continue to review full report at Codecov.
|
60940a0
to
a9aef48
Compare
private static Map<String, AttributeValue> makeAttributeMap(Attribute[] attributes) { | ||
Map<String, AttributeValue> result = new HashMap<>(); | ||
for (Attribute attribute : attributes) { | ||
result.put(attribute.key().key(), makeValue(attribute)); |
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.
Having this double key method call looks strange.
The fact that we need to unwrap and wrap again the value makes me thinking that maybe the concrete implementation of Attributes
should also already build the proper AttributeValue
and hold its reference. This way we don't need a switch since the typing information already suggests the correct method to call. WDYT?
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 goal of this draft PR is to discuss changes to the API, not provide an efficient wrapper for the current API. Don't worry about the internal details of this, as they are just there to make sure we can provide the same functionality, not to be a real 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.
Remember, the impetus for this discussion was getting rid of AttributeValue
from the API altogether. :)
import com.google.errorprone.annotations.MustBeClosed; | ||
import io.opentelemetry.context.Scope; | ||
|
||
// go Speed Racer, go Speed Racer, go Speed Racer go! |
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.
🤣
Am I missing something or is there not yet a SpanEx.put/setAttribute outside the Builder? |
I've only written options for the |
dc14421
to
82e10c0
Compare
@bogdandrutu I added some detailed notes about allocation overhead with some of the various options in this PR. |
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 think i prefer the more efficient and more user-friendly setAttribute(key, value)
.
from a user perspective, i don't think the overloaded methods make the API surface feel bigger (they only add to the API surface from a maintainer's perspective).
// option 1... provide a single attribute | ||
public SpanEx.Builder setAttribute(Attribute attribute) { | ||
builder.setAttribute(attribute.key().key(), makeValue(attribute)); | ||
return 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.
comparing
spanBuilder.setAttribute(Attribute.create(key, value))
and
spanBuilder.setAttribute(key, value)
the latter is more efficient, and seems more user-friendly to me
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.
ah, cool. This is the obvious option that we should add. I assume you mean with the typed-key. Yes, I'll add this ASAP.
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 added this, as well as all the array-based attribute methods everywhere, for completeness.
public SpanEx.Builder setAttribute(Attribute... attributes) { | ||
for (Attribute attribute : attributes) { | ||
builder.setAttribute(attribute.key().key(), makeValue(attribute)); | ||
} | ||
return 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.
comparing
Attribute attr1 = Attribute.create(key1, value1);
Attribute attr2 = Attribute.create(key2, value2);
Attribute attr3 = Attribute.create(key3, value3);
spanBuilder.setAttribute(attr1, attr2, attr3);
and
spanBuilder.setAttribute(key1, value1)
.setAttribute(key2, value2)
.setAttribute(key3, value3);
the latter is more efficient, and seems more user-friendly to me
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.
check out the latest updates, which have support for this usage.
// option 1... provide a single attribute | ||
public SpanEx.Builder setAttribute(Attribute attribute) { | ||
builder.setAttribute(attribute.key().key(), makeValue(attribute)); | ||
return this; | ||
} | ||
|
||
// option 2... a type-safe key-value pair with varargs parameters | ||
|
||
/** doc me. */ | ||
public SpanEx.Builder setAttribute(Attribute... attributes) { | ||
for (Attribute attribute : attributes) { | ||
builder.setAttribute(attribute.key().key(), makeValue(attribute)); | ||
} | ||
return this; | ||
} | ||
|
||
// option 3... accept a bunch of attributes at once | ||
|
||
/** doc me. */ | ||
public SpanEx.Builder setAttribute(Attributes attributes) { | ||
for (AttributeKey key : attributes.getKeys()) { | ||
builder.setAttribute(key.key(), makeValue(attributes, key)); | ||
} | ||
return 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.
comparing
spanBuilder.setAttributes(
MapBasedAttributes.newBuilder().put(key1, value1)
.put(key2, value2)
.put(key3, value3)
.build())
and
spanBuilder.setAttribute(key1, value1)
.setAttribute(key2, value2)
.setAttribute(key3, value3);
the latter is more efficient, and seems more user-friendly to me
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 think i prefer the more efficient and more user-friendly
setAttribute(key, value)
.from a user perspective, i don't think the overloaded methods make the API surface feel bigger (they only add to the API surface from a maintainer's perspective).
I agree with you that we should offer the setAttribute(key, value)
but I think we should also offer the 3rd option using Attributes
. In many semantic conventions, say HTTP, many attributes don't change. For example, if a library has to manually instrument its code to serve an HTTP request, the attributes method
, url
, target
, ... do not change between requests so they can be cached.
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 an interesting thought, yes. Pre-bundling the attributes that are relevant for a given HTTP endpoint is possible, but is that likely to be a common use-case, as opposed to more generic instrumentation that would need to dynamically generate the values?
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.
Would caching an Attributes
object give some performance benefit? Or is it just for convenience? Maybe a concrete example would help to understand how caching the Attributes
would be more convenient compared to settings the attributes directly.
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 was thinking out loud without having a concrete example in mind. Thinking more thoroughly on a possible usage, I would use the Attributes
interface to decouple span creation and attribute definition, similarly to how it's used here:
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 decoupling is nice in that example, but if the attribute values aren't static, I think you'd need to pass in 8 parameters to that httpAttribute()
method, at which point it may not be so nice.
de62548
to
28640f4
Compare
…ental tracer/span API.
…per-entry allocations
…n for Link attributes.
28640f4
to
37c87b9
Compare
I'm going to close this, since the introduction of the Attributes class would mean a rework, if we wanted to change to "typed" keys. |
Doing this in Draft PR to make it as open and public as possible.
Also, doing this via a new contrib module for incubating new APIs.