# How to Debug iroh: Tracing Configuration and Diagnostic Techniques

> Debug iroh effectively by enabling detailed tracing with RUST_LOG=iroh=debug. Learn techniques for diagnostic logging and troubleshooting connection issues.

- Repository: [number zero/iroh](https://github.com/n0-computer/iroh)
- Tags: how-to-guide
- Published: 2026-06-21

---

**Enable tracing by setting `RUST_LOG=iroh=debug` and initializing `tracing_subscriber::fmt::init()` in your application to capture detailed logs from connection establishment, relay handling, and QUIC transport events.**

The n0-computer/iroh repository provides a full-stack peer-to-peer networking library built in Rust, offering QUIC hole-punching, relay servers, and DNS resolution. Debugging iroh effectively means leveraging its comprehensive instrumentation through the `tracing` crate, which emits spans and events for every critical state change in the networking stack.

## Enable Debug Logging with RUST_LOG

The simplest method to debug iroh is using the `RUST_LOG` environment variable to control verbosity across the crate hierarchy. This approach works for both binary execution and test suites without requiring code changes.

Run any iroh example with informational logging:

```bash
RUST_LOG=info cargo run --example echo

```

Enable full trace-level output for the entire crate during tests:

```bash
RUST_LOG=trace cargo test -- --nocapture

```

Target specific modules to reduce noise while investigating particular subsystems:

```bash
RUST_LOG=iroh=debug,cargo=info cargo run --example listen
RUST_LOG=iroh::socket=trace cargo test --test integration -- --nocapture

```

## Programmatic Tracing Configuration

When embedding iroh as a library in your own application, you must initialize a tracing subscriber manually. The [`iroh/examples/echo.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/examples/echo.rs) file demonstrates this pattern, calling `tracing_subscriber::fmt::init()` at startup.

Initialize tracing with environment-based filtering:

```rust
use tracing_subscriber::{fmt, EnvFilter};

fn main() -> anyhow::Result<()> {
    fmt::Subscriber::builder()
        .with_env_filter(EnvFilter::from_default_env())
        .init();
    
    // Your iroh endpoint setup continues here...
    Ok(())
}

```

The `EnvFilter::from_default_env()` constructor automatically respects `RUST_LOG` settings, allowing you to adjust verbosity at runtime without recompiling.

## Debugging Connection Failures

Connection issues typically surface in [`iroh/src/endpoint/connection.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint/connection.rs), where the library emits warnings via `tracing::warn` when handshakes fail or connections terminate unexpectedly. The QUIC transport layer in [`iroh/src/endpoint/quic.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint/quic.rs) similarly logs transport-level errors.

Enable detailed connection tracing:

```bash
RUST_LOG=iroh::endpoint=trace cargo run --example connect

```

Look for specific error patterns in the output:
- `tracing::warn!("Failure while handling connection")` indicates protocol-level handshake failures
- Span events recording endpoint IDs and ALPN protocol identifiers help identify which connection attempts succeeded

## Inspecting Relay and Hole-Punching Logic

Relay connectivity and NAT traversal debugging require examining [`iroh/src/socket/transports/relay/actor.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/socket/transports/relay/actor.rs), which contains detailed spans for hole-punching attempts. The relay server implementation in [`iroh-relay/src/server/http_server.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/server/http_server.rs) emits HTTP handling spans for incoming relay requests.

Debug relay-specific issues with tiered logging:

```bash
RUST_LOG=iroh=debug,iroh-relay=trace cargo run --example remote-info

```

Key log indicators to watch for:
- `tracing::info!("home relay found")` in [`iroh/src/protocol.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/protocol.rs) confirms successful relay discovery
- `tracing::debug!` messages in the relay actor track candidate gathering and NAT traversal progress
- Warnings from `iroh::relay::client` indicate timeout or authentication failures

## Using Integration Tests for Diagnostics

The integration test suite in [`iroh/tests/integration.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/tests/integration.rs) exercises the complete stack including relay and DNS components, making it invaluable for observing real-world behavior. These tests use `tracing::info!` macros to log connection IDs and major state transitions.

Run integration tests with full diagnostics:

```bash
RUST_LOG=iroh=trace cargo test -p iroh --test integration -- --nocapture

```

Many tests utilize the `#[n0_tracing_test::traced_test]` annotation defined in [`iroh/src/test_utils.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/test_utils.rs), which automatically establishes a temporary subscriber capturing all events. This allows tests to assert against log output while maintaining isolation between test cases.

## Key Source Files for Debugging

Understanding these specific source locations helps you interpret trace output and set appropriate log filters:

- **[`iroh/src/endpoint/connection.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint/connection.rs)** – Core connection lifecycle with `tracing::warn` and `event!` calls for failure reporting
- **[`iroh/src/endpoint/quic.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint/quic.rs)** – QUIC transport warnings and state transitions
- **[`iroh/src/protocol.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/protocol.rs)** – Protocol negotiation and ALPN recording (lines 640–650) via `Span::current().record()`
- **[`iroh/src/socket/transports/relay/actor.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/socket/transports/relay/actor.rs)** – Relay-specific NAT traversal logic and candidate gathering
- **[`iroh-relay/src/server/http_server.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/server/http_server.rs)** – HTTP server-side relay request handling
- **[`iroh-dns-server/src/main.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-dns-server/src/main.rs)** – DNS resolution logging via `tracing_subscriber::fmt::init()`
- **[`iroh/examples/echo.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/examples/echo.rs)** – Reference implementation showing subscriber initialization
- **[`iroh/tests/integration.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/tests/integration.rs)** – Full-stack test examples with comprehensive instrumentation

## Summary

- **Set `RUST_LOG=iroh=debug`** to enable command-line debugging without code changes
- **Initialize `tracing_subscriber::fmt::init()`** in embedded applications to capture library events
- **Filter by module** using `RUST_LOG=iroh::endpoint=trace` to isolate specific subsystems
- **Use `--nocapture`** with `cargo test` to ensure trace output appears in terminal
- **Reference [`iroh/tests/integration.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/tests/integration.rs)** for examples of comprehensive diagnostic logging
- **Leverage `n0_tracing_test::traced_test`** in your own tests to capture and assert against log output

## Frequently Asked Questions

### How do I enable debug logging in iroh?

Set the `RUST_LOG` environment variable to `iroh=debug` or `iroh=trace` before running your binary. For embedded use, call `tracing_subscriber::fmt::init()` at application startup, which respects the `RUST_LOG` environment variable automatically.

### Why is my iroh connection failing?

Check [`iroh/src/endpoint/connection.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint/connection.rs) for `tracing::warn` messages indicating handshake failures. Run with `RUST_LOG=iroh::endpoint=trace` to see detailed connection state transitions and identify whether the failure occurs during QUIC transport establishment or application-level protocol negotiation.

### How do I debug relay connectivity issues?

Enable `RUST_LOG=iroh-relay=trace` to see detailed HTTP handling in the relay server. Look for `tracing::info!("home relay found")` in [`iroh/src/protocol.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/protocol.rs) to confirm successful relay discovery, and check [`iroh/src/socket/transports/relay/actor.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/socket/transports/relay/actor.rs) for debug messages regarding NAT traversal and candidate gathering.

### What is the `n0_tracing_test` macro used for?

The `#[n0_tracing_test::traced_test]` annotation, defined in [`iroh/src/test_utils.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/test_utils.rs), automatically creates a temporary tracing subscriber for each test. This captures all spans and events during test execution, enabling assertions against log output while preventing interference between concurrent tests.