Skip to content

About

A passive local analyzer that infers service dependencies and retry edges from traces without a service registry.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

Runtime Dependency Inference

A passive, local analyzer that infers service dependencies, asynchronous fan-out, and retry edges from OpenTelemetry JSON without a service registry. Every inferred edge retains confidence, causal evidence, observation counts, and version history.

The bundled demo reveals that shop/audit-archive, a supposedly isolated service, is connected to checkout through a single low-volume Kafka path. It also detects a fulfillment-to-inventory retry cycle and distinguishes evidence that is merely time-correlated from evidence joined by an exact message ID.

Requirements and setup

  • Node.js 20 or newer
  • npm (bundled with Node.js)

There are no third-party packages and no install step. The tool neither opens sockets nor calls external APIs. From the repository root, run all quality gates with:

npm run check

Run the demo

From the repository root:

node src/cli.js analyze samples/deploy-17.otlp.json --version deploy-17 --out build/deploy-17.graph.json
node src/cli.js analyze samples/deploy-18.otlp.json --version deploy-18 --out build/deploy-18.graph.json
node src/cli.js diff build/deploy-17.graph.json build/deploy-18.graph.json

The final command reports three added edges, one removed edge, and one confidence change. In particular, it prints the new hidden path and retry relation:

+ async shop/checkout -> shop/audit-archive via order-audit (99% confidence)
+ retry shop/fulfillment-worker -> inventory-api (94% confidence; 2 retries)

Add --json to either command for machine-readable output. analyze --json emits a graph snapshot; diff --json emits the full change set. Run node src/cli.js --help for the concise command reference.

Accepted input

The importer reads the standard OTLP JSON resourceSpans shape, including both current scopeSpans and legacy instrumentationLibrarySpans. It uses these OpenTelemetry semantic attributes when present:

  • service.namespace, service.name, and service.version for identity
  • peer.service, server.address, net.peer.name, or http.host for synchronous peers
  • messaging.destination.name and messaging.message.id for cross-trace asynchronous correlation
  • app.request.id or request.id, operation name, timing, and status for retry classification

The CLI fails on malformed trace/span identifiers, invalid or reversed timestamps, malformed typed attributes or snapshots, unknown options, and missing option values instead of silently manufacturing topology. It also refuses to replace the input trace through --out and creates output directories as needed. Sensitive values—including message and request correlation IDs, user IDs, emails, tokens, authorization values, cookies, passwords, secrets, and API keys—are SHA-256 hashed during import. Raw span attributes are not written to graph snapshots. Snapshot files are replaced atomically and created with owner-only permissions where the platform supports POSIX modes.

Exact asynchronous joins require compatible destinations and messaging systems, and one produced message can fan out to multiple consumers. The lower-confidence time heuristic is used only when both sides lack a message ID, so known but different IDs are never joined merely because their timestamps are close. Unqualified peer names are reconciled to a namespace only when exactly one observed service is a match.

Confidence model

  • Exact producer/consumer message ID: 0.99
  • Same destination within five minutes, with no message ID: 0.68
  • Client span with an explicit peer hint: 0.90
  • Repeated failed request attempts with a stable request ID: 0.94
  • Repeated attempts inferred without a request ID: 0.76

These values are explicit heuristics, not probabilities learned from a production population. Consumers should use the attached evidence and confidence rather than treating inferred edges as ground truth.

Retry inference requires non-overlapping attempts no more than five minutes apart. Every attempt before the final one must have error status. Without a request ID, attempts must also share a non-empty parent span ID. The snapshot differ reports confidence, observation-count, retry-count, and evidence-method changes; new span IDs alone do not create change noise when the evidence method is the same.

See docs/architecture.md for component boundaries, inference rules, and known limits.

License

MIT

About

A passive local analyzer that infers service dependencies and retry edges from traces without a service registry.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages