From 0ae26105982a3831b34e22f711f83bdc94a2a47b Mon Sep 17 00:00:00 2001 From: Rae McKelvey <633012+okdistribute@users.noreply.github.com> Date: Wed, 24 Jun 2026 11:52:07 -0700 Subject: [PATCH] docs: move net diagnostics integration code into the tutorial The integration snippets lived on the standalone Network Diagnostics page, one click away from the "Diagnose a connectivity issue" tutorial where readers are actually working. Move the Cargo.toml, client setup, and existing-router snippets into the tutorial, and leave the usage page as a reference for reading reports and troubleshooting. --- iroh-services/net-diagnostics/quickstart.mdx | 88 ++++++++++++++++-- iroh-services/net-diagnostics/usage.mdx | 95 +------------------- 2 files changed, 83 insertions(+), 100 deletions(-) diff --git a/iroh-services/net-diagnostics/quickstart.mdx b/iroh-services/net-diagnostics/quickstart.mdx index b06b97f..9d9dd3f 100644 --- a/iroh-services/net-diagnostics/quickstart.mdx +++ b/iroh-services/net-diagnostics/quickstart.mdx @@ -60,18 +60,92 @@ The report appears on the **Net Diagnostics** page and includes: ## Integrate Net Diagnostics into your app -The example above uses a ready-made client. To get on-demand reports from your users' endpoints, wire the same integration into your own iroh app: +The example above uses a ready-made client. To get on-demand reports from your +users' endpoints, wire the same integration into your own iroh app. -1. Add `iroh-services` to your `Cargo.toml` -2. Build an `iroh_services::Client` and grant the `NetDiagnosticsCap::GetAny` capability to your project -3. Run a `ClientHost` so the platform can dial back into the endpoint when you click **Run Diagnostics** +### Add the dependency + +```bash +cargo add iroh-services +``` + +### Connect and grant the capability + +Build an `iroh_services::Client`, grant iroh services the +`NetDiagnosticsCap::GetAny` capability so it can request diagnostics, and run a +`ClientHost` so it can dial back into your endpoint. The client reads the API +key you exported in step 1: + +```rust +use anyhow::Result; +use iroh::{Endpoint, protocol::Router}; +use iroh_services::{ + ApiSecret, Client, ClientHost, CLIENT_HOST_ALPN, API_SECRET_ENV_VAR_NAME, + caps::NetDiagnosticsCap, +}; + +async fn setup_net_diagnostics(endpoint: &Endpoint) -> Result { + // Get your secret somehow, either from an environment variable or config file + let secret = ApiSecret::from_env_var(API_SECRET_ENV_VAR_NAME)?; + + // The remote_id is the id of the endpoint we'll be sending the network + // report to, derived from the secret's address + let remote_id = secret.addr().id; + + // Build the client + let client = Client::builder(endpoint) + .api_secret(secret)? + .build() + .await?; + + // Grant the GetAny capability so the platform can request diagnostics + // from this endpoint on demand + let client2 = client.clone(); + tokio::spawn(async move { + client2 + .grant_capability(remote_id, vec![NetDiagnosticsCap::GetAny]) + .await + .unwrap(); + }); + + // Set up a ClientHost so the platform can dial back into this endpoint + let host = ClientHost::new(endpoint); + let router = Router::builder(endpoint.clone()) + .accept(CLIENT_HOST_ALPN, host) + .spawn(); + + Ok(router) +} +``` + +For a complete runnable version, see the [`net_diagnostics` example](https://github.com/n0-computer/iroh-services/tree/main/examples/net_diagnostics.rs) in the `iroh-services` repository. + +### Register on your existing router + +The snippet above spawns a router that serves only `CLIENT_HOST_ALPN`. Most +applications already run a `Router` with their own protocols. Register the +handler on that same builder rather than spawning a second router: + +```rust +use iroh::protocol::Router; +use iroh_services::{ClientHost, CLIENT_HOST_ALPN}; + +let router = Router::builder(endpoint.clone()) + .accept(MY_PROTOCOL_ALPN, my_protocol) // your application's protocols + .accept(CLIENT_HOST_ALPN, ClientHost::new(&endpoint)) // add this line + .spawn(); +``` + +Calling `.spawn()` finalizes the router's set of protocols, so the +`.accept(CLIENT_HOST_ALPN, ...)` call has to come before it. Register every +ALPN your endpoint serves on the one router you spawn for that endpoint. - Complete walkthrough with Cargo config, a minimal Rust integration, and a reference for reading reports (NAT type, connectivity summary). + Reference for interpreting a report (NAT type, connectivity summary) and fixing common setup problems. ## Next steps diff --git a/iroh-services/net-diagnostics/usage.mdx b/iroh-services/net-diagnostics/usage.mdx index f5b2a7f..f7d236f 100644 --- a/iroh-services/net-diagnostics/usage.mdx +++ b/iroh-services/net-diagnostics/usage.mdx @@ -1,6 +1,6 @@ --- title: "Network Diagnostics" -description: "Integrate on-demand connectivity reports into your iroh application" +description: "Read connectivity reports and troubleshoot net diagnostics setup" --- When you click **Run Diagnostics** in the dashboard, the platform dials back into your @@ -9,98 +9,7 @@ the request, runs the diagnostics locally (probing UDP connectivity, NAT behavior, relay latency, and port mapping), and returns the report to iroh services for display. -## Integrating Net Diagnostics Into Your App - -To add net diagnostics support to your own iroh application, you need to: - -1. Connect to iroh services with an `iroh_services::Client` -2. Grant the `NetDiagnosticsCap::GetAny` capability to iroh services so it can request diagnostics from your endpoint -3. Run a `ClientHost` so iroh services can dial back into your endpoint - -[See the `net_diagnostics` example in the `iroh-services` repository for a complete working example of this integration.](https://github.com/n0-computer/iroh-services/tree/main/examples/net_diagnostics.rs) - - -### 1. Update Cargo.toml - -Add the dependency - -```bash -cargo add iroh-services -``` - -### 2. Get Your API Key - -Create one from your project's **Settings → API Keys** tab. See [API Keys](/iroh-services/access) for the full walkthrough. Then export it as an environment variable: - -```bash -export IROH_SERVICES_API_SECRET= -``` - -### 3. Connect to iroh services and Grant Capability - -Here's a minimal integration: - -```rust -use anyhow::Result; -use iroh::{Endpoint, protocol::Router}; -use iroh_services::{ - ApiSecret, Client, ClientHost, CLIENT_HOST_ALPN, API_SECRET_ENV_VAR_NAME, - caps::NetDiagnosticsCap, -}; - -async fn setup_net_diagnostics(endpoint: &Endpoint) -> Result { - // Get your secret somehow, either from an environment variable or config file - let secret = ApiSecret::from_env_var(API_SECRET_ENV_VAR_NAME)?; - - // The remote_id is the id of the endpoint we'll be sending the network - // report to, derived from the secret's address - let remote_id = secret.addr().id; - - // Build the client - let client = Client::builder(endpoint) - .api_secret(secret)? - .build() - .await?; - - // Grant the GetAny capability so the platform can request diagnostics - // from this endpoint on demand - let client2 = client.clone(); - tokio::spawn(async move { - client2 - .grant_capability(remote_id, vec![NetDiagnosticsCap::GetAny]) - .await - .unwrap(); - }); - - // Set up a ClientHost so the platform can dial back into this endpoint - let host = ClientHost::new(endpoint); - let router = Router::builder(endpoint.clone()) - .accept(CLIENT_HOST_ALPN, host) - .spawn(); - - Ok(router) -} -``` - -### 4. Register on your existing router - -The example above spawns a router that serves only `CLIENT_HOST_ALPN`. Most -applications already run a `Router` with their own protocols. Register the -handler on that same builder rather than spawning a second router: - -```rust -use iroh::protocol::Router; -use iroh_services::{ClientHost, CLIENT_HOST_ALPN}; - -let router = Router::builder(endpoint.clone()) - .accept(MY_PROTOCOL_ALPN, my_protocol) // your application's protocols - .accept(CLIENT_HOST_ALPN, ClientHost::new(&endpoint)) // add this line - .spawn(); -``` - -Calling `.spawn()` finalizes the router's set of protocols, so the -`.accept(CLIENT_HOST_ALPN, ...)` call has to come before it. Register every -ALPN your endpoint serves on the one router you spawn for that endpoint. +To wire net diagnostics into your own application, follow [Diagnose a connectivity issue](./quickstart). This page is the reference for reading the report it produces and fixing common setup problems. ## Understanding Reports