-
Notifications
You must be signed in to change notification settings - Fork 867
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
Use Instrumenter in JMS instrumentation #2803
Use Instrumenter in JMS instrumentation #2803
Conversation
SEND, | ||
RECEIVE, | ||
PROCESS; |
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 will ask my favourite question: why enum cannot be already in lower case?
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.
Are these missing from the generated conventions? If so let's fix it.
Until then we could also go with static final String which is what our generator produces since yesterday
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 semconv generated enum is missing the send
value:
public enum MessagingOperationValues {
/** receive. */
RECEIVE("receive"),
/** process. */
PROCESS("process"),
;
}
I suppose that's because setting message.operation
to send
is strictly forbidden in the spec. Still, having send
available makes the instrumentation code a bit clearer...
why enum cannot be already in lower case?
Good question - I don't really mind it, but most people tend to dislike anything other than CONSTANT_CASE.
|
||
@ParameterizedTest | ||
@MethodSource("destinations") | ||
void shouldExtractAllAvailableAttributes( |
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 am a little bit sceptical about the value of this test. It may be useful to test extracting operation name and behaviour in case of temporary destination. But otherwise, maybe it can be replaced with tests of actual implementations of MessagingAttributesExtractor
?
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 that the real value is testing the full semantic conventions themselves, not just one implementation of them.
Maybe if we replaced the inheritance with composition too those tests would make more sense: something like MessagingAttributesExtractor.create(new JmsAttributesGetter())
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 refactored the attributes extractor and made it not abstract: ecf8ac3
Please tell me WDYT about it - the separation of concerns is nice, but on the other hand it makes setting up an Instrumenter
a bit more bloated.
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.
Hmm - I guess I lean towards the abstract version if it keeps using the Instrumenter
simpler. Not sure there was a huge problem with the test
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'll revert it for now, we can come back to this discussion in a separate issue/PR. Personally I don't really have a strong opinion about either solution, both have some good and bad sides.
* name>}. | ||
* @see MessagingAttributesExtractor#operation(Object) used to extract {@code <operation name>}. | ||
*/ | ||
public static <REQUEST> SpanNameExtractor<REQUEST> create( |
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 does this class have a factory method, while MessagingAttributesExtractor
does not? What is so different about this class that requires special construction?
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.
MessagingAttributesExtractor
is an abstract class that has to be extended, it cannot have a static factory method.
What is so different about this class that requires special construction?
Hmm, there's nothing special - I've added it here because we use builders & factory methods (instead of plain constructor calls) in the instrumenter API. I guess that's more resistant to future changes? But I may be overthinking this, and maybe it just looks a bit cooler 😄
...ent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/MessageWithDestination.java
Show resolved
Hide resolved
73f848a
to
ecf8ac3
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.
Thanks a lot @mateuszrzeszutek mostly looks good and just some questions
...n/java/io/opentelemetry/javaagent/instrumentation/jms/JmsMessageConsumerInstrumentation.java
Outdated
Show resolved
Hide resolved
...a/io/opentelemetry/instrumentation/api/instrumenter/messaging/MessagingAttributesGetter.java
Outdated
Show resolved
Hide resolved
|
||
@ParameterizedTest | ||
@MethodSource("destinations") | ||
void shouldExtractAllAvailableAttributes( |
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.
Hmm - I guess I lean towards the abstract version if it keeps using the Instrumenter
simpler. Not sure there was a huge problem with the test
18cf049
to
136b656
Compare
Added |
Instrumenter(InstrumenterBuilder<REQUEST, RESPONSE> builder) { | ||
this.instrumentationName = builder.instrumentationName; | ||
this.tracer = builder.openTelemetry.getTracer(builder.instrumentationName); | ||
this.spanNameExtractor = builder.spanNameExtractor; | ||
this.spanKindExtractor = builder.spanKindExtractor; | ||
this.spanStatusExtractor = builder.spanStatusExtractor; | ||
this.extractors = new ArrayList<>(builder.attributesExtractors); | ||
this.errorCauseExtractor = builder.errorCauseExtractor; | ||
this.startTimeExtractor = builder.startTimeExtractor; | ||
this.endTimeExtractor = builder.endTimeExtractor; | ||
} |
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 refactored the Instrumenter constructor and used the same approach as OkHttp builder. I think it makes passing all those extractors a bit easier on the eyes
And introduce messaging semantic conventions
cd54adf
to
51becf0
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.
And I've accidentally resolved #2600 for Instrumenter-using instrumentations too 😂
🎉
.../main/java/io/opentelemetry/instrumentation/api/instrumenter/messaging/MessageOperation.java
Outdated
Show resolved
Hide resolved
...ion-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/CurrentNanoTime.java
Outdated
Show resolved
Hide resolved
...tation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/Instrumenter.java
Outdated
Show resolved
Hide resolved
public InstrumenterBuilder<REQUEST, RESPONSE> setTimeExtractors( | ||
StartTimeExtractor<REQUEST> startTimeExtractor, EndTimeExtractor<RESPONSE> endTimeExtractor) { |
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.
These two should probably be always set together - start & end timestamps need to be comparable, so it does not make any sense to set just one and compare with the SDK timestamp.
* Returns the timestamp marking the start of the request processing. If the returned timestamp is | ||
* {@code null} the OpenTelemetry SDK will use its internal clock to determine the start time. | ||
*/ | ||
@Nullable |
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.
Do you think there's a use case for a custom extractor to delegate to SDK conditionally? Otherwise maybe we don't need to make this default and can treat that as an implementation detail (we could even change the null
check to == getDefault()
. This is ok too though.
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.
Do you think there's a use case for a custom extractor to delegate to SDK conditionally?
No, it doesn't make any sense for a custom extractor to delegate to SDK. I'll change that.
Thanks!
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've removed the getDefault()
methods from start/end extractors, I thought it would be confusing to have it there: now the default behavior is using SDK for timestamps, and if you pass custom extractors they must be custom implementations.
And introduce messaging semantic conventions
Part of #2713