Skip to content

Build1 publisher2 min readPublished

JetBrains' Service Map draws the architecture from each span the moment it arrives

The OpenTelemetry plugin classifies spans off their attributes and folds each one into an architecture model on arrival. A trace never signals that it is complete, so the algorithm never waits for one.

The Engineer · Build desk

Illustration accompanying JetBrains' Service Map draws the architecture from each span the moment it arrives

What happened

  • JetBrains has shipped a Service Map in its OpenTelemetry plugin that auto-generates an architecture map from runtime data, built by the Rider Execution team with Software Engineering Research.
  • Starting the IDE with the plugin enabled starts a lightweight local OpenTelemetry backend, which processes the telemetry the running application sends to it.
  • The map is built from traces rather than logs or metrics, on the grounds that traces show a request's journey through the system and are made up of spans.
  • Spans arrive independently in no guaranteed order, and JetBrains says a parent span can finish and arrive after its own child has already been processed.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • cost The plugin does nothing for a team that has not instrumented: the run sequence assumes an application already emitting spans, so the bill is OpenTelemetry SDK work in each service, paid before any diagram appears.
  • capability One tool can map a polyglot estate with no per-language support, provided every library in the path emits spans the way the OpenTelemetry conventions specify.
  • constraint What you get is a picture of the instrumented processes that exported to the local backend during that run, so the map doubles as a report on your instrumentation coverage and your test traffic.

A trace never explicitly says it is done, and JetBrains says the plugin can never be 100% sure a late-arriving span is not about to show up [8]. So it does not wait for one: the reconstruction is written as a stream algorithm that processes every span the moment it lands, instead of holding out for a complete trace [10]. Clicking the Service Map tab fetches whatever structural model the backend holds at that instant and renders it [6].

Classification is attribute inspection, and it has to be. OpenTelemetry does not provide a strictly typed version for each span type; each span carries a key-value map of attributes, and the plugin deduces what interaction it is looking at by reading them [9]. Attributes such as `http.request.method` and `http.response.status_code` say HTTP call, while other attribute sets point at a database query or a message queue interaction [11]. Classification depends on the span carrying the attributes the classifier reads [2]. JetBrains does not quantify how complete the resulting map is.

The stack-independence claim is conditional. The post says the plugin can visualize a system completely independently of your technology stack, "as long as your app and libraries emit spans the way OTel expects" [12]. The condition matters, because the classifier keys on specific attribute names [11].

The opening case in the post is the diagram that is six months out of date, where "Service A hasn't talked to Service B since the spring, and there's a new message queue nobody bothered to document" [13]. Trace data handles the second half well: an undocumented queue that carries traffic emits spans, and spans put it on the map [3]. The first half comes back in a new shape. A missing edge means either the call no longer happens or nothing triggered it while the backend was collecting, and the rendered model does not separate those two [3].

JetBrains calls a map built this way "the source of runtime truth", on the grounds that it is not guessing from source code or outdated specs [16]. Measured against static analysis, which the post says "often fails to capture how services are actually wired together at runtime" [14], that comparison holds for the code paths that ran.

What to watch

  • Whether the classifier grows past HTTP, database and message queue interactions, and which attribute keys it reads for each new one.
  • Whether services the IDE did not launch can be pointed at the local backend; that would widen the map beyond one process tree.
  • Whether the internal model persists across runs or resets each time, since that decides what a missing edge means.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories