Spitfirev1.0.0 · Yenilikler

Sürüm: 1.0.0Bu dokümantasyon Spitfire 1.0.0 içindir.

Rust servisini OTel ile bağlamak

Rust derlenen bir dil ve ajanı yok: servise bir dosya ve birkaç satır ekleyip yeniden derlersiniz. Servisin tracing span ve event'leri bundan sonra Spitfire'a trace ve log olarak, HTTP istekleri metrik olarak gider; adresler ve token'lar diğer rehberlerdeki gibi ortamdan gelir. Değerler ve genel kurallar: Servisleri OTel ile bağlamak: genel.

Sürüm tablosu

Rust Crate'ler Not
1.88 ve sonrası opentelemetry, opentelemetry_sdk, opentelemetry-otlp, opentelemetry-http, opentelemetry-appender-tracing 0.33.1; tracing-opentelemetry 0.34.0; tracing 0.1.44, tracing-subscriber 0.3.23 OTel crate'leri 1.75 der, ama çektikleri crate'lerin güncel sürümleri Rust 1.88 ister (Rust 2024 edition, ICU crate'leri)
1.87 ve öncesi desteklenmiyor Toolchain'i yükseltin (rustup update)

Sürümünüzü bulun: derleme makinesinde rustc --version (ya da Cargo.toml'daki rust-version).

Aşağıdaki örnekler axum 0.8 içindir; başka bir framework'te 1. adımdaki middleware aynı şekilde yazılır (istek başlıklarından traceparent'ı alın, span'i o parent ile açın).

Doğrulandı: 2026-11-03. Kaynak: Rust başlangıç belgesi, opentelemetry-otlp (özellikler, ortam değişkenleri), tracing-opentelemetry, crate sürümleri.

Gerekenler

  • Spitfire adresi https://<spitfire> ve OTLP alıcısı anahtarı sfotlp_…
  • Tower adresi http://<tower>:4318 ve Collector token'ı sfcol_…
  • Protokol http/protobuf
  • Servis adı <service-name>, sürümü <service-version>, ortamı <environment>
  • Özel CA varsa CA sertifikası makinenin (ya da image'ın) sistem güven deposunda
  • Proxy varsa Tower ve Spitfire NO_PROXY içinde
  • Örnekleme parentbased_traceidratio, 0.1
  • Servisin kaynak kodu ve derlendiği makine

Linux (systemd)

  1. src/otel.rs dosyasını oluşturun, şunu yapıştırın:
rust
use std::sync::OnceLock;

use axum::{extract::Request, middleware::Next, response::Response};
use opentelemetry::{global, metrics::{Counter, Histogram}, trace::TracerProvider as _, KeyValue};
use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge;
use opentelemetry_http::HeaderExtractor;
use opentelemetry_otlp::{LogExporter, MetricExporter, SpanExporter};
use opentelemetry_sdk::{logs::SdkLoggerProvider, metrics::SdkMeterProvider, propagation::TraceContextPropagator, trace::SdkTracerProvider, Resource};
use tracing::{level_filters::LevelFilter, Instrument};
use tracing_opentelemetry::OpenTelemetrySpanExt;
use tracing_subscriber::{filter::Targets, layer::SubscriberExt, util::SubscriberInitExt};

/// Sends what is left when dropped: keep it until main returns.
pub struct Otel {
    tp: SdkTracerProvider,
    mp: SdkMeterProvider,
    lp: SdkLoggerProvider,
}

impl Drop for Otel {
    fn drop(&mut self) {
        let _ = self.tp.shutdown();
        let _ = self.mp.shutdown();
        let _ = self.lp.shutdown();
    }
}

/// IS_OTEL_ENABLED=true turns OTel on; any other value leaves it off.
/// Addresses, tokens, sampling and the service name come from the OTEL_*
/// environment values.
pub fn setup() -> Option<Otel> {
    // The exporters' own crates stay out, or every export would log again.
    let filter = Targets::new()
        .with_default(LevelFilter::INFO)
        .with_target("hyper", LevelFilter::OFF)
        .with_target("h2", LevelFilter::OFF)
        .with_target("reqwest", LevelFilter::OFF)
        .with_target("opentelemetry", LevelFilter::OFF);
    if std::env::var("IS_OTEL_ENABLED").as_deref() != Ok("true") {
        tracing_subscriber::registry().with(filter).with(tracing_subscriber::fmt::layer()).init();
        return None;
    }
    let resource = Resource::builder().build();
    let tp = SdkTracerProvider::builder()
        .with_batch_exporter(SpanExporter::builder().with_http().build().expect("OTLP span exporter"))
        .with_resource(resource.clone())
        .build();
    let mp = SdkMeterProvider::builder()
        .with_periodic_exporter(MetricExporter::builder().with_http().build().expect("OTLP metric exporter"))
        .with_resource(resource.clone())
        .build();
    let lp = SdkLoggerProvider::builder()
        .with_batch_exporter(LogExporter::builder().with_http().build().expect("OTLP log exporter"))
        .with_resource(resource)
        .build();
    global::set_text_map_propagator(TraceContextPropagator::new());
    global::set_tracer_provider(tp.clone());
    global::set_meter_provider(mp.clone());
    tracing_subscriber::registry()
        .with(filter)
        .with(tracing_subscriber::fmt::layer())
        .with(tracing_opentelemetry::layer().with_tracer(tp.tracer("otel")))
        .with(OpenTelemetryTracingBridge::new(&lp))
        .init();
    Some(Otel { tp, mp, lp })
}

/// axum middleware: a server span per request, continuing an incoming
/// traceparent (Spitfire's test), and the request count and duration as metrics.
pub async fn trace_http(req: Request, next: Next) -> Response {
    static DURATION: OnceLock<Histogram<f64>> = OnceLock::new();
    static REQUESTS: OnceLock<Counter<u64>> = OnceLock::new();
    let duration = DURATION.get_or_init(|| {
        global::meter("otel").f64_histogram("http.server.request.duration").with_unit("s").build()
    });
    let requests = REQUESTS.get_or_init(|| {
        global::meter("otel").u64_counter("http.server.requests").with_unit("{request}").build()
    });
    let parent = global::get_text_map_propagator(|p| p.extract(&HeaderExtractor(req.headers())));
    let method = req.method().to_string();
    let path = req.uri().path().to_string();
    let span = tracing::info_span!("request", otel.name = %format!("{method} {path}"), otel.kind = "server",
        http.request.method = %method, url.path = %path, http.response.status_code = tracing::field::Empty);
    let _ = span.set_parent(parent);
    let start = std::time::Instant::now();
    let res = next.run(req).instrument(span.clone()).await;
    let status = res.status().as_u16();
    span.record("http.response.status_code", status);
    let attrs = [
        KeyValue::new("http.request.method", method),
        KeyValue::new("http.response.status_code", i64::from(status)),
    ];
    duration.record(start.elapsed().as_secs_f64(), &attrs);
    requests.add(1, &attrs);
    res
}
  1. src/main.rs'te modülü ekleyin, önce setup'ı çağırın ve middleware'i router'a koyun:
rust
mod otel;

// at the start of main; keep it until main returns:
let _otel = otel::setup();

// on the router (axum::middleware):
let app = Router::new()
    .route("/", get(handler))
    .layer(axum::middleware::from_fn(otel::trace_http));

Servis tracing_subscriber'ı zaten kuruyorsa o satırı silin: setup bunu yapar.

  1. Cargo.toml'da [dependencies] altına bu satırları ekleyin ve servisi yeniden derleyin (cargo build --release):
toml
opentelemetry = "=0.33.1"
opentelemetry_sdk = "=0.33.1"
opentelemetry-otlp = { version = "=0.33.1", features = ["reqwest-rustls"] }
opentelemetry-http = "=0.33.1"
opentelemetry-appender-tracing = "=0.33.1"
tracing-opentelemetry = "=0.34.0"
tracing = "=0.1.44"
tracing-subscriber = "=0.3.23"

https:// adresleri için reqwest-rustls gerekir; sistemin güven deposunu kullanır.

  1. Klasörü, ardından /etc/spitfire-otel/<service-name>.env dosyasını oluşturun, şunu yapıştırın:
bash
sudo mkdir -p /etc/spitfire-otel
bash
IS_OTEL_ENABLED=true
OTEL_SERVICE_NAME=<service-name>
OTEL_RESOURCE_ATTRIBUTES=service.version=<service-version>,deployment.environment=<environment>
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://<spitfire>/otlp/v1/traces
OTEL_EXPORTER_OTLP_TRACES_HEADERS=authorization=sfotlp_…
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://<spitfire>/otlp/v1/logs
OTEL_EXPORTER_OTLP_LOGS_HEADERS=authorization=sfotlp_…
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://<tower>:4318/v1/metrics
OTEL_EXPORTER_OTLP_METRICS_HEADERS=authorization=sfcol_…
OTEL_TRACES_SAMPLER=parentbased_traceidratio
OTEL_TRACES_SAMPLER_ARG=0.1
NO_PROXY=<tower>,<spitfire>
  1. İzni kısın: sudo chmod 600 /etc/spitfire-otel/<service-name>.env
  2. sudo systemctl edit <unit> açın, şunu yapıştırın:
ini
[Service]
EnvironmentFile=/etc/spitfire-otel/<service-name>.env
  1. Yeni binary'yi yerine koyup yeniden başlatın: sudo systemctl daemon-reload && sudo systemctl restart <unit>
  2. Başladığını görün: journalctl -u <unit> -n 50 çıktısında OTLP span exporter olmamalı (exporter kurulamazsa servis bu mesajla durur).
Not

Özel CA varsa CA'yı sistem güven deposuna ekleyin (sudo cp ca.pem /usr/local/share/ca-certificates/spitfire-ca.crt && sudo update-ca-certificates); Rust exporter'ı OTEL_EXPORTER_OTLP_CERTIFICATE değerini okumaz.

Docker

  1. Kod değişikliklerini yapın (Linux 1–3. adım); Dockerfile'a yeni satır gerekmez, crate'ler binary'nin içine derlenir.
  2. Son image'da https://<spitfire> için CA sertifikaları olmalı (Debian/Ubuntu'da: RUN apt-get update && apt-get install -y ca-certificates); özel CA varsa onu da kopyalayıp update-ca-certificates çalıştırın.
  3. Ortam dosyasını (Linux 4. adım) Docker makinesinde /etc/spitfire-otel/<service-name>.env olarak kaydedin.
  4. Çalıştırın: docker run --env-file /etc/spitfire-otel/<service-name>.env … ya da compose'da servisin altına env_file: /etc/spitfire-otel/<service-name>.env.
  5. Ortam dosyası değişince konteyneri yeniden oluşturun (restart yetmez): docker compose up -d --force-recreate <service>

Kubernetes

  1. Image'ı Docker bölümündeki gibi hazırlayın.
  2. Ortam dosyasını (Linux 4. adım) <service-name>.env olarak kaydedip Secret yapın:
bash
kubectl create secret generic <service-name>-otel --from-env-file=<service-name>.env \
  --dry-run=client -o yaml | kubectl apply -f -
  1. Deployment'ta container'ın altına ekleyin:
yaml
envFrom:
  - secretRef:
      name: <service-name>-otel
  1. Yeniden başlatın: kubectl rollout restart deployment/<deployment>

Windows (servis)

  1. Kod değişikliklerini yapın (Linux 1–3. adım) ve .exe'yi yeniden derleyin.
  2. Yönetici PowerShell'de <windows-service> yerine servisin adını (Get-Service listesindeki Name) yazıp çalıştırın:
powershell
$Service = "<windows-service>"
$IS_OTEL_ENABLED = "true"
$Otel = @(
  "IS_OTEL_ENABLED=$IS_OTEL_ENABLED",
  "OTEL_SERVICE_NAME=<service-name>",
  "OTEL_RESOURCE_ATTRIBUTES=service.version=<service-version>,deployment.environment=<environment>",
  "OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf",
  "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://<spitfire>/otlp/v1/traces",
  "OTEL_EXPORTER_OTLP_TRACES_HEADERS=authorization=sfotlp_…",
  "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://<spitfire>/otlp/v1/logs",
  "OTEL_EXPORTER_OTLP_LOGS_HEADERS=authorization=sfotlp_…",
  "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://<tower>:4318/v1/metrics",
  "OTEL_EXPORTER_OTLP_METRICS_HEADERS=authorization=sfcol_…",
  "OTEL_TRACES_SAMPLER=parentbased_traceidratio",
  "OTEL_TRACES_SAMPLER_ARG=0.1",
  "NO_PROXY=<tower>,<spitfire>"
)
$Key = "HKLM:\SYSTEM\CurrentControlSet\Services\$Service"
$Keep = @((Get-ItemProperty $Key).Environment | Where-Object { $_ -and $_ -notmatch '^(IS_OTEL_ENABLED|OTEL_|NO_PROXY)=' })
Set-ItemProperty $Key -Name Environment -Type MultiString -Value ($Keep + $Otel)
Restart-Service -Name $Service -Force

Kapatma ve kaldırma

  1. Kapatmak: ortam dosyasında (Windows'ta betikte) IS_OTEL_ENABLED=false yapın ve servisi yeniden başlatın (Linux 7. adım, Docker 5. adım, Kubernetes 4. adım ya da Windows betiğini yeniden çalıştırın). Kod kalır; setup o zaman log'ları yalnız stdout'a yazar.
  2. Kaldırmak: src/otel.rs dosyasını, mod otel;, setup ve layer satırlarını ve Cargo.toml'a eklenen crate'leri silip yeniden derleyin; sudo systemctl revert <unit> ve sudo rm -r /etc/spitfire-otel; Windows'ta servisin Environment değerinden OTel satırlarını silin.

Sık karşılaşılan sorunlar

Belirti Neden Çözüm
feature edition2024 is required ya da requires rustc 1.88 Toolchain çok eski rustup update (sürüm tablosuna bakın)
opentelemetry tipleri arasında the trait bound … is not satisfied Derlemede opentelemetry crate'lerinin iki sürümü var Bütün crate'leri yukarıdaki sürümlerle (=) yazın; cargo tree -d çiftleri gösterir
invalid peer certificate: UnknownIssuer Özel CA güven deposunda değil Linux notundaki gibi ekleyin
a global default trace dispatcher has already been set Servis tracing_subscriber'ı kendisi de kuruyor O satırı silin (Linux 2. adım)
Trace ya da metrik gelmiyor Adres, token ya da ağ Doğrulama adımlarını uygulayın

İlgili sayfalar