Skip to content

API Reference

Frody edited this page Sep 4, 2026 · 1 revision

Complete API Reference

This document provides exhaustive documentation of all public classes, methods, parameters, and configuration options available in LoomDoctor.


1. io.github.frodygr.loomdoctor.core.LoomDoctor

The top-level facade coordinating Virtual Thread pinning detection, connection pool starvation tracking, and comprehensive diagnostic reporting.

Constructors

Constructor Description
LoomDoctor() Instantiates a default LoomDoctor instance with internally managed PinningDetector and PoolStarvationDetector.

Public Methods

getPinningDetector()

  • Signature: public PinningDetector getPinningDetector()
  • Description: Returns the underlying circular buffer pinning detector instance.
  • Returns: PinningDetector - the active pinning event buffer and listener dispatcher.

getStarvationDetector()

  • Signature: public PoolStarvationDetector getStarvationDetector()
  • Description: Returns the resource pool starvation monitor.
  • Returns: PoolStarvationDetector - the pool queue and starvation tracker.

diagnose()

  • Signature: public LoomDiagnosticsReport diagnose()
  • Description: Gathers pinning counts, recent incidents, pool states, and calculates an overall health status with prioritized mitigation recommendations.
  • Returns: LoomDiagnosticsReport - snapshot containing health status, pinning counts, pool metrics, and advice strings.

Example

LoomDoctor doctor = new LoomDoctor();

// Check system health
LoomDiagnosticsReport report = doctor.diagnose();
if (report.getStatus() == LoomHealthStatus.CRITICAL) {
    logger.error("Virtual thread infrastructure critical: {}", report.getRecommendations());
}

2. io.github.frodygr.loomdoctor.core.pinning.PinningDetector

A thread-safe, bounded circular buffer (default capacity: 500) that logs carrier pinning events without risking OutOfMemoryError.

Public Methods

recordPinning(PinningEventType type, String virtualThreadName, String carrierThreadName, long durationMs, String location, String stackTrace)

  • Signature: public PinningEvent recordPinning(PinningEventType type, String virtualThreadName, String carrierThreadName, long durationMs, String location, String stackTrace)
  • Description: Records a new pinning event, adds it to the internal circular buffer, increments total counts, and notifies all registered listeners.
  • Parameters:
    • type (PinningEventType): The root cause of the pinning (e.g., SYNCHRONIZED_BLOCK).
    • virtualThreadName (String): Identifier or name of the pinned virtual thread.
    • carrierThreadName (String): Name of the underlying OS worker thread (e.g., ForkJoin worker).
    • durationMs (long): Duration in milliseconds that the thread was held pinned.
    • location (String): Exact class and method signature where pinning occurred.
    • stackTrace (String): Truncated or full stack trace captured during the event.
  • Returns: PinningEvent - The immutable recorded event object.

addListener(PinningListener listener)

  • Signature: public void addListener(PinningListener listener)
  • Description: Registers a callback to be invoked whenever a pinning event is captured. Useful for alerting, Slack webhooks, or Micrometer custom metrics.
  • Parameters:
    • listener (PinningListener): Consumer callback accepting the recorded PinningEvent.

removeListener(PinningListener listener)

  • Signature: public void removeListener(PinningListener listener)
  • Description: Unregisters a previously registered listener.
  • Parameters:
    • listener (PinningListener): The listener to remove.

getRecentEvents(int limit)

  • Signature: public List<PinningEvent> getRecentEvents(int limit)
  • Description: Retrieves the most recent pinning incidents in reverse chronological order (newest first).
  • Parameters:
    • limit (int): Maximum number of events to retrieve.
  • Returns: List<PinningEvent> - Unmodifiable list of recent events.

getTotalPinningCount()

  • Signature: public long getTotalPinningCount()
  • Description: Total number of pinning occurrences recorded since application startup.
  • Returns: long - Cumulative pinning count.

clear()

  • Signature: public void clear()
  • Description: Resets the event buffer and clears accumulated counters.

Example

PinningDetector detector = doctor.getPinningDetector();

// Add an alerting listener
detector.addListener(event -> {
    if (event.durationMs() > 100) {
        alertService.notify("High-latency pinning in " + event.location() + " (" + event.durationMs() + "ms)");
    }
});

// Record an event
detector.recordPinning(
    PinningEventType.SYNCHRONIZED_BLOCK,
    Thread.currentThread().toString(),
    "ForkJoinPool-worker-1",
    120,
    "com.example.LegacyClient.call()",
    "at com.example.LegacyClient.call(LegacyClient.java:45)"
);

3. io.github.frodygr.loomdoctor.core.pinning.PinningEvent

