mirror of
https://github.com/actix/actix-extras.git
synced 2025-02-23 10:53:02 +01:00
Allow level customisation (#91)
* Add the possibility to specify the span level for the root span. * Improve docs.
This commit is contained in:
parent
601210678f
commit
0eb13e9794
29
README.md
29
README.md
@ -182,6 +182,35 @@ We need to use a macro because `tracing` requires all the properties attached to
|
|||||||
You cannot add new ones afterwards. This makes it extremely fast, but it pushes us to reach for macros when we need some level of
|
You cannot add new ones afterwards. This makes it extremely fast, but it pushes us to reach for macros when we need some level of
|
||||||
composition.
|
composition.
|
||||||
|
|
||||||
|
[`root_span!`] exposes more or less the same knob you can find on `tracing`'s `span!` macro. You can, for example, customise
|
||||||
|
the span level:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use actix_web::dev::{ServiceResponse, ServiceRequest};
|
||||||
|
use actix_web::Error;
|
||||||
|
use tracing_actix_web::{TracingLogger, DefaultRootSpanBuilder, RootSpanBuilder, Level};
|
||||||
|
use tracing::Span;
|
||||||
|
|
||||||
|
pub struct CustomLevelRootSpanBuilder;
|
||||||
|
|
||||||
|
impl RootSpanBuilder for CustomLevelRootSpanBuilder {
|
||||||
|
fn on_request_start(request: &ServiceRequest) -> Span {
|
||||||
|
let level = if request.path() == "/health_check" {
|
||||||
|
Level::DEBUG
|
||||||
|
} else {
|
||||||
|
Level::INFO
|
||||||
|
};
|
||||||
|
tracing_actix_web::root_span!(level = level, request)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_request_end<B>(span: Span, outcome: &Result<ServiceResponse<B>, Error>) {
|
||||||
|
DefaultRootSpanBuilder::on_request_end(span, outcome);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let custom_middleware = TracingLogger::<CustomLevelRootSpanBuilder>::new();
|
||||||
|
```
|
||||||
|
|
||||||
## The [`RootSpan`] extractor
|
## The [`RootSpan`] extractor
|
||||||
|
|
||||||
It often happens that not all information about a task is known upfront, encoded in the incoming request.
|
It often happens that not all information about a task is known upfront, encoded in the incoming request.
|
||||||
|
31
src/lib.rs
31
src/lib.rs
@ -151,6 +151,35 @@
|
|||||||
//! You cannot add new ones afterwards. This makes it extremely fast, but it pushes us to reach for macros when we need some level of
|
//! You cannot add new ones afterwards. This makes it extremely fast, but it pushes us to reach for macros when we need some level of
|
||||||
//! composition.
|
//! composition.
|
||||||
//!
|
//!
|
||||||
|
//! [`root_span!`] exposes more or less the same knob you can find on `tracing`'s `span!` macro. You can, for example, customise
|
||||||
|
//! the span level:
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use actix_web::dev::{ServiceResponse, ServiceRequest};
|
||||||
|
//! use actix_web::Error;
|
||||||
|
//! use tracing_actix_web::{TracingLogger, DefaultRootSpanBuilder, RootSpanBuilder, Level};
|
||||||
|
//! use tracing::Span;
|
||||||
|
//!
|
||||||
|
//! pub struct CustomLevelRootSpanBuilder;
|
||||||
|
//!
|
||||||
|
//! impl RootSpanBuilder for CustomLevelRootSpanBuilder {
|
||||||
|
//! fn on_request_start(request: &ServiceRequest) -> Span {
|
||||||
|
//! let level = if request.path() == "/health_check" {
|
||||||
|
//! Level::DEBUG
|
||||||
|
//! } else {
|
||||||
|
//! Level::INFO
|
||||||
|
//! };
|
||||||
|
//! tracing_actix_web::root_span!(level = level, request)
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! fn on_request_end<B>(span: Span, outcome: &Result<ServiceResponse<B>, Error>) {
|
||||||
|
//! DefaultRootSpanBuilder::on_request_end(span, outcome);
|
||||||
|
//! }
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! let custom_middleware = TracingLogger::<CustomLevelRootSpanBuilder>::new();
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
//! ## The [`RootSpan`] extractor
|
//! ## The [`RootSpan`] extractor
|
||||||
//!
|
//!
|
||||||
//! It often happens that not all information about a task is known upfront, encoded in the incoming request.
|
//! It often happens that not all information about a task is known upfront, encoded in the incoming request.
|
||||||
@ -244,6 +273,8 @@ pub use middleware::TracingLogger;
|
|||||||
pub use request_id::RequestId;
|
pub use request_id::RequestId;
|
||||||
pub use root_span::RootSpan;
|
pub use root_span::RootSpan;
|
||||||
pub use root_span_builder::{DefaultRootSpanBuilder, RootSpanBuilder};
|
pub use root_span_builder::{DefaultRootSpanBuilder, RootSpanBuilder};
|
||||||
|
// Re-exporting the `Level` enum since it's used in our `root_span!` macro
|
||||||
|
pub use tracing::Level;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod root_span_macro;
|
pub mod root_span_macro;
|
||||||
|
@ -37,7 +37,7 @@ pub struct DefaultRootSpanBuilder;
|
|||||||
|
|
||||||
impl RootSpanBuilder for DefaultRootSpanBuilder {
|
impl RootSpanBuilder for DefaultRootSpanBuilder {
|
||||||
fn on_request_start(request: &ServiceRequest) -> Span {
|
fn on_request_start(request: &ServiceRequest) -> Span {
|
||||||
root_span!(request)
|
root_span!(level = crate::Level::INFO, request)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_request_end<B>(span: Span, outcome: &Result<ServiceResponse<B>, Error>) {
|
fn on_request_end<B>(span: Span, outcome: &Result<ServiceResponse<B>, Error>) {
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
///
|
///
|
||||||
/// ```rust,should_panic
|
/// ```rust,should_panic
|
||||||
/// # let request: &actix_web::dev::ServiceRequest = todo!();
|
/// # let request: &actix_web::dev::ServiceRequest = todo!();
|
||||||
|
/// use tracing_actix_web::Level;
|
||||||
///
|
///
|
||||||
/// // Define a `client_id` field as empty. It might be populated later.
|
/// // Define a `client_id` field as empty. It might be populated later.
|
||||||
/// tracing_actix_web::root_span!(request, client_id = tracing::field::Empty);
|
/// tracing_actix_web::root_span!(request, client_id = tracing::field::Empty);
|
||||||
@ -50,6 +51,9 @@
|
|||||||
/// let app_id = "XYZ";
|
/// let app_id = "XYZ";
|
||||||
/// tracing_actix_web::root_span!(request, app_id);
|
/// tracing_actix_web::root_span!(request, app_id);
|
||||||
///
|
///
|
||||||
|
/// // Use a custom level, `DEBUG`, instead of the default (`INFO`).
|
||||||
|
/// tracing_actix_web::root_span!(level = Level::DEBUG, request);
|
||||||
|
///
|
||||||
/// // All together
|
/// // All together
|
||||||
/// tracing_actix_web::root_span!(request, client_id = tracing::field::Empty, name = "AppName", app_id);
|
/// tracing_actix_web::root_span!(request, client_id = tracing::field::Empty, name = "AppName", app_id);
|
||||||
/// ```
|
/// ```
|
||||||
@ -58,10 +62,18 @@
|
|||||||
macro_rules! root_span {
|
macro_rules! root_span {
|
||||||
// Vanilla root span, with no additional fields
|
// Vanilla root span, with no additional fields
|
||||||
($request:ident) => {
|
($request:ident) => {
|
||||||
root_span!($request,)
|
$crate::root_span!($request,)
|
||||||
|
};
|
||||||
|
// Vanilla root span, with a level but no additional fields
|
||||||
|
(level = $lvl:expr, $request:ident) => {
|
||||||
|
$crate::root_span!(level = $lvl, $request,)
|
||||||
|
};
|
||||||
|
// One or more additional fields, comma separated, without a level
|
||||||
|
($request:ident, $($field:tt)*) => {
|
||||||
|
$crate::root_span!(level = $crate::Level::INFO, $request, $($field)*)
|
||||||
};
|
};
|
||||||
// One or more additional fields, comma separated
|
// One or more additional fields, comma separated
|
||||||
($request:ident, $($field:tt)*) => {
|
(level = $lvl:expr, $request:ident, $($field:tt)*) => {
|
||||||
{
|
{
|
||||||
let user_agent = $request
|
let user_agent = $request
|
||||||
.headers()
|
.headers()
|
||||||
@ -75,7 +87,11 @@ macro_rules! root_span {
|
|||||||
let http_method = $crate::root_span_macro::private::http_method_str($request.method());
|
let http_method = $crate::root_span_macro::private::http_method_str($request.method());
|
||||||
let connection_info = $request.connection_info();
|
let connection_info = $request.connection_info();
|
||||||
let request_id = $crate::root_span_macro::private::get_request_id($request);
|
let request_id = $crate::root_span_macro::private::get_request_id($request);
|
||||||
let span = $crate::root_span_macro::private::tracing::info_span!(
|
|
||||||
|
macro_rules! inner_span {
|
||||||
|
($level:expr) => {
|
||||||
|
$crate::root_span_macro::private::tracing::span!(
|
||||||
|
$level,
|
||||||
"HTTP request",
|
"HTTP request",
|
||||||
http.method = %http_method,
|
http.method = %http_method,
|
||||||
http.route = %http_route,
|
http.route = %http_route,
|
||||||
@ -95,7 +111,16 @@ macro_rules! root_span {
|
|||||||
// Not proper OpenTelemetry, but their terminology is fairly exception-centric
|
// Not proper OpenTelemetry, but their terminology is fairly exception-centric
|
||||||
exception.details = $crate::root_span_macro::private::tracing::field::Empty,
|
exception.details = $crate::root_span_macro::private::tracing::field::Empty,
|
||||||
$($field)*
|
$($field)*
|
||||||
);
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
let span = match $lvl {
|
||||||
|
$crate::Level::TRACE => inner_span!($crate::Level::TRACE),
|
||||||
|
$crate::Level::DEBUG => inner_span!($crate::Level::DEBUG),
|
||||||
|
$crate::Level::INFO => inner_span!($crate::Level::INFO),
|
||||||
|
$crate::Level::WARN => inner_span!($crate::Level::WARN),
|
||||||
|
$crate::Level::ERROR => inner_span!($crate::Level::ERROR),
|
||||||
|
};
|
||||||
std::mem::drop(connection_info);
|
std::mem::drop(connection_info);
|
||||||
|
|
||||||
// Previously, this line was instrumented with an opentelemetry-specific feature
|
// Previously, this line was instrumented with an opentelemetry-specific feature
|
||||||
|
Loading…
x
Reference in New Issue
Block a user