All skills
lukemurraynz avatar

/rust-patterns

@2cc2455

USE FOR: Rust implementation recipes for new Rust 2024 services, libraries, CLIs, and workspace scaffolds - Cargo setup, error types, async patterns, serde/config, gRPC/Protobuf, HTTP/axum, OpenTelemetry/tracing, testing, quality gates, API design, production readiness, and security/supply-chain checks. Pairs with `rust.instructions.md` and `rust-tests.instructions.md`. Load this skill when Copilot needs working Rust code patterns or configuration guidance.

Use this Skill: https://skilld.dev/gh/lukemurraynz/hve-agent-skills/rust-patterns

This session only. Nothing lands on disk.

recipestracing-opentelemetry.md

≈1.1k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Tracing and OpenTelemetry Patterns

Use this recipe for structured logs, distributed tracing, OTLP export, and shutdown/flush behavior.

Structured Logging Baseline

use tracing::{error, info, warn};
use tracing_subscriber::{filter::EnvFilter, layer::SubscriberExt, util::SubscriberInitExt};

pub fn init_logging() -> Result<()> {
    tracing_subscriber::registry()
        .with(EnvFilter::from_default_env())
        .with(tracing_subscriber::fmt::layer().json())
        .try_init()
        .map_err(|error| ServiceError::invalid_input(format!("logging already initialized: {error}")))?;

    Ok(())
}

info!(service.name = "service-name", "service starting");
warn!(queue_depth = 128, "queue depth is high");
error!(error.code = "PUBLISH_FAILED", ?error, "failed to publish message");

Rules:

  • Prefer structured fields over interpolated strings.
  • Use %value for display-safe values and ?value for debug-safe values.
  • Do not log secrets, tokens, connection strings, or full Authorization headers.
  • Use stable field names for operational dashboards.

OpenTelemetry Dependencies

Verify current versions before generating. Current known pattern (verified 2026-08-26):

[dependencies]
opentelemetry = "0.32"
opentelemetry_sdk = "0.32"
opentelemetry-otlp = { version = "0.32", default-features = false, features = ["trace", "grpc-tonic"] }
opentelemetry-semantic-conventions = "0.32"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt", "json"] }
tracing-opentelemetry = "0.33"

OTLP Tracing Initialization

Keep the provider so it can be shut down during graceful exit:

use opentelemetry::{global, trace::TracerProvider as _};
use opentelemetry_otlp::SpanExporter;
use opentelemetry_sdk::{propagation::TraceContextPropagator, trace::SdkTracerProvider};
use tracing_subscriber::{filter::EnvFilter, layer::SubscriberExt, util::SubscriberInitExt};

pub struct TelemetryGuard {
    tracer_provider: Option<SdkTracerProvider>,
}

impl TelemetryGuard {
    pub fn shutdown(self) -> Result<()> {
        if let Some(provider) = self.tracer_provider {
            provider
                .shutdown()
                .map_err(|error| ServiceError::invalid_input(format!("telemetry shutdown failed: {error}")))?;
        }

        Ok(())
    }
}

pub fn init_tracing(service_name: &'static str) -> Result<TelemetryGuard> {
    let env_filter = EnvFilter::from_default_env();
    let fmt_layer = tracing_subscriber::fmt::layer().json();

    global::set_text_map_propagator(TraceContextPropagator::new());

    if std::env::var("OTEL_EXPORTER_OTLP_ENDPOINT").is_ok() {
        let exporter = SpanExporter::builder()
            .with_tonic()
            .build()
            .map_err(|error| ServiceError::invalid_input(format!("OTLP exporter failed: {error}")))?;

        let tracer_provider = SdkTracerProvider::builder()
            .with_batch_exporter(exporter)
            .build();

        let tracer = tracer_provider.tracer(service_name);
        let otel_layer = tracing_opentelemetry::layer().with_tracer(tracer);

        tracing_subscriber::registry()
            .with(env_filter)
            .with(fmt_layer)
            .with(otel_layer)
            .try_init()
            .map_err(|error| ServiceError::invalid_input(format!("tracing already initialized: {error}")))?;

        global::set_tracer_provider(tracer_provider.clone());

        Ok(TelemetryGuard {
            tracer_provider: Some(tracer_provider),
        })
    } else {
        tracing_subscriber::registry()
            .with(env_filter)
            .with(fmt_layer)
            .try_init()
            .map_err(|error| ServiceError::invalid_input(format!("tracing already initialized: {error}")))?;

        Ok(TelemetryGuard {
            tracer_provider: None,
        })
    }
}

Shutdown Usage

#[tokio::main]
async fn main() -> Result<()> {
    let telemetry = init_tracing("service-name")?;
    let result = run().await;
    telemetry.shutdown()?;
    result
}

Rules:

  • Check for OTEL_EXPORTER_OTLP_ENDPOINT before enabling export.
  • Fall back to structured logs when OTLP is not configured.
  • Set W3C trace context propagation.
  • Retain and explicitly shut down the provider; do not rely on removed global shutdown APIs.
  • Verify exact builder names against crate docs before generating final code.

Source: SKILL.md on GitHub

No alerts8d3 checks · Risk SAFE
  • Gen Agent Trust Hub8d

    The skill provides a comprehensive library of Rust implementation recipes and configuration baselines, emphasizing modern standards (Rust 2024) and security best practices such as secret redaction, dependency hygiene, and structured observability.

  • Socket8d

    No alerts

  • Snyk8d

    Risk: LOW · No issues

Signed by skilld at 2cc2455. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last month.

Steadyupdated last month
Other metadata
metadata
{
  "last_verified": "2026-08-26",
  "layer": "scoped",
  "owner": "engineering"
}

README badge

README badge for lukemurraynz/hve-agent-skills/rust-patterns