reqwest_datadog_tracing/lib.rs
1// MIT License
2//
3// Copyright (c) 2021 TrueLayer
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to deal
7// in the Software without restriction, including without limitation the rights
8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9// copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23//! Opentracing middleware implementation for [`reqwest_middleware`].
24//!
25//! Attach [`TracingMiddleware`] to your client to automatically trace HTTP requests.
26//!
27//! The simplest possible usage:
28//! ```no_run
29//! # use reqwest_middleware::Result;
30//! use reqwest_middleware::{ClientBuilder};
31//! use reqwest_datadog_tracing::TracingMiddleware;
32//!
33//! # async fn example() -> Result<()> {
34//! let reqwest_client = reqwest::Client::builder().build().unwrap();
35//! let client = ClientBuilder::new(reqwest_client)
36//! // Insert the tracing middleware
37//! .with(TracingMiddleware::default())
38//! .build();
39//!
40//! let resp = client.get("https://truelayer.com").send().await.unwrap();
41//! # Ok(())
42//! # }
43//! ```
44//!
45//! To customise the span names use [`OtelName`].
46//! ```no_run
47//! # use reqwest_middleware::Result;
48//! use reqwest_middleware::{ClientBuilder, Extension};
49//! use reqwest_datadog_tracing::{
50//! TracingMiddleware, OtelName
51//! };
52//! # async fn example() -> Result<()> {
53//! let reqwest_client = reqwest::Client::builder().build().unwrap();
54//! let client = ClientBuilder::new(reqwest_client)
55//! // Inserts the extension before the request is started
56//! .with_init(Extension(OtelName("my-client".into())))
57//! // Makes use of that extension to specify the otel name
58//! .with(TracingMiddleware::default())
59//! .build();
60//!
61//! let resp = client.get("https://truelayer.com").send().await.unwrap();
62//!
63//! // Or specify it on the individual request (will take priority)
64//! let resp = client.post("https://api.truelayer.com/payment")
65//! .with_extension(OtelName("POST /payment".into()))
66//! .send()
67//! .await
68//! .unwrap();
69//! # Ok(())
70//! # }
71//! ```
72//!
73//! In this example we define a custom span builder to calculate the request time elapsed and we register the [`TracingMiddleware`].
74//!
75//! Note that Opentelemetry tracks start and stop already, there is no need to have a custom builder like this.
76//! ```rust
77//! use reqwest_middleware::Result;
78//! use http::Extensions;
79//! use reqwest::{Request, Response};
80//! use reqwest_middleware::ClientBuilder;
81//! use reqwest_datadog_tracing::{
82//! default_on_request_end, reqwest_otel_span, ReqwestOtelSpanBackend, TracingMiddleware
83//! };
84//! use tracing::Span;
85//! use std::time::{Duration, Instant};
86//!
87//! pub struct TimeTrace;
88//!
89//! impl ReqwestOtelSpanBackend for TimeTrace {
90//! fn on_request_start(req: &Request, extension: &mut Extensions) -> Span {
91//! extension.insert(Instant::now());
92//! reqwest_otel_span!(name="example-request", req, time_elapsed = tracing::field::Empty)
93//! }
94//!
95//! fn on_request_end(span: &Span, outcome: &Result<Response>, extension: &mut Extensions) {
96//! let time_elapsed = extension.get::<Instant>().unwrap().elapsed().as_millis() as i64;
97//! default_on_request_end(span, outcome);
98//! span.record("time_elapsed", &time_elapsed);
99//! }
100//! }
101//!
102//! let http = ClientBuilder::new(reqwest::Client::new())
103//! .with(TracingMiddleware::<TimeTrace>::new())
104//! .build();
105//! ```
106
107mod middleware;
108#[cfg(any(feature = "opentelemetry_0_30",))]
109mod otel;
110mod reqwest_otel_span_builder;
111pub use middleware::TracingMiddleware;
112pub use reqwest_otel_span_builder::{
113 DefaultSpanBackend, DisableOtelPropagation, ERROR_CAUSE_CHAIN, ERROR_MESSAGE,
114 HTTP_REQUEST_METHOD, HTTP_RESPONSE_STATUS_CODE, OTEL_KIND, OTEL_NAME, OTEL_STATUS_CODE,
115 OtelName, OtelPathNames, ReqwestOtelSpanBackend, SERVER_ADDRESS, SERVER_PORT,
116 SpanBackendWithUrl, URL_FULL, URL_SCHEME, USER_AGENT_ORIGINAL, default_on_request_end,
117 default_on_request_failure, default_on_request_success, default_span_name,
118};
119
120#[cfg(feature = "deprecated_attributes")]
121pub use reqwest_otel_span_builder::{
122 HTTP_HOST, HTTP_METHOD, HTTP_SCHEME, HTTP_STATUS_CODE, HTTP_URL, HTTP_USER_AGENT, NET_HOST_PORT,
123};
124
125#[doc(hidden)]
126pub mod reqwest_otel_span_macro;