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
[Feature]: Visualize uninstrumented services in the dependency diagrams #3804
Comments
Hi @yurishkuro, I like your idea to just add it to the trace enrichment. Can you help me where to find the code of this? So I can try my luck to implement it? :) |
@paule96 the dependencies calculation done by all-in-one happens inside jaeger/plugin/storage/memory/memory.go Line 63 in 711488f
It may not be very straightforward to combine this with the enricher idea because dependencies logic does not query for traces, it just accesses them directly. |
@yurishkuro I am planning to look into this issue. Will share my findings here and also create a WIP PR. |
Hi @yurishkuro, |
Hi @yurishkuro, 1. In-Memory Storage Modification:
2. Flink/Spark Jobs Modification (for Production Usage):
Alternative - Trace Enrichment:
I am eager to kick start the implementation upon your feedback and any additional insights or considerations that should be taken into account to align with Jaeger’s existing architecture. |
@nidhey27 I don't completely follow your write-up. E.g. in step 1, are you presenting multiple options or think all 3 steps need to be done? I wouldn't go with a trace enrichment approach. The basic logic in both implementations is to construct a tree of spans, and walk it while outputting parent-child links. In that algorithm, it's pretty easy to add an extra conditional branch to handle leaf CLIENT spans. The other issue you will run into is figuring out the name of the destination service from the client span. Sometimes it may have a peer.service tag, but it may not. You will likely need to build a bit of heuristic to infer the destination from a combination of tags on the client span. This will probably require understanding a number of semantic conventions, e.g. to detect that it's a database call (and specifically which database). Unfortunately, this logic will be way more complicated than the piece I mentioned above, and even more unfortunately that we have independent Go and Java implementations for it. |
@yurishkuro I had initially set my sights on inserting artificial server spans into the in-memory store to represent those uninstrumented services, and then bringing these artificial spans into play during dependency calculations and visualizations. However, having absorbed your insights, I’ve pivoted my approach for something a bit more streamlined and, dare I say, elegant.
As for the heuristic approach to nail down the destination service name, that’s still a work in progress - I’m exploring and weighing my options there. Could you please confirm if this approach is in sync with your expectations, or is there room for some tweaks? |
approach makes sense to me. |
Requirement
Visualize services in the dependency diagram even when they are not instrumented, but known from the caller side.
Problem
When the trace leaf nodes that represent outbound calls to uninstrumented services, those services are not shown in the dependency diagram (e.g. see how Zipkin shows them in #3803).
Proposal
Jaeger can infer that there is an existing callee service when the caller service logs a span with tag
span.kind=client
without the correspondingspan.kind=server
span.There are several places in the code base where this will need to be accounted for:
Aside from changing the graph logic, another alternative is to have a trace enrichment which will add artificial
server
spans to the trace. Then the graph building logic would not need to change at all, and the inferred nodes could also be shown in the single-trace views.Open questions
Deciding what to call the missing callee services can be tricky. We will need to implement a heuristic that derives the name from some of the tags of the client span:
peer.service
peer.address
peer.ip?
+peer.port
There was a discussion in OTEL once about labeling the type of downstream service (e.g. an SQL db, etc), which could also be taken into account when naming the derived services.
The text was updated successfully, but these errors were encountered: