detrix-rs 1.1.1

Detrix client library for debug-on-demand observability in Rust applications
Documentation

Detrix Rust Client

Debug-on-demand observability library for Rust applications. Enables AI-powered debugging of running Rust processes without code modifications or restarts.

Features

  • Zero overhead when sleeping: No debugger loaded until explicitly woken
  • No code changes required: Add metrics to any line of code at runtime
  • Production-safe: Non-breaking observation points (logpoints) that don't pause execution
  • Clean lifecycle: Unlike Python's debugpy, LLDB can be fully stopped on sleep

Installation

Add to your Cargo.toml:

[dependencies]
detrix-rs = "1.0.0"

Quick Start

use detrix_rs::{self as detrix, Config};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize client (starts control plane, stays SLEEPING)
    detrix::init(Config {
        name: Some("my-service".to_string()),
        ..Config::default()
    })?;

    // Your application code runs normally with zero overhead...

    // When debugging is needed (could be months later):
    // POST http://127.0.0.1:{control_port}/detrix/wake
    // → Client spawns lldb-dap and attaches to self
    // → Registers connection with Detrix daemon
    // → AI can now add metrics and observe values

    // Cleanup on shutdown
    detrix::shutdown()?;
    Ok(())
}

Try It

Run the end-to-end example that simulates an AI agent: builds a sample app, wakes it, adds metrics, and captures events.

# 1. Start the Detrix server
detrix serve --daemon

# 2. Run the agent simulation (from clients/rust/)
cargo run --example test_wake -- --daemon-port 8090

Other examples in examples/:

Example Description Run
basic_usage Init / wake / sleep cycle cargo run --example basic_usage
trade_bot Long-running app with embedded client cargo run --example trade_bot
test_wake Agent simulation (builds app, wakes, observes) cargo run --example test_wake

Architecture

┌─────────────────────────────────────────────────────────────────────┐
│  Rust Application Process                                           │
│  ┌─────────────────────────────────────────────────────────────────┐│
│  │ Application Code                                                 ││
│  │   use detrix_rs as detrix;                                       ││
│  │   detrix::init(Config::default())?;                             ││
│  └─────────────────────────────────────────────────────────────────┘│
│  ┌─────────────────────────────────────────────────────────────────┐│
│  │ Control Plane HTTP Server (background thread)                   ││
│  │   - Exposes /detrix/* endpoints                                 ││
│  │   - Manages lldb-dap process lifecycle                          ││
│  └─────────────────────────────────────────────────────────────────┘│
│  ┌─────────────────────────────────────────────────────────────────┐│
│  │ LLDB Manager                                                     ││
│  │   - Spawns: lldb-dap --connection listen://host:port            ││
│  │   - Sends DAP attach request with PID                           ││
│  │   - Monitors process health                                      ││
│  └─────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────┘
        │
        │ ptrace attach (OS-level)
        ↓
┌─────────────────────────────────────────────────────────────────────┐
│  lldb-dap Process (SEPARATE process)                                │
│  ┌─────────────────────────────────────────────────────────────────┐│
│  │ DAP Server                                                       ││
│  │   - Listens on debug_port                                       ││
│  │   - Accepts connections from Detrix daemon                      ││
│  │   - Sets logpoints for metrics                                  ││
│  └─────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────┘

API

Initialization

use detrix_rs::{self as detrix, Config};
use std::time::Duration;

// With defaults
detrix::init(Config::default())?;

// With custom configuration
detrix::init(Config {
    name: Some("my-service".to_string()),
    control_host: "127.0.0.1".to_string(),
    control_port: 0,  // 0 = auto-assign
    debug_port: 0,    // 0 = auto-assign
    daemon_url: "http://127.0.0.1:8090".to_string(),
    lldb_dap_path: None,  // searches PATH
    detrix_home: None,
    safe_mode: false,
    health_check_timeout: Duration::from_secs(2),
    register_timeout: Duration::from_secs(5),
    unregister_timeout: Duration::from_secs(2),
    lldb_start_timeout: Duration::from_secs(10),
})?;

Status

let status = detrix::status();
println!("State: {}", status.state);
println!("Control port: {}", status.control_port);
if let Some(ref conn_id) = status.connection_id {
    println!("Connection ID: {}", conn_id);
}

Wake/Sleep (programmatic)

// Wake: start debugger and register with daemon
let response = detrix::wake()?;
println!("Debug port: {}", response.debug_port);

// Or wake with daemon URL override
let response = detrix::wake_with_url("http://192.168.1.100:8090")?;

// Sleep: stop debugger and unregister
let response = detrix::sleep()?;

Shutdown

// Cleanup on application exit
detrix::shutdown()?;

Control Plane Endpoints

Endpoint Method Auth Description
/detrix/health GET No Health check (always 200 OK)
/detrix/status GET Yes* Current state, ports, connection info
/detrix/info GET Yes* App metadata (name, PID, Rust version)
/detrix/wake POST Yes* Start debugger, register with daemon
/detrix/sleep POST Yes* Stop debugger, unregister

*Localhost bypass: 127.0.0.1 and ::1 always authorized

Environment Variables

Variable Description Default
DETRIX_NAME Connection name detrix-client-{pid}
DETRIX_DAEMON_URL Daemon URL http://127.0.0.1:8090
DETRIX_CONTROL_HOST Control plane bind host 127.0.0.1
DETRIX_CONTROL_PORT Control plane port 0 (auto)
DETRIX_DEBUG_PORT Debug adapter port 0 (auto)
DETRIX_TOKEN Auth token for remote access -
DETRIX_LLDB_DAP_PATH Path to lldb-dap binary searches PATH
DETRIX_HOME Detrix home directory ~/detrix
DETRIX_HEALTH_CHECK_TIMEOUT Health check timeout (seconds) 2.0
DETRIX_REGISTER_TIMEOUT Registration timeout (seconds) 5.0
DETRIX_UNREGISTER_TIMEOUT Unregistration timeout (seconds) 2.0

Build Information

The client automatically detects build metadata from:

  1. Explicit parameters (via Config::builder().build_commit()/.build_tag())
  2. Environment variables at runtime:
    • DETRIX_BUILD_COMMIT / DETRIX_BUILD_TAG
    • GIT_COMMIT, CI_COMMIT_SHA, GITHUB_SHA
    • GIT_TAG, CI_COMMIT_TAG, GITHUB_REF_NAME
  3. Compile-time injection (via environment variables during cargo build):
    GIT_COMMIT=$(git rev-parse HEAD) cargo build --release
    
  4. Runtime git detection (local dev only)

Docker Example

FROM rust:1.75 AS builder
ARG GIT_COMMIT=unknown
ARG GIT_TAG=unknown

# Set at build time - captured by build.rs
ENV GIT_COMMIT=${GIT_COMMIT}
ENV GIT_TAG=${GIT_TAG}

RUN cargo build --release

Build with:

docker build --build-arg GIT_COMMIT=$(git rev-parse HEAD) \
             --build-arg GIT_TAG=$(git describe --tags) .

Requirements

lldb-dap

The client requires lldb-dap (formerly lldb-vscode) to be installed:

macOS:

# Via Homebrew LLVM
brew install llvm
# Binary at: /opt/homebrew/opt/llvm/bin/lldb-dap

# Or via Xcode Command Line Tools
xcode-select --install
# Binary at: xcrun -f lldb-dap

Linux:

# Ubuntu/Debian
sudo apt install lldb

# Binary at: /usr/bin/lldb-dap

Debug Symbols

For useful debugging, compile with debug symbols:

# Cargo.toml
[profile.release]
debug = true

Platform Notes

macOS

  • May need to grant "Developer Tools" access in System Preferences
  • lldb-dap paths: /opt/homebrew/opt/llvm/bin/lldb-dap or via xcrun -f lldb-dap

Linux

  • ptrace_scope=1 works (lldb-dap spawned as child process)
  • Check: cat /proc/sys/kernel/yama/ptrace_scope

License

MIT