async-inspect ๐Ÿ”

December 30, 2025 ยท View on GitHub

async-inspect ๐Ÿ”

X-ray vision for async Rust

CI Crates.io Documentation License: MIT codecov

async-inspect is a debugging tool that visualizes and inspects async state machines in Rust. See exactly what your futures are doing, where they're stuck, and why.

Documentation | Crates.io | API Docs

๐Ÿ˜ฐ The Problem

Debugging async Rust is frustrating:

#[tokio::test]
async fn test_user_flow() {
    let user = fetch_user(123).await;      // Where is this stuck?
    let posts = fetch_posts(user.id).await; // Or here?
    let friends = fetch_friends(user.id).await; // Or here?
    
    // Test hangs... but WHERE? WHY? ๐Ÿ˜ฑ
}

What you see in a regular debugger:

Thread blocked in:
  tokio::runtime::park
  std::sys::unix::thread::Thread::sleep
  ???

โŒ Useless! You can't tell:

  • Which .await is blocked
  • What the future is waiting for
  • How long it's been waiting
  • What state the async state machine is in

Common async debugging nightmares:

  • ๐ŸŒ Tests hang forever (where?)
  • ๐Ÿ”„ Deadlocks with no stack trace
  • โฐ Timeouts that shouldn't happen
  • ๐ŸŽฒ Flaky tests (race conditions)
  • ๐Ÿ“‰ Performance issues (lock contention? slow I/O?)

Current "solutions":

// Solution 1: Add prints everywhere ๐Ÿ˜ญ
async fn fetch_user(id: u64) -> User {
    println!("Starting fetch_user");
    let result = http_get(url).await;
    println!("Finished fetch_user");
    result
}

// Solution 2: Use tokio-console (limited visibility)
// Solution 3: Give up and add timeouts everywhere ๐Ÿคท

๐Ÿ’ก The Solution

async-inspect gives you complete visibility into async execution:

$ async-inspect run ./my-app

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ async-inspect - Task Inspector                              โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                             โ”‚
โ”‚ Task #42: fetch_user_data(user_id=12345)                    โ”‚
โ”‚ Status: BLOCKED (2.3s)                                      โ”‚
โ”‚ State: WaitingForPosts                                      โ”‚
โ”‚                                                             โ”‚
โ”‚ Progress: โ–“โ–“โ–“โ–“โ–“โ–‘โ–‘โ–‘ 2/4 steps                                โ”‚
โ”‚                                                             โ”‚
โ”‚ โœ… fetch_user() - Completed (145ms)                         โ”‚
โ”‚ โณ fetch_posts() - IN PROGRESS (2.3s) โ—„โ”€โ”€โ”€ STUCK HERE       โ”‚
โ”‚    โ””โ”€> http::get("api.example.com/posts/12345")             โ”‚
โ”‚        โ””โ”€> TCP: ESTABLISHED, waiting for response           โ”‚
โ”‚        โ””โ”€> Timeout in: 27.7s                                โ”‚
โ”‚ โธ๏ธ  fetch_friends() - Not started                           โ”‚ 
โ”‚ โธ๏ธ  build_response() - Not started                          โ”‚
โ”‚                                                             โ”‚
โ”‚ State Machine Polls: 156 (avg: 14.7ms between polls)        โ”‚
โ”‚                                                             โ”‚
โ”‚ Press 'd' for details | 't' for timeline | 'g' for graph    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Now you know EXACTLY:

  • โœ… Which step is stuck (fetch_posts)
  • โœ… What it's waiting for (HTTP response)
  • โœ… How long it's been waiting (2.3s)
  • โœ… What will happen next (timeout in 27.7s)
  • โœ… Complete execution history

๐ŸŽฏ Why async-inspect?

Motivation

Async Rust is powerful but opaque. When you write:

async fn complex_operation() {
    let a = step_a().await;
    let b = step_b(a).await;
    let c = step_c(b).await;
}

The compiler transforms this into a state machine:

// Simplified - the real thing is more complex
enum ComplexOperationState {
    WaitingForStepA { /* ... */ },
    WaitingForStepB { a: ResultA, /* ... */ },
    WaitingForStepC { a: ResultA, b: ResultB, /* ... */ },
    Done,
}

The problem: This state machine is invisible to debuggers!

Traditional debuggers show you:

  • โŒ Stack frames (useless - points to runtime internals)
  • โŒ Variable values (many are "moved" or "uninitialized")
  • โŒ Current line (incorrect - shows scheduler code)

async-inspect understands async state machines and shows you:

  • โœ… Current state name and position
  • โœ… All captured variables and their values
  • โœ… Which .await you're blocked on
  • โœ… Why you're blocked (I/O, lock, sleep, etc.)
  • โœ… Complete execution timeline
  • โœ… Dependencies between tasks

๐Ÿ†š Comparison with Existing Tools

tokio-console

tokio-console is excellent but limited:

$ tokio-console

What tokio-console shows:

Task    Duration    Polls   State
#42     2.3s        156     Running
#43     0.1s        5       Idle
#44     5.2s        892     Running

What it DOESN'T show:

  • โŒ Which .await is blocked
  • โŒ Internal state machine state
  • โŒ What the task is waiting for
  • โŒ Variable values
  • โŒ Deadlock detection
  • โŒ Timeline visualization

Comparison Table

Featureasync-inspecttokio-consolegdb/lldbprintln!
See current .awaitโœ…โŒโŒโš ๏ธ Manual
State machine stateโœ…โŒโŒโŒ
Variable inspectionโœ…โŒโš ๏ธ LimitedโŒ
Waiting reasonโœ…โŒโŒโŒ
Timeline viewโœ…โš ๏ธ BasicโŒโŒ
Deadlock detectionโœ…โŒโŒโŒ
Dependency graphโœ…โš ๏ธ BasicโŒโŒ
Runtime agnosticโœ…โŒ Tokio onlyโœ…โœ…
Zero code changesโœ…โš ๏ธ Requires tracingโœ…โŒ

async-inspect is complementary to tokio-console:

  • tokio-console: High-level task monitoring
  • async-inspect: Deep state machine inspection

Use both together for complete visibility!

Runtime Support

async-inspect works with multiple async runtimes:

  • โœ… Tokio - Full support with tokio feature
  • โœ… async-std - Full support with async-std-runtime feature
  • โœ… smol - Full support with smol-runtime feature

Example usage with different runtimes:

// Tokio
use async_inspect::runtime::tokio::{spawn_tracked, InspectExt};

#[tokio::main]
async fn main() {
    spawn_tracked("my_task", async {
        // Your code here
    }).await;

    let result = fetch_data()
        .inspect("fetch_data")
        .await;
}

// async-std
use async_inspect::runtime::async_std::{spawn_tracked, InspectExt};

fn main() {
    async_std::task::block_on(async {
        spawn_tracked("my_task", async {
            // Your code here
        }).await;
    });
}

// smol
use async_inspect::runtime::smol::{spawn_tracked, InspectExt};

fn main() {
    smol::block_on(async {
        spawn_tracked("my_task", async {
            // Your code here
        }).await;
    });
}

See the examples/ directory for complete working examples.


โœจ Features (Planned)

Core Features

  • ๐Ÿ” State Machine Inspection - See current state and variables
  • โฑ๏ธ Execution Timeline - Visualize async execution over time
  • ๐ŸŽฏ Breakpoints - Pause at specific states or .await points
  • ๐Ÿ”— Dependency Tracking - See which tasks are waiting on others
  • ๐Ÿ’€ Deadlock Detection - Automatically find circular dependencies
  • ๐Ÿ“Š Performance Analysis - Identify slow operations and contention
  • ๐ŸŽฎ Interactive Debugging - Step through async state transitions
  • ๐Ÿ“ธ Snapshot & Replay - Record execution and replay later

Advanced Features

  • ๐ŸŒ Distributed Tracing - Track async across services
  • ๐Ÿ”ฅ Flamegraphs - Visualize where time is spent
  • ๐ŸŽ›๏ธ Live Inspection - Attach to running processes
  • ๐Ÿ“ Export & Share - Save traces for collaboration
  • ๐Ÿค– CI Integration - Detect hangs in test suites
  • ๐ŸŽจ Custom Views - Plugin system for specialized visualization

