How to Debug iroh: Tracing Configuration and Diagnostic Techniques

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:

RUST_LOG=info cargo run --example echo

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

RUST_LOG=trace cargo test -- --nocapture

Target specific modules to reduce noise while investigating particular subsystems:

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 file demonstrates this pattern, calling tracing_subscriber::fmt::init() at startup.

Initialize tracing with environment-based filtering:

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, 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 similarly logs transport-level errors.

Enable detailed connection tracing:

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, which contains detailed spans for hole-punching attempts. The relay server implementation in iroh-relay/src/server/http_server.rs emits HTTP handling spans for incoming relay requests.

Debug relay-specific issues with tiered logging:

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 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 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:

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, 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:

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 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 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 to confirm successful relay discovery, and check 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, 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →