diff --git a/iroh-services/access.mdx b/iroh-services/access.mdx index e8c2db0..045169e 100644 --- a/iroh-services/access.mdx +++ b/iroh-services/access.mdx @@ -34,17 +34,23 @@ The environment variable used by the Rust client is `IROH_SERVICES_API_SECRET` ( ## Use it in your app -Pass the key when building your `iroh_services::Client`: +Pass the key to `iroh_services::preset()`, bind your endpoint with the preset, +then hand the same preset to the client: ```rust -use iroh_services::Client; +use iroh::Endpoint; -let client = Client::builder(&endpoint) +let preset = iroh_services::preset() .api_secret_from_str("YOUR_API_KEY")? - .build() - .await?; + .build()?; + +let endpoint = Endpoint::bind(preset.clone()).await?; + +let client = preset.client_builder(&endpoint).build().await?; ``` +The preset carries the key, so you don't pass it to the client a second time. + In production, load the key from a config file or environment variable instead of hardcoding it. diff --git a/iroh-services/metrics/custom.mdx b/iroh-services/metrics/custom.mdx index 643eb63..a655e83 100644 --- a/iroh-services/metrics/custom.mdx +++ b/iroh-services/metrics/custom.mdx @@ -35,23 +35,52 @@ successfully, we will report the metric to the Iroh Services platform. For a complete example, see the [iroh-ping example on GitHub](https://github.com/n0-computer/iroh-ping). +Custom metrics live in a struct that derives `MetricsGroup` from the +`iroh-metrics` crate, which you register on the client: + +```bash +cargo add iroh-metrics +``` + ```rust -use iroh::{Endpoint, endpoint::presets}; -use iroh_services::Client; +use std::sync::Arc; + +use iroh::Endpoint; +use iroh_metrics::{Counter, MetricsGroup}; + +/// Metrics for our docs protocol. +#[derive(Debug, Default, MetricsGroup)] +#[metrics(name = "docs")] +struct DocsMetrics { + /// Documents written successfully + documents_written: Counter, +} #[tokio::main] async fn main() -> anyhow::Result<()> { - let endpoint = Endpoint::bind(presets::N0).await?; - endpoint.online().await; - - let client = Client::builder(&endpoint) + let preset = iroh_services::preset() .api_secret_from_str("YOUR_API_KEY")? + .build()?; + + let endpoint = Endpoint::bind(preset.clone()).await?; + endpoint.online().await; + + // Register the group with the client. It ships alongside the built-in + // endpoint metrics on the client's reporting interval. + let metrics = Arc::new(DocsMetrics::default()); + let client = preset + .client_builder(&endpoint) + .register_metrics_group(metrics.clone()) .build() .await?; - - // Report a custom metric - client.metric("document_written", 1).await?; - + + // Each time a document is written, bump the counter + metrics.documents_written.inc(); + Ok(()) } ``` + +The doc comment on each field becomes its help text, and `#[metrics(name = ...)]` +names the group. Call `client.push_metrics()` if you need a dump sent +immediately rather than waiting for the next interval. diff --git a/iroh-services/net-diagnostics/quickstart.mdx b/iroh-services/net-diagnostics/quickstart.mdx index 9d9dd3f..cda33ec 100644 --- a/iroh-services/net-diagnostics/quickstart.mdx +++ b/iroh-services/net-diagnostics/quickstart.mdx @@ -73,30 +73,36 @@ cargo add iroh-services 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: +`ClientHost` so it can dial back into your endpoint. + +At startup, build a preset from the API key you exported in step 1 and bind your +endpoint with it: + +```rust +let preset = iroh_services::preset().api_secret_from_env()?.build()?; +let endpoint = Endpoint::bind(preset.clone()).await?; +``` + +Then pass that preset alongside the endpoint. Its `client_builder` hands the API +key to the client, so you don't supply it twice: ```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, + ClientHost, CLIENT_HOST_ALPN, IrohServicesPreset, 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)?; - +async fn setup_net_diagnostics( + preset: &IrohServicesPreset, + endpoint: &Endpoint, +) -> Result { // 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; + // report to, derived from the API key's address + let remote_id = preset.api_secret().addr().id; // Build the client - let client = Client::builder(endpoint) - .api_secret(secret)? - .build() - .await?; + let client = preset.client_builder(endpoint).build().await?; // Grant the GetAny capability so the platform can request diagnostics // from this endpoint on demand diff --git a/snippets/iroh-services-setup.mdx b/snippets/iroh-services-setup.mdx index bf07d0d..eaf5fd3 100644 --- a/snippets/iroh-services-setup.mdx +++ b/snippets/iroh-services-setup.mdx @@ -16,20 +16,26 @@ Then, in your code, create a client and connect your endpoint to Iroh Services. ```rust Rust -use iroh::{Endpoint, endpoint::presets}; -use iroh_services::Client; +use iroh::Endpoint; #[tokio::main] async fn main() -> anyhow::Result<()> { - // Create an iroh endpoint - let endpoint = Endpoint::bind(presets::N0).await?; + // Build a preset from your API key. In production, load the key from a + // config file or environment variable instead of hardcoding it. + let preset = iroh_services::preset() + .api_secret_from_str("YOUR_API_KEY")? + .build()?; + + // Create an iroh endpoint with the preset + let endpoint = Endpoint::bind(preset.clone()).await?; // Wait for the endpoint to be online endpoint.online().await; - // Create the Iroh Services client with your API key. - let client = Client::builder(&endpoint) - .api_secret_from_str("YOUR_API_KEY")? + // Create the Iroh Services client. `client_builder` reuses the preset's + // API key, which also carries the address of the service to dial. + let client = preset + .client_builder(&endpoint) .name("my-endpoint")? .build() .await?;