๐Ÿšง Status

Work in Progress - Early development

Current version: 0.1.0-alpha


๐Ÿš€ Quick Start (Planned API)

Installation

# Not yet published
cargo install async-inspect

# Or build from source
git clone https://github.com/yourusername/async-inspect
cd async-inspect
cargo install --path .

Basic Usage

# Run your app with inspection enabled
async-inspect run ./my-app

# Attach to running process
async-inspect attach --pid 12345

# Run tests with inspection
async-inspect test

# Start web dashboard
async-inspect serve --port 8080

In Code (Optional Instrumentation)

// Add to Cargo.toml
[dependencies]
async-inspect = "0.1"

// Instrument specific functions
#[async_inspect::trace]
async fn fetch_user(id: u64) -> User {
    // Automatically instrumented
    let profile = fetch_profile(id).await;
    let posts = fetch_posts(id).await;
    User { profile, posts }
}

// Or use manual inspection points
use async_inspect::prelude::*;

async fn complex_operation() {
    inspect_point!("starting");
    
    let data = fetch_data().await;
    
    inspect_point!("data_fetched", data.len());
    
    process(data).await
}

๐Ÿ“– Use Cases

1. Find Where Test is Stuck

#[tokio::test]
async fn test_timeout() {
    // This test hangs... but where?
    let result = timeout(
        Duration::from_secs(30),
        long_operation()
    ).await;
}

With async-inspect:

$ async-inspect test

Found test stuck at:
  test_timeout
    โ””โ”€> long_operation()
        โ””โ”€> fetch_data().await  โ—„โ”€โ”€โ”€ BLOCKED (5m 23s)
            โ””โ”€> Waiting for: HTTP response
            โ””โ”€> URL: https://slow-api.example.com/data
            โ””โ”€> Timeout: None (will wait forever!)
            
Suggestion: Add timeout to HTTP client

2. Debug Deadlock

async fn deadlock_example() {
    let mutex_a = Arc::new(Mutex::new(0));
    let mutex_b = Arc::new(Mutex::new(0));
    
    // Task 1: locks A then B
    tokio::spawn(async move {
        let _a = mutex_a.lock().await;
        tokio::time::sleep(Duration::from_millis(10)).await;
        let _b = mutex_b.lock().await; // DEADLOCK!
    });
    
    // Task 2: locks B then A
    tokio::spawn(async move {
        let _b = mutex_b.lock().await;
        tokio::time::sleep(Duration::from_millis(10)).await;
        let _a = mutex_a.lock().await; // DEADLOCK!
    });
}

With async-inspect:

๐Ÿ’€ DEADLOCK DETECTED!

Task #42: waiting for Mutex<i32> @ 0x7f8a9c0
  โ””โ”€> Held by: Task #89
  
Task #89: waiting for Mutex<i32> @ 0x7f8a9d0
  โ””โ”€> Held by: Task #42

Circular dependency:
  Task #42 โ†’ Mutex A โ†’ Task #89 โ†’ Mutex B โ†’ Task #42

Suggestion:
  โ€ข Acquire locks in consistent order (A before B)
  โ€ข Use try_lock() with timeout
  โ€ข Consider lock-free alternatives

3. Performance Investigation

$ async-inspect profile ./my-app

Performance Report:
  
Slowest Operations:
  1. fetch_posts() - avg 2.3s (called 450x)
     โ””โ”€> 98% time in: HTTP request
     โ””โ”€> Suggestion: Add caching or batch requests
  
  2. acquire_lock() - avg 340ms (called 1200x)
     โ””โ”€> Lock contention: 50 tasks waiting
     โ””โ”€> Suggestion: Reduce lock scope or use RwLock

Hot Paths:
  1. process_request โ†’ fetch_user โ†’ fetch_posts (89% of requests)
  2. handle_webhook โ†’ validate โ†’ store (11% of requests)

4. CI/CD Integration

# .github/workflows/test.yml
- name: Run tests with async inspection
  run: async-inspect test --timeout 30s --fail-on-hang
  
- name: Upload trace on failure
  if: failure()
  uses: actions/upload-artifact@v3
  with:
    name: async-trace
    path: async-inspect-trace.json

๐Ÿ› ๏ธ How It Works

Compiler Instrumentation

// Your code
async fn fetch_user(id: u64) -> User {
    let profile = fetch_profile(id).await;
    let posts = fetch_posts(id).await;
    User { profile, posts }
}

// With instrumentation (conceptual)
async fn fetch_user(id: u64) -> User {
    __async_inspect_enter("fetch_user", id);
    
    __async_inspect_await_start("fetch_profile");
    let profile = fetch_profile(id).await;
    __async_inspect_await_end("fetch_profile");
    
    __async_inspect_await_start("fetch_posts");
    let posts = fetch_posts(id).await;
    __async_inspect_await_end("fetch_posts");
    
    let result = User { profile, posts };
    __async_inspect_exit("fetch_user", &result);
    result
}

Runtime Integration

  • Tokio: Hooks into task spawning and polling
  • async-std: Custom executor wrapper
  • smol: Runtime instrumentation
  • Generic: Works with any runtime via proc macros

Zero Overhead When Disabled

# Production build - no overhead
[profile.release]
debug = false

# Debug build - full instrumentation
[profile.dev]
debug = true

๐ŸŒ Ecosystem Integration

async-inspect works seamlessly with your existing Rust async ecosystem tools:

Prometheus Metrics

Export metrics for monitoring dashboards:

use async_inspect::integrations::prometheus::PrometheusExporter;

let exporter = PrometheusExporter::new()?;
exporter.update();

// In your /metrics endpoint:
let metrics = exporter.gather();

Available metrics:

  • async_inspect_tasks_total - Total tasks created
  • async_inspect_active_tasks - Currently active tasks
  • async_inspect_blocked_tasks - Tasks waiting on I/O
  • async_inspect_task_duration_seconds - Task execution times
  • async_inspect_tasks_failed_total - Failed task count

OpenTelemetry Export

Send traces to Jaeger, Zipkin, or any OTLP backend:

use async_inspect::integrations::opentelemetry::OtelExporter;

let exporter = OtelExporter::new("my-service");
exporter.export_tasks();

Tracing Integration

Automatic capture via tracing-subscriber:

use tracing_subscriber::prelude::*;
use async_inspect::integrations::tracing_layer::AsyncInspectLayer;

tracing_subscriber::registry()
    .with(AsyncInspectLayer::new())
    .init();

Tokio Console Compatibility

Use alongside tokio-console for complementary insights:

# Terminal 1: Run with tokio-console
RUSTFLAGS="--cfg tokio_unstable" cargo run

# Terminal 2: Monitor with tokio-console
tokio-console

# async-inspect exports provide historical analysis
cargo run --example ecosystem_integration

Grafana Dashboards

Import async-inspect metrics into Grafana:

  1. Configure Prometheus scraping
  2. Import dashboard template (coming soon)
  3. Monitor key metrics:
    • Task creation rate
    • Active/blocked task ratio
    • Task duration percentiles
    • Error rates

Feature Flags:

[dependencies]
async-inspect = { version = "0.0.1", features = [
    "prometheus-export",     # Prometheus metrics
    "opentelemetry-export",  # OTLP traces
    "tracing-sub",           # Tracing integration
] }

๐Ÿ“ค Export Formats

async-inspect supports multiple industry-standard export formats for visualization and analysis:

JSON Export

Export complete task and event data as structured JSON:

use async_inspect::export::JsonExporter;

// Export to file
JsonExporter::export_to_file(&inspector, "data.json")?;

// Or get as string
let json = JsonExporter::export_to_string(&inspector)?;

Use with: jq, Python pandas, JavaScript tools, data pipelines

CSV Export

Export tasks and events in spreadsheet-compatible format:

use async_inspect::export::CsvExporter;

// Export tasks (id, name, duration, poll_count, etc.)
CsvExporter::export_tasks_to_file(&inspector, "tasks.csv")?;

// Export events (event_id, task_id, timestamp, kind, details)
CsvExporter::export_events_to_file(&inspector, "events.csv")?;

Use with: Excel, Google Sheets, pandas, data analysis

Chrome Trace Event Format

Export for visualization in chrome://tracing or Perfetto UI:

use async_inspect::export::ChromeTraceExporter;

ChromeTraceExporter::export_to_file(&inspector, "trace.json")?;

How to visualize:

  1. Chrome DevTools (built-in):

    • Open Chrome/Chromium
    • Navigate to chrome://tracing
    • Click "Load" and select trace.json
    • Explore the interactive timeline!
  2. Perfetto UI (recommended):

    • Go to https://ui.perfetto.dev/
    • Click "Open trace file"
    • Select trace.json
    • Get advanced analysis features:
      • Thread-level view
      • SQL-based queries
      • Statistical summaries
      • Custom tracks

What you see:

  • Task spawning and completion as events
  • Poll operations with precise durations
  • Await points showing blocking time
  • Complete async execution timeline
  • Task relationships and dependencies

Flamegraph Export

Generate flamegraphs for performance analysis:

use async_inspect::export::{FlamegraphExporter, FlamegraphBuilder};

// Basic export (folded stack format)
FlamegraphExporter::export_to_file(&inspector, "flamegraph.txt")?;

// Customized export
FlamegraphBuilder::new()
    .include_polls(false)      // Exclude poll events
    .include_awaits(true)       // Include await points
    .min_duration_ms(10)        // Filter < 10ms operations
    .export_to_file(&inspector, "flamegraph_filtered.txt")?;

// Generate SVG directly (requires 'flamegraph' feature)
#[cfg(feature = "flamegraph")]
FlamegraphExporter::generate_svg(&inspector, "flamegraph.svg")?;

How to visualize:

  1. Speedscope (easiest, online):

  2. inferno (local SVG generation):

    cargo install inferno
    cat flamegraph.txt | inferno-flamegraph > output.svg
    open output.svg
    
  3. flamegraph.pl (classic):

    git clone https://github.com/brendangregg/FlameGraph
    ./FlameGraph/flamegraph.pl flamegraph.txt > output.svg
    

What you see:

  • Call stacks showing task hierarchies
  • Time spent in each async operation
  • Hotspots and bottlenecks
  • Parent-child task relationships

Comprehensive Example

See examples/export_formats.rs for a complete example:

cargo run --example export_formats

This demonstrates:

  • All export formats in one workflow
  • Realistic async operations
  • Multiple concurrent tasks
  • Export to JSON, CSV, Chrome Trace, and Flamegraph
  • Usage instructions for each format

Output files:

async_inspect_exports/
โ”œโ”€โ”€ data.json                    # Complete JSON export
โ”œโ”€โ”€ tasks.csv                    # Task metrics
โ”œโ”€โ”€ events.csv                   # Event timeline
โ”œโ”€โ”€ trace.json                   # Chrome Trace Event Format
โ”œโ”€โ”€ flamegraph.txt               # Basic flamegraph
โ””โ”€โ”€ flamegraph_filtered.txt      # Filtered flamegraph

๐Ÿ—บ๏ธ Roadmap

Phase 1: Core Inspector (Current)

  • Basic state machine inspection
  • Task listing and status
  • Simple TUI interface
  • Tokio runtime integration

Phase 2: Advanced Debugging

  • Variable inspection
  • Breakpoints on states
  • Step-by-step execution
  • Timeline visualization

Phase 3: Analysis Tools

  • Deadlock detection
  • Performance profiling
  • Lock contention analysis
  • Flamegraphs

Phase 4: Production Ready

  • Web dashboard
  • Live process attachment
  • Distributed tracing
  • CI/CD integration
  • Plugin system

Phase 5: Ecosystem

  • async-std support
  • smol support
  • IDE integration (VS Code, IntelliJ)
  • Cloud deployment monitoring

๐ŸŽจ Interface Preview (Planned)

TUI (Terminal)

