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

Make spanKindExtractor configurable in Ktor instrumentations #8255

Merged
merged 3 commits into from
May 15, 2023

Conversation

orangain
Copy link
Contributor

@orangain orangain commented Apr 8, 2023

This PR solves #8139. Now spanKindExtractor is configurable in Ktor instrumentations.

This make it possible to customize the SpanKind depending on the request as following:

    install(KtorServerTracing) {
        setOpenTelemetry(openTelemetry)
        setSpanKindExtractor {
            SpanKindExtractor { req ->
                if (req.uri.startsWith("/from-pubsub/")) {
                    SpanKind.CONSUMER
                } else {
                    SpanKind.SERVER
                }
            }
        }
    }

@orangain orangain requested a review from a team as a code owner April 8, 2023 12:47
* Returns a new {@link Instrumenter} which will create spans with kind determined by the passed
* {@link SpanKindExtractor} and extract context from requests.
*/
public Instrumenter<REQUEST, RESPONSE> buildIncomingInstrumenter(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if it is ok to add such a public method to the InstrumenterBuilder, but I could not think of a better way to make SpanKindExtractor configurable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it is necessary to add a new method here (I kinda forgot about it earlier, when we were talking in GH discussions).

Since this is a stable public API, we need to make sure we come up with a good name. I'll list a few ideas I came up with here:

  • buildIncomingInstrumenter/buildOutgoingInstrumenter (pretty much what this PR proposes)
  • buildContextExtractingInstrumenter/buildContextInjectingInstrumenter
  • buildUpstreamInstrumenter/buildDownstreamInstrumeter
  • buildPropagatingToUpstreamInstrumenter/buildPropagatingToDownstreamInstrumeter
  • buildPropagatingInstrumenter for both

@open-telemetry/java-instrumentation-maintainers WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming is hard. Perhaps we should adopt a @Incubating or @Experimental annotations so such changes could be introduced more easily.
I think it is possible to implement this feature without introducing new api. You could use buildInstrumenter(spanKindExtractor) and do the context extraction manually before instrumenter.start() similarly to like it is done in PropagatingFromUpstreamInstrumenter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@laurit Thank you for your suggestion. I tried implementing this without introducing a new API.
orangain@daec120

While it is indeed possible to implement, I have a few concerns.

  • Doing context propagation within library instrumentation seems to be a violation of responsibilities. Wouldn't it be confusing if only Ktor instrumentation does context propagation on its own, while Instrumenter does it in other library instrumentations?
  • ContextPropagationDebug exists in the internal package, is it acceptable to use it in Ktor instrumentation? If not allowed, there is a concern that Ktor users will not be able to debug context propagation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@orangain While letting Instrumenter handle context propagation is preferable there are instrumentations that do it manually for a variety of reasons. This was just a suggestion on how to move this forward faster, if you so wish you can ignore it. You could also start with manual propagation and when the methods you need are added to Instrumenter you can start using them.
Using internal classes is fine everywhere in this repository. Marking classes internal is more for informing users outside this repository that these classes could change without prior notice. I think that in this case not using ContextPropagationDebug would also be fine.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @orangain I opened #8392 to unblock you PR -- I'll let you know when it's merged so that you can rebase on top of it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey @orangain, #8392 is merged now

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mateuszrzeszutek @trask @laurit Sorry for the late response. Thank you for unblocking my PR! I've rebased the PR to use InstrumenterUtil.buildUpstreamInstrumenter.

* Returns a new {@link Instrumenter} which will create spans with kind determined by the passed
* {@link SpanKindExtractor} and inject context into requests.
*/
public Instrumenter<REQUEST, RESPONSE> buildOngoingInstrumenter(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is not used at this time, but I added it to make it symmetrical with the buildIncomingInstrumenter.

@@ -52,6 +56,12 @@ class KtorServerTracing private constructor(
this.statusExtractor = extractor
}

fun setSpanKindExtractor(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not written any tests for this method, as there were no unit tests for the existing setStatusExtractor or addAttributeExtractor, is that ok?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have some integration tests that exercise the entire instrumentation module.
You could perhaps use the AbstractHttpServerUsingTest and HttpServerInstrumentationExtension directly and set up a simple HTTP server with one endpoint, just to verify that the span it emits has the span kind you want.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your detailed explanation, I added test cases in 959ee02.

Copy link
Member

@mateuszrzeszutek mateuszrzeszutek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @orangain !
LGTM 👍

@trask trask merged commit 9596fc7 into open-telemetry:main May 15, 2023
44 checks passed
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.

None yet

4 participants