Skip to content
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

Merged
merged 7 commits into from
May 5, 2021

Conversation

mateuszrzeszutek
Copy link
Member

And introduce messaging semantic conventions

Part of #2713

Comment on lines +14 to +18
SEND,
RECEIVE,
PROCESS;
Copy link
Contributor

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?

Copy link
Contributor

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

Copy link
Member Author

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(
Copy link
Contributor

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?

Copy link
Member Author

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())

Copy link
Member Author

@mateuszrzeszutek mateuszrzeszutek Apr 16, 2021

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.

Copy link
Contributor

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

Copy link
Member Author

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(
Copy link
Contributor

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?

Copy link
Member Author

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 😄

Copy link
Contributor

@anuraaga anuraaga left a 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


@ParameterizedTest
@MethodSource("destinations")
void shouldExtractAllAvailableAttributes(
Copy link
Contributor

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

@mateuszrzeszutek
Copy link
Member Author

Added StartTimeExtractor and EndTimeExtractor, those two should also be useful for metrics. And I've accidentally resolved #2600 for Instrumenter-using instrumentations too 😂

Comment on lines 63 to 73
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;
}
Copy link
Member Author

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

Copy link
Member

@trask trask left a 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 😂

🎉

Comment on lines +91 to +92
public InstrumenterBuilder<REQUEST, RESPONSE> setTimeExtractors(
StartTimeExtractor<REQUEST> startTimeExtractor, EndTimeExtractor<RESPONSE> endTimeExtractor) {
Copy link
Member Author

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
Copy link
Contributor

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.

Copy link
Member Author

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!

Copy link
Member Author

@mateuszrzeszutek mateuszrzeszutek May 4, 2021

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.

@iNikem iNikem merged commit e003417 into open-telemetry:main May 5, 2021
@mateuszrzeszutek mateuszrzeszutek deleted the instrumenter-messaging branch May 6, 2021 08:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants