Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

111 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿฉบ WireDoctor

"Your bean graph has a story. WireDoctor reads it."

WireDoctor is a runtime diagnostic and architectural analysis tool for Spring Boot. Add one dependency โ€” it hooks into the real, resolved ApplicationContext at startup and turns it into an interactive report, honest advice, and CI gates. Zero-intrusion, zero-dashboard-server, pure insights.

WireDoctor report โ€” Overview tab

Captured from a real run against start.spring.io (Boot 4.0.x, 390 beans) with performance gates armed โ€” the red GATE FAIL chip is a genuinely tripped gate, not a mockup. Full report tour โ†’

โ–ถ Open this exact report live in your browser โ€” no install needed; it's the self-contained HTML WireDoctor writes on every run.


Why WireDoctor?

  • "Why does this service take 40 seconds to boot now?" โ€” Actuator gives you raw StartupStep JSON; nobody ships the analysis layer on top. WireDoctor ranks the slow beans, computes the critical path, and tells you which @Lazy would pay off most.
  • "We bumped Spring Boot and a feature quietly broke." โ€” An autoconfiguration stopped matching and nobody noticed until production. WireDoctor diffs Boot's condition report across builds and catches the matched โ†’ notMatched flip in CI, with the exact condition message.
  • "Someone added a bean cycle six months ago and now it's load-bearing." โ€” Commit a baseline like a lockfile for your architecture; the PR that introduces a new cycle fails its build the same day, not at refactoring time.
  • "Which of these beans actually do anything?" โ€” Ghost detection crosses three signals to find beans that cost startup time and memory but show no sign of use โ€” honestly labeled, never overclaimed.

โœจ What it does

(Release history lives in the CHANGELOG.)

๐Ÿ” See โ€” the report

  • Interactive HTML console โ€” a single self-contained wiredoctor-report.html (tabs: Overview / Graph / Ghosts / Smells / Timing / Conditions) with a health-verdict header and a searchable, click-to-inspect dependency graph. Renders fully offline. โ†’ Report tour
  • Real startup timings โ€” per-bean instantiation times from BufferingApplicationStartup, no reflection heuristics.
  • The resolved graph โ€” read directly from getDependenciesForBean(): what Spring actually wired, not what the source suggests.
  • Condition snapshot โ€” Boot's autoconfiguration decisions, tabbed and filterable.
  • JSON export โ€” wiredoctor-report.json as the single source of truth for tooling; live views via /actuator/wiredoctor/*.

๐Ÿšจ Diagnose โ€” the analysis

  • Cycle detection with fix advice โ€” Tarjan SCC finds silently-resolved cycles, and lazySuggestions ranks which @Lazy breaks the most cycles with the smallest blast radius.
  • Startup critical path โ€” the instantiation-weighted dependency chain your readiness time actually sits on.
  • Architecture smells โ€” fan-in coupling hotspots, fan-out shotgun-surgery risk, and instability metrics on the live graph; framework beans filtered so every ranked bean is refactorable.
  • Ghost beans โ€” passive candidates (always on, labeled confidence: LOW) plus opt-in first-touch tracking for dev/staging. โ†’ Ghost Detector guide
  • Proxy overhead โ€” CGLIB/JDK proxy count exposing hidden indirection layers.

๐Ÿ›ก๏ธ Guard โ€” the CI gates

  • Architectural regression guard โ€” commit wiredoctor-baseline.json, fail the PR that adds a new cycle (fail-on=new-cycle). โ†’ CI gating guide
  • Upgrade Guard โ€” condition diff across Boot upgrades; gate on condition-changed. โ†’ Upgrade Guard guide
  • Performance gates โ€” fail on startup-time regressions (dual-threshold, noise-tolerant) and new slow beans (jitter-margin protected). โ†’ Performance Gates guide
  • CI-friendly output โ€” gates write wiredoctor-gate.status (PASS/FAIL) and wiredoctor-diff.json; the report is written even when a gate fails the build.

๐Ÿš€ Quick start

Add the dependency โ€” that's it. WireDoctor runs at startup, writes wiredoctor-report.html + wiredoctor-report.json, and prints a diagnostic summary to your logs.

Maven:

<dependency>
    <groupId>io.github.ddsha441981</groupId>
    <artifactId>wiredoctor-autoconfigure</artifactId>
    <version>1.0.0</version>
</dependency>

Gradle:

implementation 'io.github.ddsha441981:wiredoctor-autoconfigure:1.0.0'

Want CI gates? Capture a baseline once, commit it, arm the gates:

./mvnw spring-boot:run \
  -Dspring-boot.run.arguments="--wiredoctor.baseline=wiredoctor-baseline.json --wiredoctor.baseline-write=true"
git add wiredoctor-baseline.json && git commit -m "chore: WireDoctor baseline"
# application-ci.properties
wiredoctor.baseline=wiredoctor-baseline.json
wiredoctor.fail-on=new-cycle,startup-time,slow-bean

A tripped gate fails startup with a precise message:

WireDoctorRegressionException: WireDoctor regression gate 'startup-time' tripped:
  startup time increased by 734ms (18.2%) vs baseline (4025ms -> 4759ms)

Common knobs (wiredoctor.scan-packages, thresholds, output path, production kill-switch wiredoctor.enabled=false) are in the configuration reference.


โœ… Supported Versions

The full test suite runs against this matrix in CI (compat.yml); the table below reflects what is actually green, not what we hope works:

Spring Boot Java 17 Java 21 Java 25
2.7.x โœ… โœ… โœ…
3.3.x โœ… โœ… โœ…
3.5.x โœ… โœ… โœ…
4.0.x โœ… โœ… โœ…

Notes:

  • Floor is Boot 2.4: startup timings need BufferingApplicationStartup, introduced in Boot 2.4. Lines older than 2.7 are not CI-verified โ€” they may work, but you're on your own.
  • Boot lines between the tested ones (3.0โ€“3.2, 3.4) are expected to work since WireDoctor only uses stable spring-context / spring-boot APIs, but only the listed lines carry a CI guarantee.
  • WireDoctor itself is compiled for Java 17 bytecode, so Java 8/11 apps cannot load it even on Boot 2.7.
  • WebFlux (reactive, Netty): verified since v0.8.0 โ€” an integration test boots a reactive (non-servlet) context in CI and asserts reports, startup timings, and ghost analysis all work; RouterFunction, WebHandler, WebSocketHandler and WebExceptionHandler beans are recognized as entry points (never flagged as ghosts).

๐Ÿ“š Documentation

Guide What it covers
Report tour Every tab of the HTML console, explained with real screenshots
Configuration reference Every property, grouped by feature, with defaults
CI gating Fail your PR on a new bean cycle โ€” the full workflow
Performance gates Startup-time and slow-bean gates, thresholds, noise tolerance
Upgrade Guard Catching silent autoconfiguration changes across Boot upgrades
Ghost Detector Passive candidates + opt-in first-touch tracking, and their trust postures
Security posture What the reports expose, offline-only network behavior

Pre-generated sample reports (from real apps, including start.spring.io) are in sample/ โ€” or view the start.spring.io report live without cloning anything.


๐Ÿ”ฌ Epistemic Honesty & Known Limitations

Like any static/runtime analysis tool, WireDoctor prefers honest heuristics over false certainty:

  1. โšก AOT / GraalVM Native Image โ€” not supported, skipped gracefully: WireDoctor is designed for traditional JVM mode only. When running inside a GraalVM native image (detected at runtime via NativeDetector.inNativeImage()), the entire analysis is skipped automatically with a single WARN log line โ€” no crash, no incomplete report, no gates. Set wiredoctor.enabled=false in your native profile to silence the warning. Boot 3+ AOT compilation (not native-image runtime) is unaffected; analysis runs normally in JVM mode even when the app was compiled with AOT processing enabled.

  2. ๐Ÿ‘ป Orphan Bean Heuristic (Weak Signal): The tool reports "Orphan Beans" (beans with 0 incoming dependencies). This is a heuristic, not a guarantee that the bean is unused. Beans accessed dynamically via ApplicationContext.getBean(), event listeners, or scheduled tasks will appear as "orphaned". Since v0.6.0 the ghostCandidates section refines this (entry-point detection filters out controllers/listeners/runners), and opt-in ghost tracking measures actual invocation โ€” but even a tracked "untouched" bean only means not invoked during this run, never "unused".

  3. ๐Ÿ’ฅ Structural Cycles vs. Crashing Cycles: If Spring encounters an unresolvable cycle (e.g., constructor-to-constructor), the app crashes (BeanCurrentlyInCreationException) before WireDoctor can report it. WireDoctor detects resolved cycles (via setter injection or proxies) that succeed silently. These are reported as structural design smells.

  4. ๐Ÿ™ˆ Early-Reference Cycle Blindspot (allow-circular-references=true): Cycle detection uses getDependenciesForBean() which may not capture cycles resolved via Spring's early-reference mechanism (the 3-level cache earlySingletonObjects pathway). Only explicit @DependsOn and fully-registered constructor/setter dependencies are detected. Some silently resolved cycles might go unreported.

  5. ๐Ÿ”ญ Bean Scopes (pinned by tests since v0.8.0): Prototype and @Lazy bean definitions appear as graph nodes, but they are never instantiated by the analysis (zero-intrusion promise โ€” a regression test proves it). Their proxy status can't be known without instantiating them, so they are skipped by the proxy scan and honestly counted in proxies.notInstantiatedSkipped. FactoryBeans appear under the factory's bean name; a consumer of the product gets its dependency edge recorded against the factory's name (Spring's own bookkeeping). Runtime-only facts about these scopes โ€” how often a prototype is created, whether a lazy bean is ever touched โ€” are outside a startup snapshot's reach.

See KNOWN_ISSUES.md for the full, versioned list.


๐Ÿ”ฎ Roadmap

Next up: v1.0.0 โ€” API & schema freeze + Maven Central launch. Report schema stabilized, publish to Maven Central, launch.

Dropped (deliberately): Memory Footprint Estimation โ€” honest per-bean heap numbers need a Java Agent; shallow size-of is a correctness trap. The Ghost Detector answers the same underlying question ("which beans are wasting resources?") without lying about bytes.


๐Ÿค Contributing

Contributions are welcome โ€” bug reports, docs, tests, and features. See CONTRIBUTING.md for build/test conventions and the zero-intrusion design posture, and please follow the Code of Conduct. New here? Look for issues labelled good first issue.

Maintained by Deendayal Kumawat ยท LinkedIn ยท deendayal_kumawat@hotmail.com

๐Ÿ“„ License

Dual-licensed under MIT OR Apache-2.0 โ€” pick whichever suits your project.

About

๐Ÿฉบ Zero-intrusion runtime diagnostic and architectural analyzer for Spring Boot. Automatically detects cyclic dependencies, proxy overheads, and startup bottlenecks with an interactive physics-based HTML dashboard.

Topics

Resources

Code of conduct

Contributing

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages