It is not uncommon that users who are new to tracing look at the examples in the `master` branch of the repository and find that they don't compile. This is because they are examples which compile with the code from the master branch, which is for the as yet unreleased tracing 0.2.0 ecosystem. Users should instead go to the `v0.1.x` branch to find examples compatible with the crates published on crates.io. This change adds a doc-comment to the beginning of every example file informing the user of this fact and suggesting that they check out the `v0.1.x` branch instead.
104 lines
2.9 KiB
Rust
104 lines
2.9 KiB
Rust
//! NOTE: This is pre-release documentation for the upcoming tracing 0.2.0 ecosystem. For the
|
|
//! release examples, please see the `v0.1.x` branch instead.
|
|
use futures::future;
|
|
use http::{Request, Response};
|
|
use hyper::{Body, Server};
|
|
use std::task::{Context, Poll};
|
|
use std::time::Duration;
|
|
use tower::{Service, ServiceBuilder};
|
|
use tracing::dispatch;
|
|
use tracing::info;
|
|
use tracing_tower::request_span::make;
|
|
|
|
type Err = Box<dyn std::error::Error + Send + Sync + 'static>;
|
|
|
|
fn req_span<A>(req: &Request<A>) -> tracing::Span {
|
|
let span = tracing::info_span!(
|
|
"request",
|
|
req.method = ?req.method(),
|
|
req.uri = ?req.uri(),
|
|
req.version = ?req.version(),
|
|
req.headers = ?req.headers()
|
|
);
|
|
tracing::info!(parent: &span, "received request");
|
|
span
|
|
}
|
|
|
|
const ROOT: &str = "/";
|
|
|
|
#[derive(Debug)]
|
|
pub struct Svc;
|
|
|
|
impl Service<Request<Body>> for Svc {
|
|
type Response = Response<Body>;
|
|
type Error = hyper::Error;
|
|
type Future = future::Ready<Result<Self::Response, Self::Error>>;
|
|
|
|
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
|
Ok(()).into()
|
|
}
|
|
|
|
fn call(&mut self, req: Request<Body>) -> Self::Future {
|
|
let rsp = Response::builder();
|
|
|
|
let uri = req.uri();
|
|
let rsp = if uri.path() != ROOT {
|
|
let body = Body::from(Vec::new());
|
|
rsp.status(404).body(body).unwrap()
|
|
} else {
|
|
let body = Body::from(Vec::from(&b"heyo!"[..]));
|
|
rsp.status(200).body(body).unwrap()
|
|
};
|
|
let span = tracing::info_span!(
|
|
"response",
|
|
rsp.status = ?rsp.status(),
|
|
rsp.version = ?rsp.version(),
|
|
rsp.headers = ?rsp.headers()
|
|
);
|
|
|
|
dispatch::get_default(|dispatch| {
|
|
let id = span.id().expect("Missing ID; this is a bug");
|
|
if let Some(current) = dispatch.current_span().id() {
|
|
dispatch.record_follows_from(&id, current)
|
|
}
|
|
});
|
|
let _guard = span.enter();
|
|
info!("sending response");
|
|
future::ok(rsp)
|
|
}
|
|
}
|
|
|
|
pub struct MakeSvc;
|
|
|
|
impl<T> Service<T> for MakeSvc {
|
|
type Response = Svc;
|
|
type Error = std::io::Error;
|
|
type Future = future::Ready<Result<Self::Response, Self::Error>>;
|
|
|
|
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
|
Ok(()).into()
|
|
}
|
|
|
|
fn call(&mut self, _: T) -> Self::Future {
|
|
future::ok(Svc)
|
|
}
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result<(), Err> {
|
|
tracing_subscriber::fmt()
|
|
.with_env_filter("tower=trace")
|
|
.try_init()?;
|
|
|
|
let svc = ServiceBuilder::new()
|
|
.timeout(Duration::from_millis(250))
|
|
.layer(make::layer::<_, Svc, _>(req_span))
|
|
.service(MakeSvc);
|
|
|
|
let addr = "127.0.0.1:3000".parse()?;
|
|
let server = Server::bind(&addr).serve(svc);
|
|
info!(message = "listening", addr = ?addr);
|
|
server.await?;
|
|
|
|
Ok(())
|
|
}
|