From 8c2fb0c066af7f68fdcfcdec96fa030af059bf63 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Thu, 17 Feb 2022 23:28:23 +0100 Subject: Add tracing integration with opentelemetry --- src/api/Cargo.toml | 7 ++++++- src/api/api_server.rs | 24 +++++++++++++++++++++++- src/api/lib.rs | 2 +- src/api/s3_router.rs | 4 +++- 4 files changed, 33 insertions(+), 4 deletions(-) (limited to 'src/api') diff --git a/src/api/Cargo.toml b/src/api/Cargo.toml index cc9635bb..968e8aab 100644 --- a/src/api/Cargo.toml +++ b/src/api/Cargo.toml @@ -26,11 +26,14 @@ err-derive = "0.3" hex = "0.4" hmac = "0.10" idna = "0.2" -log = "0.4" +tracing = "0.1.30" md-5 = "0.9" nom = "7.1" sha2 = "0.9" +strum = "0.23" +strum_macros = "0.23" + futures = "0.3" futures-util = "0.3" pin-project = "1.0" @@ -49,3 +52,5 @@ serde_bytes = "0.11" serde_json = "1.0" quick-xml = { version = "0.21", features = [ "serialize" ] } url = "2.1" + +opentelemetry = "0.17" diff --git a/src/api/api_server.rs b/src/api/api_server.rs index 322ea298..15b00dde 100644 --- a/src/api/api_server.rs +++ b/src/api/api_server.rs @@ -7,6 +7,11 @@ use hyper::server::conn::AddrStream; use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Method, Request, Response, Server}; +use opentelemetry::{ + trace::{FutureExt, TraceContextExt, Tracer}, + Context, +}; + use garage_util::data::*; use garage_util::error::Error as GarageError; @@ -43,7 +48,20 @@ pub async fn run_api_server( async move { Ok::<_, GarageError>(service_fn(move |req: Request| { let garage = garage.clone(); - handler(garage, req, client_addr) + + let tracer = opentelemetry::global::tracer("garage"); + let uuid = gen_uuid(); + let span = tracer + .span_builder("S3 API call (unknown)") + .with_trace_id( + opentelemetry::trace::TraceId::from_hex(&hex::encode( + &uuid.as_slice()[..16], + )) + .unwrap(), + ) + .start(&tracer); + + handler(garage, req, client_addr).with_context(Context::current_with_span(span)) })) } }); @@ -111,6 +129,10 @@ async fn handler_inner(garage: Arc, req: Request) -> Result(format!("S3 API {}", endpoint)); + // Some endpoints are processed early, before we even check for an API key if let Endpoint::PostObject = endpoint { return handle_post_object(garage, req, bucket_name.unwrap()).await; diff --git a/src/api/lib.rs b/src/api/lib.rs index 071cd7a6..f865325e 100644 --- a/src/api/lib.rs +++ b/src/api/lib.rs @@ -1,6 +1,6 @@ //! Crate for serving a S3 compatible API #[macro_use] -extern crate log; +extern crate tracing; pub mod error; pub use error::Error; diff --git a/src/api/s3_router.rs b/src/api/s3_router.rs index 95a7eceb..c325805d 100644 --- a/src/api/s3_router.rs +++ b/src/api/s3_router.rs @@ -5,6 +5,8 @@ use std::borrow::Cow; use hyper::header::HeaderValue; use hyper::{HeaderMap, Method, Request}; +use strum_macros::Display; + /// This macro is used to generate very repetitive match {} blocks in this module /// It is _not_ made to be used anywhere else macro_rules! s3_match { @@ -133,7 +135,7 @@ s3_match! {@func /// query parameters). Parameters it may receive by header are left out, however headers are /// considered when required to determine between one endpoint or another (for CopyObject and /// UploadObject, for instance). -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Display)] pub enum Endpoint { AbortMultipartUpload { key: String, -- cgit v1.2.3