-
Notifications
You must be signed in to change notification settings - Fork 858
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
Implement the keyed-attributes proposal #1631
Implement the keyed-attributes proposal #1631
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1631 +/- ##
============================================
+ Coverage 86.68% 86.79% +0.11%
+ Complexity 1402 1384 -18
============================================
Files 164 162 -2
Lines 5542 5340 -202
Branches 553 546 -7
============================================
- Hits 4804 4635 -169
+ Misses 542 509 -33
Partials 196 196
Continue to review full report at Codecov.
|
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.
Not sure how much I like it, but I can see the benefits. Can we discuss this Friday during the sig meeting?
} | ||
|
||
/** | ||
* Sets a long {@link AttributeValue} into this. | ||
* Sets a long attribute into this. | ||
* | ||
* @return this Builder | ||
*/ | ||
public Builder setAttribute(String key, long value) { |
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.
Should this change to LongKey, long value?
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.
My thought was, since these are already type-safe, to keep the easy option in the API, for cases where people don't want to directly use the new keys. The method that takes the generic key should cover the particular, and would end up being the same method signature as this if we change the first parameter to LongKey
.
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 I don't think we need to change these methods to use the keys. We could consider removing these methods - I'm on the fence on how useful these are for users. Keys will always have a significant performance benefit compared to creating a wrapper key every time this is invoked, so removing them reduces the chances of a user not realizing that.
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.
At the very least, I was thinking we should add some strongly worded language to the javadoc about preferring to use the method that takes the Key.
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.
added some javadoc to the relevant methods.
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.
Generally looks good to me
api/src/main/java/io/opentelemetry/common/AttributeKeyImpl.java
Outdated
Show resolved
Hide resolved
|
||
@Override | ||
public String toString() { | ||
return "AttributeKeyImpl{" + "key='" + key + '\'' + '}'; |
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.
return "AttributeKeyImpl{" + "key='" + key + '\'' + '}'; | |
return key; |
I think just the key is a better toString for keys
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'm on the fence. It will certainly read better, but I wonder if it could be misleading in tests if the failure happens when you're trying to compare to a raw String, and the toStrings would look identical.
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.
Admittedly I'm biased because instrumentation tests are groovy and would be able to use the key itself in assertions instead of calling a method. This is not a strong enough reason to pick one or another though so ok with either 😃
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.
wait...spock uses the toString to do assertions??? That sounds like a terrible idea.
api/src/main/java/io/opentelemetry/common/AttributeKeyImpl.java
Outdated
Show resolved
Hide resolved
api/src/main/java/io/opentelemetry/common/AttributeKeyImpl.java
Outdated
Show resolved
Hide resolved
} | ||
|
||
/** | ||
* Sets a long {@link AttributeValue} into this. | ||
* Sets a long attribute into this. | ||
* | ||
* @return this Builder | ||
*/ | ||
public Builder setAttribute(String key, long value) { |
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 I don't think we need to change these methods to use the keys. We could consider removing these methods - I'm on the fence on how useful these are for users. Keys will always have a significant performance benefit compared to creating a wrapper key every time this is invoked, so removing them reduces the chances of a user not realizing that.
exporters/jaeger/src/main/java/io/opentelemetry/exporters/jaeger/Adapter.java
Show resolved
Hide resolved
Overall good - I was worried at first at the beginning because we lost some type safety, but if the memory footprint really improves (and maybe we also help the Instrumentation?), I'm ok with it definitely. |
78de78f
to
3dfeff1
Compare
@jkwatson thank you for the huge amount of work put into this PR! In the last SIG meeting, you said there are fewer allocations with this approach! Do you have the JMH number at hand? |
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 reviewed about half of the PR and in do agree with this change in general :)
|
||
////////////////////////////////// | ||
// IMPORTANT: the equals/hashcode/compareTo *only* include the key, and not the type, | ||
// so that de-duping of attributes is based on the key, and not also based on the type. |
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.
Why? Can there be attributes with the same key but different types?
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.
Well... what would that mean, exactly? Certainly with the previous implementation, you get only one value per key. Having multiple values per string-key would be very odd to have to deal with in an Exporter, I think.
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.
My though was that if there is NO two attributes with the same key but different type, why it is important to include only key, but not type, into equals/hashcode/compareTo?
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.
Something has to make the replacement of one keyed-value with another (of a different type). This is the implementation that makes that happen. The de-duping relies on the equals/hashcode not including the type.
I do. I've been using the SpanPipelineBenchmark for this test, which does exercise attributes, although maybe or maybe not in a super realisitc way. Here is the after/befpre for that (note: don't pay much attention to the timing numbers here; only the allocation numbers should be useful, since I ran these on my laptop):
|
35c1b9b
to
9977762
Compare
Am I reading it right, that this PR reduces allocation rate by 3%? Somehow I expected more :( |
|
||
AttributeKeyImpl<?> that = (AttributeKeyImpl<?>) o; | ||
|
||
return getKey() != null ? getKey().equals(that.getKey()) : that.getKey() == null; |
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.
return getKey() != null ? getKey().equals(that.getKey()) : that.getKey() == null; | |
return Objects.equals(getKey(), that.getKey()); |
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.
We can't use that in the API, due to java 7/android
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 API is definititely in Java 7, check the link I posted 😃
|
||
@Override | ||
public int compareTo(AttributeKey o) { | ||
return getKey().compareTo(o.getKey()); |
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.
Why no null check here? Use Objects.compare?
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.
For some reason I thought we couldn't use that with java 7/android. Let me take a look.
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.
updated to be null-safe
If this helps Auto-Instrumentation, that's a big win already ;) |
Recall that the benchmark I'm running is creating one of each type of attribute. Only the String attribute has an allocation improvement in this scheme. I would guess that, in real instrumentation, most of the attributes are String-typed, and hence the allocation rate gain would be proportionally much better. |
@carlosalberto @bogdandrutu This is good to go. Any last thoughts/concerns before we merge it? |
Move the key creators to a AttributesKeys class. Hide the implementation classes and replace with interface use.
9aceb85
to
dc86d82
Compare
Hi, it would be nice if you could merge this PR mostly as-is without relying on Java 8 features (features for newer android API levels are fine), as we would like to include this (hopefully last) major change to the tracing API in our Dynatrace fork. |
I'm planning on merging first thing on Monday. |
Merging! |
This implements the proposal in #1580 .
Many apologies for the size of this PR. The only thing I can say in my defense is that it removes a net of over 1100 lines of code.
Most of the changes are to test code, where attributes are created extensively. The actual change to the API surface is remarkably small.
Resolves #1580