Immutable record representing an individual pinning event.

Record Components / Getters

Component Type Description
eventType() PinningEventType Classification of the cause (SYNCHRONIZED_BLOCK, SYNCHRONIZED_METHOD, NATIVE_CALL, CUSTOM).
virtualThreadName() String Virtual thread name or descriptor.
carrierThreadName() String Physical carrier thread blocked during execution.
durationMs() long Milliseconds the carrier thread remained pinned.
location() String Source code file/class/method location string.
stackTrace() String Diagnostic stack trace snippet.
timestamp() Instant UTC instant when the event was recorded.

4. io.github.frodygr.loomdoctor.core.pinning.PinningEventType

Enumeration classifying why the virtual thread became pinned:

  • SYNCHRONIZED_BLOCK: Pinned inside a synchronized (lock) { ... } block holding I/O or blocking code.
  • SYNCHRONIZED_METHOD: Pinned inside a method declared with the synchronized modifier.
  • NATIVE_CALL: Pinned inside a Java Native Interface (JNI) or Foreign Function & Memory (FFM) call.
  • CUSTOM: Application-defined or external profiling hook classification.

5. io.github.frodygr.loomdoctor.core.starvation.PoolStarvationDetector

Tracks pool contention and thread queuing across database connection pools (e.g., HikariCP, Tomcat JDBC) or third-party client resource pools.

Public Methods

registerPool(String poolName, int activeConnections, int queuedThreads)

  • Signature: public PoolMetricsSnapshot registerPool(String poolName, int activeConnections, int queuedThreads)
  • Description: Updates telemetry for a named pool, recalculating the wait-to-capacity ratio and flagging starvation alerts.
  • Parameters:
    • poolName (String): Unique pool identifier (e.g., "HikariPool-1").
    • activeConnections (int): Number of currently leased connections.
    • queuedThreads (int): Number of threads awaiting an available connection.
  • Returns: PoolMetricsSnapshot - The calculated snapshot for this pool.

getPool(String poolName)

  • Signature: public Optional<PoolMetricsSnapshot> getPool(String poolName)
  • Description: Fetches the latest recorded metrics for a specific pool name.
  • Parameters:
    • poolName (String): The pool identifier.
  • Returns: Optional<PoolMetricsSnapshot> - Present if registered, empty otherwise.

getAllPools()

  • Signature: public List<PoolMetricsSnapshot> getAllPools()
  • Description: Returns all tracked pool snapshots.
  • Returns: List<PoolMetricsSnapshot> - Unmodifiable snapshot collection.

hasStarvationRisks()

  • Signature: public boolean hasStarvationRisks()
  • Description: Returns true if any tracked pool has a wait ratio exceeding the configured threshold.
  • Returns: boolean - true if starvation is occurring.

setStarvationThresholdRatio(double ratio)

  • Signature: public void setStarvationThresholdRatio(double ratio)
  • Description: Configures the ratio of queuedThreads / activeConnections that triggers a starvation alert (default: 2.0).
  • Parameters:
    • ratio (double): Threshold ratio.

Example

PoolStarvationDetector detector = doctor.getStarvationDetector();

// Update metrics periodically from HikariPoolMXBean
detector.registerPool(
    "HikariPool-OrderDB",
    hikariMXBean.getActiveConnections(), // e.g. 10
    hikariMXBean.getThreadsAwaitingConnection() // e.g. 85
);

if (detector.hasStarvationRisks()) {
    log.warn("Database connection pool is starving virtual threads!");
}

6. io.github.frodygr.loomdoctor.core.metrics.LoomDiagnosticsReport

Comprehensive diagnostic report generated by LoomDoctor.diagnose().

Record Components / Getters

Component Type Description
status() LoomHealthStatus Overall runtime health (HEALTHY, DEGRADED, CRITICAL).
totalPinningCount() long Total pinning events recorded since boot.
recentPinning() List<PinningEvent> Most recent sample pinning incidents.
pools() List<PoolMetricsSnapshot> Current state of monitored connection pools.
recommendations() List<String> Actionable advice explaining how to resolve detected issues.
timestamp() Instant UTC timestamp of diagnostic generation.

7. Spring Boot Actuator Integration

Endpoint: /actuator/loom-doctor

Provided by loomdoctor-spring-boot-starter.

  • HTTP Method: GET
  • Produces: application/json
  • Response: Full serialization of LoomDiagnosticsReport.

Minimal application.yml

loomdoctor:
  enabled: true
  pinning-threshold-ms: 50
  queue-starvation-ratio: 2.0

management:
  endpoints:
    web:
      exposure:
        include: "health,info,loom-doctor"

Clone this wiki locally