โ”Œโ”€ async-inspect โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ [Tasks] [Timeline] [Graph] [Profile]          [?] Help  โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                          โ”‚
โ”‚ Active Tasks: 23                 CPU: โ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘ 45%       โ”‚
โ”‚ Blocked: 8                       Mem: โ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘ 20%       โ”‚
โ”‚ Running: 15                                             โ”‚
โ”‚                                                          โ”‚
โ”‚ Task    State            Duration    Details            โ”‚
โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚
โ”‚ #42  โณ WaitingPosts    2.3s      http::get()          โ”‚
โ”‚ #43  โœ… Done            0.1s      Completed             โ”‚
โ”‚ #44  ๐Ÿ’€ Deadlock        5.2s      Mutex wait            โ”‚
โ”‚ #45  ๐Ÿƒ Running         0.03s     Computing             โ”‚
โ”‚                                                          โ”‚
โ”‚ [โ†โ†’] Navigate  [Enter] Details  [g] Graph  [q] Quit    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Web Dashboard

http://localhost:8080

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  async-inspect                      [Settings] โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                โ”‚
โ”‚  ๐Ÿ“Š Overview           ๐Ÿ•’ Last updated: 2s ago โ”‚
โ”‚                                                โ”‚
โ”‚  โ— 23 Tasks Active     โ–โ–ƒโ–…โ–‡โ–ˆโ–‡โ–…โ–ƒโ– Activity     โ”‚
โ”‚  โธ๏ธ  8 Blocked                                 โ”‚
โ”‚  ๐Ÿ’€ 1 Deadlock         [View Details โ†’]       โ”‚
โ”‚                                                โ”‚
โ”‚  ๐Ÿ“ˆ Performance                                โ”‚
โ”‚  โ”œโ”€ Avg Response: 145ms                       โ”‚
โ”‚  โ”œโ”€ 99th percentile: 2.3s                     โ”‚
โ”‚  โ””โ”€ Slowest: fetch_posts() - 5.2s            โ”‚
โ”‚                                                โ”‚
โ”‚  [View Timeline] [Export Trace] [Filter...]   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿค Contributing

Contributions welcome! This is a challenging project that needs expertise in:

  • ๐Ÿฆ€ Rust compiler internals
  • ๐Ÿ”ง Async runtime implementation
  • ๐ŸŽจ UI/UX design
  • ๐Ÿ“Š Data visualization
  • ๐Ÿ› Debugger implementation

Priority areas:

  • State machine introspection
  • Runtime hooks (Tokio, async-std)
  • TUI implementation
  • Deadlock detection algorithms
  • Documentation and examples

See CONTRIBUTING.md for details.


๐Ÿ”’ Security

async-inspect is designed to be used in development and CI/CD environments for analyzing async code. We take security seriously:

Supply Chain Security

  • SLSA Level 3 Provenance: All release binaries include SLSA provenance attestations for verifiable builds
  • Dependency Scanning: Automated dependency review on all pull requests
  • License Compliance: Only permissive licenses (MIT, Apache-2.0, BSD) - GPL/AGPL excluded
  • Security Audits: Continuous monitoring via cargo-audit and cargo-deny

Build Verification

You can verify the provenance of any release binary:

# Install GitHub CLI attestation verification
gh attestation verify async-inspect-linux-x86_64.tar.gz \
  --owner ibrahimcesar

Reporting Security Issues

If you discover a security vulnerability, please email security@ibrahimcesar.com instead of using the issue tracker.


๐Ÿ“ License

MIT OR Apache-2.0


๐Ÿ™ Acknowledgments

Inspired by:

  • tokio-console - Task monitoring for Tokio
  • async-backtrace - Async stack traces
  • tracing - Instrumentation framework
  • Chrome DevTools - JavaScript async debugging
  • Go's runtime tracer - Goroutine visualization
  • rr - Time-travel debugging

async-inspect - Because async shouldn't be a black box ๐Ÿ”

Status: ๐Ÿšง Pre-alpha - Architecture design phase

Star โญ this repo to follow development!

๐Ÿ’ฌ Discussion

Have ideas or feedback? Open an issue or discussion!

Key questions we're exploring:

  • How to minimize runtime overhead?
  • Best UI for visualizing state machines?
  • How to support multiple runtimes?
  • What features would help you most?