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

Trace methods of all classes under a package by otel.instrumentation.methods.include=my.package.** #2574

Open
Johnny850807 opened this issue Mar 15, 2021 · 11 comments
Labels
contribution welcome Request makes sense, maintainers probably won't have time, contribution would be welcome enhancement New feature or request

Comments

@Johnny850807
Copy link

Johnny850807 commented Mar 15, 2021

Is your feature request related to a problem? Please describe.
I'd like to trace all the classes/methods under a package recursively using the otel.instrumentation.methods.include system property, without naming every class.

I think this is a really powerful feature if we can achieve such transparency for in-process tracing like this, as in many situations, we hope that our core domain's module is agnostic of how they are traced.

So we can no longer depend on the open-telemetry instrumentation API's @WithSpan.

Describe the solution you'd like

Given I have a Spring-Boot project as below

src
│   └── main
│       ├── java
│       │   └── com
│       │       └── example
│       │           └── demo
│       │               ├── DemoApplication.java
│       │               ├── SignIn.java
│       │               ├── SignInRequest.java
│       │               ├── SignUp.java
│       │               ├── User.java
│       │               ├── UserController.java
│       │               ├── UserPresenter.java
│       │               └── UserRepository.java

I want to set -Dotel.instrumentation.methods.include=com.example.demo or -Dotel.instrumentation.methods.include=com.example.demo.** to include all my application classes for tracing.

Could we achieve this?


This feature may produce many spans and is considered dangerous.
However, I think we can emphasize its consequences to the users,
but be able to support the full transparency if the user asks to.

If it's properly used then we can see a trace like:
(In a Clean Architecture style)

[POST] /api/chessGames/13/chess
  └──PlayChessController.putChess
      ├── PutChessUseCase.putChess (Domain)
      | └── SpringBootChessGameRepository 
      |      ├── CrudRepository.findById 
      |      └── DataMapper.toEntity
      ├──  ChessGame.putChess (Domain)
      |      └── Board.setChess
      ├── SpringBootChessGameRepository 
      |      ├── DataMapper.toData
      |.     └── CrudRepository.save  
      │          └── INSERT INTO ...
      └── ChessGamePresenter.present

Alternatives

Consider that there may be so many spans produced,
the alternative is that Include only the Spring bean's methods under a package*

Thanks for your time on my post.

@Johnny850807 Johnny850807 added the enhancement New feature or request label Mar 15, 2021
@iNikem
Copy link
Contributor

iNikem commented Mar 15, 2021

It certainly can be added, but we have to think about corner cases here. Do you want ALL methods or only public ones? What about methods inherited from superclasses? What if one instrumented method directly calls another one, do you want 2 spans? This is quite dangerous feature that may result in millions of spans...

@Johnny850807
Copy link
Author

It certainly can be added, but we have to think about corner cases here. Do you want ALL methods or only public ones? What about methods inherited from superclasses? What if one instrumented method directly calls another one, do you want 2 spans? This is quite dangerous feature that may result in millions of spans...

Do you want ALL methods or only public ones

Only the public methods are included.

What about methods inherited from superclasses?

Only the lowest method's execution is instrumented.

What if one instrumented method directly calls another one, do you want 2 spans?

Yes, in this case, I want 2 spans.

This may produce many spans.
However, I think we can emphasize its consequences to the users,
but be able to support the full transparency if the user asks to.

If it's properly used then we can see a trace like:
(In a Clean Architecture style)

[POST] /api/chessGames/13/chess
  └──PlayChessController.putChess
      ├── PutChessUseCase.putChess (Domain)
      | └── SpringBootChessGameRepository 
      |      ├── CrudRepository.findById 
      |      └── DataMapper.toEntity
      ├──  ChessGame.putChess (Domain)
      |      └── Board.setChess
      ├── SpringBootChessGameRepository 
      |      ├── DataMapper.toData
      |.     └── CrudRepository.save  
      │          └── INSERT INTO ...
      └── ChessGamePresenter.present

This is helpful in case that we don't want our core domain module to depend on Open-telemetry's APIs.

@mateuszrzeszutek
Copy link
Member

If you don't want to depend on otel APIs you can always add your own @interface Traced annotation and configure the agent to add spans whenever it encounters it: -Dotel.instrumentation.external-annotations.include=my.app.Traced.
The downside of this approach is that you have to annotate every single method, as we don't detect class usage.

@Johnny850807
Copy link
Author

If you don't want to depend on otel APIs you can always add your own @interface Traced annotation and configure the agent to add spans whenever it encounters it: -Dotel.instrumentation.external-annotations.include=my.app.Traced.
The downside of this approach is that you have to annotate every single method, as we don't detect class usage.

Good suggestion! Thanks for your info.
As you said, I still need to annotate every single method, which does not suffice those who are really care about the domain's purity 😂.

@stnor
Copy link

stnor commented May 3, 2021

Class level annotations aren't supported?
-Dotel.instrumentation.external-annotations.include=org.springframework.stereotype.Service doesn't seem to do anything for example.

@stnor
Copy link

stnor commented May 3, 2021

I'd like to write my own aspect to handle my application's tracing to COMPLEMENT the otel javaagent, but it's unclear to me how to proceed after reading https://opentelemetry.io/docs/java/manual_instrumentation/

@stnor
Copy link

stnor commented May 4, 2021

I got some help from @anuraaga and solved it here:
aws/aws-xray-sdk-java#281 (comment)

@delanym
Copy link

delanym commented Apr 26, 2022

Would be handy

@AndresPineros
Copy link

AndresPineros commented Dec 26, 2022

This would be very helpful. Temporarily turning on packages with regexes would be very useful to debug whenever a performance issue is not located in the currently included methods.

APM services such as AppDynamics only export these in-depth spans whenever the trace is problematic (slow or exception). I think this is a great strategy because it saves money (only a small percentage should be slow or error) and gives in-depth information for issues without having to manually instrument or manually configure specific methods/classes. I think what is considered "slow" and "error" can be configured. I think they also "crop" the spans to show only the relevant pieces involed in the slowness or the errors, that way 1000 spans won't be sent for each problematic trace. Further sampling could be done via the collector. This is much easier said than done, but it is an elegant solution that covers what 99% of users need.

Configuring specific methods or classes can be brittle, specially when the code that is instrumented is located in third party libraries that can change their class structure any time.

@trask
Copy link
Member

trask commented Jan 3, 2023

profiling is generally my go-to when the performance issue is not located in the currently included methods.

the OpenTelemetry community kicked off Profiling work in 2022, with one of the goals being to correlate Profiling with Tracing, which would allow you to dig into a specific slow request and look at an execution profile for it

@DGuhr
Copy link

DGuhr commented Mar 3, 2024

Based on the information here (thanks) I created this repository specific to spring boot, with a working aspect-based instrumentation of all public methods inside @Component,@Service and @Repository: https://github.com/DGuhr/spring-otel-extended

currently, I am trying to build an agent extension to do this instead of the aspects, but for some reason it does not get picked up. If anyone could help me out, that'd be quite awesome. I thought I'd post it here so others have a working aspect-based solution (at least for spring).

The extension works now, so feel free to grab it and use it as a starting point for your use case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contribution welcome Request makes sense, maintainers probably won't have time, contribution would be welcome enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

8 participants