# How to Collect Metrics from an iroh Endpoint: Complete Socket Monitoring Guide

> Collect metrics from an iroh endpoint by calling the metrics method on a live Endpoint instance. Monitor bytes sent received, connection events, and transport activity.

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

---

**To collect metrics from an iroh Endpoint, call the `metrics()` method on a live `Endpoint` instance, which returns a snapshot of counters tracking bytes sent/received, connection events, and transport activity.**

The iroh crate embeds a built-in metrics system that records detailed counters for all socket-level activity. Every `iroh::Endpoint` implements the **MetricsGroup** trait from the `iroh_metrics` crate, exposing network telemetry through a zero-overhead API. This guide demonstrates how to access these metrics directly from your application code according to the n0-computer/iroh source.

## What Metrics Are Available

The iroh Endpoint tracks comprehensive socket-level statistics defined in [`iroh/src/socket/metrics.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/socket/metrics.rs). These counters record:

- **Transport bytes**: `send_ipv4`, `send_ipv6`, and `send_relay` for outgoing data; `recv_data_ipv4`, `recv_data_ipv6`, `recv_data_relay`, and `recv_data_custom` for incoming data
- **Connection lifecycle**: `num_conns_opened` and `num_conns_closed` tracking handshaked connections
- **Path discovery**: `paths_direct`, `paths_relay`, and `paths_custom` showing transport path utilization
- **Hole-punching**: `holepunch_attempts` counting NAT traversal events
- **Actor loop**: `actor_tick_main` and `actor_tick_msg` for internal async runtime monitoring

## Accessing Metrics via the Endpoint API

The `Endpoint` type provides the `metrics()` method as the primary interface for collecting metrics. This method returns a **clone** of the current **Metrics** struct, ensuring thread-safe access to counter snapshots without blocking the underlying socket operations.

The Endpoint automatically registers its metrics group with the global collector during initialization via the `#[metrics(name = "socket", default)]` attribute defined in [`iroh/src/socket/metrics.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/socket/metrics.rs).

## Implementation Details

Internally, iroh uses the `iroh_metrics` crate to manage metric collection. The `Metrics` struct in [`iroh/src/socket/metrics.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/socket/metrics.rs) implements the **MetricsGroup** trait, which enables automatic registration with the global collector. You can also manually register groups via `iroh_metrics::register_group` if building custom collectors.

## Code Examples

### Basic Metrics Collection

Fetch metrics periodically from a running Endpoint:

```rust
use iroh::Endpoint;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let endpoint = Endpoint::builder()
        .bind_udp(0)
        .await?;

    loop {
        let snap = endpoint.metrics();
        
        println!("IPv4 bytes sent: {}", snap.send_ipv4.get());
        println!("IPv6 bytes sent: {}", snap.send_ipv6.get());
        println!("Relay bytes sent: {}", snap.send_relay.get());
        println!("Hole-punch attempts: {}", snap.holepunch_attempts.get());
        println!("Connections opened: {}", snap.num_conns_opened.get());
        
        tokio::time::sleep(std::time::Duration::from_secs(30)).await;
    }
}

```

### Exporting to JSON

The `Metrics` struct derives `Serialize`, enabling structured export to monitoring systems:

```rust
use serde_json::to_string_pretty;

let json = to_string_pretty(&endpoint.metrics())?;
println!("{}", json);

```

## Summary

- Call `endpoint.metrics()` on any live `Endpoint` to collect metrics from an iroh Endpoint
- Counters are defined in [`iroh/src/socket/metrics.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/socket/metrics.rs) and track bytes sent/received, connections, and transport paths
- The `MetricsGroup` trait from `iroh_metrics` enables automatic registration with the global collector
- Metrics snapshots are clones of internal state, ensuring non-blocking access
- Export to JSON or integrate with Prometheus using the `Serialize` implementation

## Frequently Asked Questions

### What counters does the iroh Endpoint track?

The Endpoint tracks transport-specific byte counters (`send_ipv4`, `send_ipv6`, `send_relay`, `recv_data_ipv4`, `recv_data_ipv6`, `recv_data_relay`), connection lifecycle events (`num_conns_opened`, `num_conns_closed`), path statistics (`paths_direct`, `paths_relay`, `paths_custom`), and hole-punching attempts (`holepunch_attempts`). These are defined in [`iroh/src/socket/metrics.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/socket/metrics.rs).

### How do I register custom metrics collectors?

Use `iroh_metrics::register_group` to manually register a `MetricsGroup` implementation with the global collector. While the `Endpoint` auto-registers its socket metrics via the `#[metrics]` attribute, custom components require explicit registration to participate in the same collection pipeline.

### Can I export metrics to Prometheus?

Yes. Because the `Metrics` struct implements `Serialize`, you can serialize snapshots to JSON and feed them into Prometheus via a bridge, or implement the `iroh_metrics` traits to write a custom Prometheus exporter that polls `endpoint.metrics()` periodically.

### Where are the metrics defined in the source code?

The socket-level metrics are defined in [`iroh/src/socket/metrics.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/socket/metrics.rs) within the `iroh` crate. The `Endpoint` type that exposes the `metrics()` method is defined in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs), and the public API is re-exported through [`iroh/src/lib.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/lib.rs).