From 3422e7338c4daa7fa981d313d29351f995eb71f9 Mon Sep 17 00:00:00 2001 From: Christopher Serr Date: Fri, 2 Feb 2024 00:14:49 +0100 Subject: [PATCH] Match stable Semantic Conventions for HTTP Spans The stable [Semantic Conventions for HTTP Spans](https://opentelemetry.io/docs/specs/semconv/http/http-spans/) use different keys than the ones used in this crate. This changes them to match the keys as defined by the stable specification. --- reqwest-tracing/CHANGELOG.md | 4 ++ reqwest-tracing/src/lib.rs | 6 +- .../src/reqwest_otel_span_builder.rs | 60 ++++++++++++------- .../src/reqwest_otel_span_macro.rs | 30 ++++++---- 4 files changed, 62 insertions(+), 38 deletions(-) diff --git a/reqwest-tracing/CHANGELOG.md b/reqwest-tracing/CHANGELOG.md index 04b3965..1f8450f 100644 --- a/reqwest-tracing/CHANGELOG.md +++ b/reqwest-tracing/CHANGELOG.md @@ -9,11 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Breaking changes - Upgraded `reqwest-middleware` to `0.3.0`. - Removed support for `opentelemetry` 0.13 to 0.19 +- The keys emitted by the crate now match the stable Semantic Conventions for HTTP Spans. ### Changed - The keys emitted by the crate now match the stable Semantic Conventions for HTTP Spans. - Opentelemetry features are now additive. +### Deprecated +- The old keys are now deprecated. + ## [0.4.8] - 2024-03-11 ### Added diff --git a/reqwest-tracing/src/lib.rs b/reqwest-tracing/src/lib.rs index e0b38b9..ad84f1b 100644 --- a/reqwest-tracing/src/lib.rs +++ b/reqwest-tracing/src/lib.rs @@ -91,12 +91,14 @@ mod middleware; mod otel; mod reqwest_otel_span_builder; pub use middleware::TracingMiddleware; +#[allow(deprecated)] pub use reqwest_otel_span_builder::{ default_on_request_end, default_on_request_failure, default_on_request_success, default_span_name, DefaultSpanBackend, DisableOtelPropagation, OtelName, OtelPathNames, ReqwestOtelSpanBackend, SpanBackendWithUrl, ERROR_CAUSE_CHAIN, ERROR_MESSAGE, HTTP_HOST, - HTTP_METHOD, HTTP_SCHEME, HTTP_STATUS_CODE, HTTP_URL, HTTP_USER_AGENT, NET_HOST_PORT, - OTEL_KIND, OTEL_NAME, OTEL_STATUS_CODE, + HTTP_METHOD, HTTP_REQUEST_METHOD, HTTP_RESPONSE_STATUS_CODE, HTTP_SCHEME, HTTP_STATUS_CODE, + HTTP_URL, HTTP_USER_AGENT, NET_HOST_PORT, OTEL_KIND, OTEL_NAME, OTEL_STATUS_CODE, + SERVER_ADDRESS, SERVER_PORT, URL_FULL, URL_SCHEME, USER_AGENT_ORIGINAL, }; #[doc(hidden)] diff --git a/reqwest-tracing/src/reqwest_otel_span_builder.rs b/reqwest-tracing/src/reqwest_otel_span_builder.rs index c425eb8..a24c784 100644 --- a/reqwest-tracing/src/reqwest_otel_span_builder.rs +++ b/reqwest-tracing/src/reqwest_otel_span_builder.rs @@ -2,36 +2,57 @@ use std::borrow::Cow; use http::Extensions; use matchit::Router; -use reqwest::header::{HeaderMap, HeaderValue}; -use reqwest::{Request, Response, StatusCode as RequestStatusCode, Url}; +use reqwest::{header::HeaderValue, Request, Response, StatusCode as RequestStatusCode, Url}; use reqwest_middleware::{Error, Result}; use tracing::{warn, Span}; use crate::reqwest_otel_span; -/// The `http.method` field added to the span by [`reqwest_otel_span`] -pub const HTTP_METHOD: &str = "http.method"; -/// The `http.scheme` field added to the span by [`reqwest_otel_span`] -pub const HTTP_SCHEME: &str = "http.scheme"; -/// The `http.host` field added to the span by [`reqwest_otel_span`] -pub const HTTP_HOST: &str = "http.host"; -/// The `http.url` field added to the span by [`reqwest_otel_span`] -pub const HTTP_URL: &str = "http.url"; -/// The `host.port` field added to the span by [`reqwest_otel_span`] -pub const NET_HOST_PORT: &str = "net.host.port"; +/// The `http.request.method` field added to the span by [`reqwest_otel_span`] +pub const HTTP_REQUEST_METHOD: &str = "http.request.method"; +/// The `url.scheme` field added to the span by [`reqwest_otel_span`] +pub const URL_SCHEME: &str = "url.scheme"; +/// The `server.address` field added to the span by [`reqwest_otel_span`] +pub const SERVER_ADDRESS: &str = "server.address"; +/// The `server.port` field added to the span by [`reqwest_otel_span`] +pub const SERVER_PORT: &str = "server.port"; +/// The `url.full` field added to the span by [`reqwest_otel_span`] +pub const URL_FULL: &str = "url.full"; +/// The `user_agent.original` field added to the span by [`reqwest_otel_span`] +pub const USER_AGENT_ORIGINAL: &str = "user_agent.original"; /// The `otel.kind` field added to the span by [`reqwest_otel_span`] pub const OTEL_KIND: &str = "otel.kind"; /// The `otel.name` field added to the span by [`reqwest_otel_span`] pub const OTEL_NAME: &str = "otel.name"; /// The `otel.status_code` field added to the span by [`reqwest_otel_span`] pub const OTEL_STATUS_CODE: &str = "otel.status_code"; +/// The `http.response.status_code` field added to the span by [`reqwest_otel_span`] +pub const HTTP_RESPONSE_STATUS_CODE: &str = "http.response.status_code"; /// The `error.message` field added to the span by [`reqwest_otel_span`] pub const ERROR_MESSAGE: &str = "error.message"; /// The `error.cause_chain` field added to the span by [`reqwest_otel_span`] pub const ERROR_CAUSE_CHAIN: &str = "error.cause_chain"; -/// The `http.status_code` field added to the span by [`reqwest_otel_span`] + +/// The deprecated `http.method` field added to the span by [`reqwest_otel_span`] +#[deprecated] +pub const HTTP_METHOD: &str = "http.method"; +/// The deprecated `http.scheme` field added to the span by [`reqwest_otel_span`] +#[deprecated] +pub const HTTP_SCHEME: &str = "http.scheme"; +/// The deprecated `http.host` field added to the span by [`reqwest_otel_span`] +#[deprecated] +pub const HTTP_HOST: &str = "http.host"; +/// The deprecated `http.url` field added to the span by [`reqwest_otel_span`] +#[deprecated] +pub const HTTP_URL: &str = "http.url"; +/// The deprecated `host.port` field added to the span by [`reqwest_otel_span`] +#[deprecated] +pub const NET_HOST_PORT: &str = "net.host.port"; +/// The deprecated `http.status_code` field added to the span by [`reqwest_otel_span`] +#[deprecated] pub const HTTP_STATUS_CODE: &str = "http.status_code"; -/// The `http.user_agent` added to the span by [`reqwest_otel_span`] +/// The deprecated `http.user_agent` added to the span by [`reqwest_otel_span`] +#[deprecated] pub const HTTP_USER_AGENT: &str = "http.user_agent"; /// [`ReqwestOtelSpanBackend`] allows you to customise the span attached by @@ -61,12 +82,10 @@ pub fn default_on_request_end(span: &Span, outcome: &Result) { #[inline] pub fn default_on_request_success(span: &Span, response: &Response) { let span_status = get_span_status(response.status()); - let user_agent = get_header_value("user_agent", response.headers()); if let Some(span_status) = span_status { span.record(OTEL_STATUS_CODE, span_status); } - span.record(HTTP_STATUS_CODE, response.status().as_u16()); - span.record(HTTP_USER_AGENT, user_agent.as_str()); + span.record(HTTP_RESPONSE_STATUS_CODE, response.status().as_u16()); } /// Populates default failure fields for a given [`reqwest_otel_span!`] span. @@ -79,7 +98,7 @@ pub fn default_on_request_failure(span: &Span, e: &Error) { span.record(ERROR_CAUSE_CHAIN, error_cause_chain.as_str()); if let Error::Reqwest(e) = e { if let Some(status) = e.status() { - span.record(HTTP_STATUS_CODE, status.as_u16()); + span.record(HTTP_RESPONSE_STATUS_CODE, status.as_u16()); } } } @@ -122,11 +141,6 @@ impl ReqwestOtelSpanBackend for DefaultSpanBackend { } } -fn get_header_value(key: &str, headers: &HeaderMap) -> String { - let header_default = &HeaderValue::from_static(""); - format!("{:?}", headers.get(key).unwrap_or(header_default)).replace('"', "") -} - /// Similar to [`DefaultSpanBackend`] but also adds the `http.url` attribute to request spans. /// /// [`TracingMiddleware`]: crate::middleware::TracingMiddleware diff --git a/reqwest-tracing/src/reqwest_otel_span_macro.rs b/reqwest-tracing/src/reqwest_otel_span_macro.rs index 3ea5287..a757fc4 100644 --- a/reqwest-tracing/src/reqwest_otel_span_macro.rs +++ b/reqwest-tracing/src/reqwest_otel_span_macro.rs @@ -3,15 +3,16 @@ /// It empowers you to add custom properties to the span on top of the default properties provided by the macro /// /// Default Fields: -/// - http.method -/// - http.scheme -/// - http.host -/// - net.host +/// - http.request.method +/// - url.scheme +/// - server.address +/// - server.port +/// - url.full /// - otel.kind /// - otel.name /// - otel.status_code -/// - http.user_agent -/// - http.status_code +/// - user_agent.original +/// - http.response.status_code /// - error.message /// - error.cause_chain /// @@ -122,23 +123,26 @@ macro_rules! reqwest_otel_span { let url = $request.url(); let scheme = url.scheme(); let host = url.host_str().unwrap_or(""); - let host_port = url.port().unwrap_or(0) as i64; + let host_port = url.port_or_known_default().unwrap_or(0) as i64; let otel_name = $name.to_string(); + let header_default = &HeaderValue::from_static(""); + let user_agent = format!("{:?}", $request.headers().get("user_agent").unwrap_or(header_default)).replace('"', ""); macro_rules! request_span { ($lvl:expr) => { $crate::reqwest_otel_span_macro::private::span!( $lvl, "HTTP request", - http.method = %method, - http.scheme = %scheme, - http.host = %host, - net.host.port = %host_port, + http.request.method = %method, + url.scheme = %scheme, + server.address = %host, + server.port = %host_port, + url.full = %url, + user_agent.original = %user_agent, otel.kind = "client", otel.name = %otel_name, otel.status_code = tracing::field::Empty, - http.user_agent = tracing::field::Empty, - http.status_code = tracing::field::Empty, + http.response.status_code = tracing::field::Empty, error.message = tracing::field::Empty, error.cause_chain = tracing::field::Empty, $($field)*