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

[WIP] Add peer.service to Instrumenter API #3050

Conversation

mateuszrzeszutek
Copy link
Member

We should add peer.service extractor to Instrumenter API as soon as possible so that we don't lose existing functionality when migrating tracers.
This attribute is only used in the agent - the problem is, NetAttributesExtractor implementations are package-private in library instrumentations and agent code currently has no way to inject another extractor that depends on the private net one.
For example:

private static final ArmeriaTracing TRACING = ArmeriaTracing.create(GlobalOpenTelemetry.get());

I thought of several options on how to handle this:

  1. Just add the attribute to NetAttributesExtractor;
  2. Create a separate extractor just for peer.service and keep it in instrumentation-api so that it's accessible to library instrumentation code; the library instrumentations have to add it even though it's useless without javaagent (this PR implements this solution);
  3. Add a getter to the builder: InstrumenterBuilder#attributeExtractors() (and library instrumentations tracing builders...) and in the agent code find net attributes extractor using instanceof and if it's there, add the peer service one. This is hacky, and you have to do it in each javaagent instrumentation...
  4. Add a Function<InstrumenterBuilder, InstrumenterBuilder> hook to instrumentation-api that'll be implemented in the javaagent (similar to e.g. rxjava hooks that we use in our instrumentations) that'll do the instanceof check. This option sort of implements Support for subclassing instrumentation Tracers in custom distributions #778

WDYT? I'd like to get your opinion on this matter as I don't have any strong preference towards any of these options (and maybe there's another one that I didn't think of)

TODO: tests, javadocs

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.

Create a separate extractor just for peer.service and keep it in instrumentation-api so that it's accessible to library instrumentation code; the library instrumentations have to add it even though it's useless without javaagent (this PR implements this solution);

This doesn't seem to be the approach in this PR since you add it in javaagent instrumentation not library instrumentation, right?

  1. Seems like an interesting option if we know other real use cases wonder if anything comes to mind?

* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.api.instrumenter.net;
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess this should be in javaagent-api since it's only for auto instrumentation?

Copy link
Member Author

Choose a reason for hiding this comment

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

That's the problem: if I put it inside javaagent-api then I'd have to make library instrumentations (armeria, okhttp, ...) depend on javaagent-api to use that (because NetAttributeExtractor implementations are package-private and not visible from the javaagent code).

Copy link
Contributor

Choose a reason for hiding this comment

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

Oops package names are so long so got confused. Hmm - yeah we definitely shouldn't use this code from library instrumentation, libraries are just supposed to be called with something like .addAttributeExtractor(FixedAttributeExtractor.of(PEER_SERVICE, "my-service")), there's no point of the map approach outside of agent and it shouldn't be supported.

Should we just access the package private ArmeriaNetAttributesExtractor from the agent reflectively?

Copy link
Member Author

Choose a reason for hiding this comment

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

Should we just access the package private ArmeriaNetAttributesExtractor from the agent reflectively?

Hmm, that would work too -- I'll implement that option in this PR and we'll see how it looks.


INSTRUMENTER =
Instrumenter.<HttpMethod, Void>newBuilder(
GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, spanNameExtractor)
.setSpanStatusExtractor(spanStatusExtractor)
.addAttributesExtractor(httpAttributesExtractor)
.addAttributesExtractor(new ApacheHttpClientNetAttributesExtractor())
.addAttributesExtractor(netAttributesExtractor)
Copy link
Contributor

Choose a reason for hiding this comment

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

This is the approach I had in mind. I guess it's a bit tedious, but we could do it for now as a quick fix, luckily being agent code we're never stuck with it long term.

@mateuszrzeszutek
Copy link
Member Author

  1. Seems like an interesting option if we know other real use cases wonder if anything comes to mind?

Adding custom attributes/metrics to built-in javaagent instrumentations?

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.

This seems to do a good job of keeping the agent-specific logic to the agent. It's too bad it makes the net attributes not follow the pattern of the others with protected methods. Maybe we should just go with public for all of them though, since they're user-implemented classes the visibility doesn't matter that much I guess.

@mateuszrzeszutek
Copy link
Member Author

mateuszrzeszutek commented May 24, 2021

Maybe we should just go with public for all of them though, since they're user-implemented classes the visibility doesn't matter that much I guess.

💯
That'll even make testing a bit easier, since you'll be able to call AttributesExtractor methods directly:

AttributesExtractor<?> ae = new MyExtractor<>();
// onStart is now public, can be called by other packages
ae.onStart(...);

@mateuszrzeszutek mateuszrzeszutek force-pushed the peer-service-attribute-extractor branch from 96730cf to 75eeca7 Compare May 24, 2021 13:14
@mateuszrzeszutek
Copy link
Member Author

I ended up making only NetAttributesExtractor public - I'll change all other extractors in a separate PR, to minimize merge conflicts in this one.

@mateuszrzeszutek mateuszrzeszutek marked this pull request as ready for review May 24, 2021 13:15
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.

I'm ok with this, thanks for getting the functionality back. Hopefully we'll see some patterns emerge in the future and come up with something nicer (or realize that this is just a weird one-off and we can live with it).

@mateuszrzeszutek mateuszrzeszutek force-pushed the peer-service-attribute-extractor branch from 3b5524b to 486af3f Compare May 25, 2021 11:30
@mateuszrzeszutek mateuszrzeszutek merged commit d755654 into open-telemetry:main May 25, 2021
@mateuszrzeszutek mateuszrzeszutek deleted the peer-service-attribute-extractor branch May 25, 2021 13:31
robododge pushed a commit to robododge/opentelemetry-java-instrumentation that referenced this pull request Jun 17, 2021
* [WIP] Add peer.service to Instrumenter API

* Move PeerServiceAttributesExtractor to javaagent-api and use reflection to add it

* Finish PeerServiceAttributesExtractor

* Fix tests

* Add peer.service to apache-httpclient-5.0, jedis-1.4, lettuce-4.0
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.

3 participants