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.
pull/141/head
Christopher Serr 2024-02-02 00:14:49 +01:00 committed by Ethan Brierley
parent 94a38211f7
commit 3422e7338c
4 changed files with 62 additions and 38 deletions

View File

@ -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

View File

@ -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)]

View File

@ -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<Response>) {
#[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

View File

@ -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)*