Greatly improve Debug output of ServiceBuilder (#280)

This commit is contained in:
Sean McArthur 2019-05-09 08:44:40 -07:00 committed by Carl Lerche
parent 4d6d2c8572
commit b9c2fea0fc
6 changed files with 72 additions and 8 deletions

View File

@ -1,5 +1,5 @@
use crate::{error::Error, service::Buffer, worker::WorkerExecutor};
use std::marker::PhantomData;
use std::{fmt, marker::PhantomData};
use tokio_executor::DefaultExecutor;
use tower_layer::Layer;
use tower_service::Service;
@ -43,3 +43,15 @@ where
Buffer::with_executor(service, self.bound, &mut self.executor.clone())
}
}
impl<Request, E> fmt::Debug for BufferLayer<Request, E>
where
// Require E: Debug in case we want to print the executor at a later date
E: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("BufferLayer")
.field("bound", &self.bound)
.finish()
}
}

View File

@ -1,9 +1,10 @@
use std::fmt;
use tower_layer::Layer;
use crate::LoadShed;
/// A `tower-layer` to wrap services in `LoadShed` middleware.
#[derive(Debug)]
#[derive(Clone)]
pub struct LoadShedLayer {
_p: (),
}
@ -22,3 +23,9 @@ impl<S> Layer<S> for LoadShedLayer {
LoadShed::new(service)
}
}
impl fmt::Debug for LoadShedLayer {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("LoadShedLayer").finish()
}
}

View File

@ -1,10 +1,11 @@
use std::fmt;
use tower_layer::Layer;
/// A no-op middleware.
///
/// When wrapping a `Service`, the `Identity` layer returns the provided
/// service without modifying it.
#[derive(Debug, Default, Clone)]
#[derive(Default, Clone)]
pub struct Identity {
_p: (),
}
@ -24,3 +25,9 @@ impl<S> Layer<S> for Identity {
inner
}
}
impl fmt::Debug for Identity {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Identity").finish()
}
}

View File

@ -1,9 +1,8 @@
use std::fmt;
use tower_layer::Layer;
/// Two middlewares chained together.
///
/// This type is produced by `Layer::chain`.
#[derive(Clone, Debug)]
#[derive(Clone)]
pub struct Stack<Inner, Outer> {
inner: Inner,
outer: Outer,
@ -29,3 +28,35 @@ where
self.outer.layer(inner)
}
}
impl<Inner, Outer> fmt::Debug for Stack<Inner, Outer>
where
Inner: fmt::Debug,
Outer: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// The generated output of nested `Stack`s is very noisy and makes
// it harder to understand what is in a `ServiceBuilder`.
//
// Instead, this output is designed assuming that a `Stack` is
// usually quite nested, and inside a `ServiceBuilder`. Therefore,
// this skips using `f.debug_struct()`, since each one would force
// a new layer of indentation.
//
// - In compact mode, a nested stack ends up just looking like a flat
// list of layers.
//
// - In pretty mode, while a newline is inserted between each layer,
// the `DebugStruct` used in the `ServiceBuilder` will inject padding
// to that each line is at the same indentation level.
//
// Also, the order of [outer, inner] is important, since it reflects
// the order that the layers were added to the stack.
if f.alternate() {
// pretty
write!(f, "{:#?},\n{:#?}", self.outer, self.inner)
} else {
write!(f, "{:?}, {:?}", self.outer, self.inner)
}
}
}

View File

@ -11,7 +11,7 @@ use crate::{
use tower_layer::Layer;
use tower_util::layer::{Identity, Stack};
use std::time::Duration;
use std::{fmt, time::Duration};
/// Declaratively construct Service values.
///
@ -142,7 +142,7 @@ use std::time::Duration;
/// .rate_limit(5, Duration::from_secs(1))
/// .service(MyService);
/// ```
#[derive(Clone, Debug)]
#[derive(Clone)]
pub struct ServiceBuilder<L> {
layer: L,
}
@ -220,3 +220,9 @@ impl<L> ServiceBuilder<L> {
self.layer.layer(service)
}
}
impl<L: fmt::Debug> fmt::Debug for ServiceBuilder<L> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("ServiceBuilder").field(&self.layer).finish()
}
}

View File

@ -3,6 +3,7 @@
// compatibility
#![cfg(feature = "full")]
#![deny(missing_docs, missing_debug_implementations, rust_2018_idioms)]
#![allow(elided_lifetimes_in_paths)]
#![cfg_attr(test, deny(warnings))]
//! `fn(Request) -> Future<Response>`