Skip to main content

tonic_debug/
layer.rs

1//! Tower Layer implementation for the gRPC debug middleware.
2//!
3//! [`DebugLayer`] is the primary entry point for users of this crate. It wraps
4//! any tonic/tower service with request/response inspection and logging.
5
6use tower_layer::Layer;
7
8use crate::service::DebugService;
9
10/// Configuration for the gRPC debug middleware.
11#[derive(Debug, Clone)]
12pub struct DebugLayer {
13    config: DebugConfig,
14}
15
16/// Controls what the debug middleware captures and logs.
17#[derive(Debug, Clone)]
18pub struct DebugConfig {
19    /// Log request headers.
20    pub log_headers: bool,
21    /// Log request and response bodies (protobuf inspection).
22    pub log_bodies: bool,
23    /// Log individual response body frames as they stream.
24    pub log_response_frames: bool,
25    /// Maximum number of bytes to capture for body inspection.
26    pub max_body_bytes: usize,
27    /// Include a hex dump of raw bytes in logs.
28    pub hex_dump: bool,
29}
30
31impl Default for DebugConfig {
32    fn default() -> Self {
33        Self {
34            log_headers: true,
35            log_bodies: true,
36            log_response_frames: true,
37            max_body_bytes: 4096,
38            hex_dump: false,
39        }
40    }
41}
42
43impl DebugLayer {
44    /// Create a new `DebugLayer` with default configuration.
45    ///
46    /// By default, headers and bodies are logged, hex dumps are off.
47    pub fn new() -> Self {
48        Self {
49            config: DebugConfig::default(),
50        }
51    }
52
53    /// Create a new `DebugLayer` with the given configuration.
54    pub fn with_config(config: DebugConfig) -> Self {
55        Self { config }
56    }
57
58    /// Set whether to log request/response headers.
59    pub fn log_headers(mut self, enabled: bool) -> Self {
60        self.config.log_headers = enabled;
61        self
62    }
63
64    /// Set whether to log request/response bodies.
65    pub fn log_bodies(mut self, enabled: bool) -> Self {
66        self.config.log_bodies = enabled;
67        self
68    }
69
70    /// Set whether to log individual response body frames.
71    pub fn log_response_frames(mut self, enabled: bool) -> Self {
72        self.config.log_response_frames = enabled;
73        self
74    }
75
76    /// Set the maximum number of bytes to capture for body inspection.
77    pub fn max_body_bytes(mut self, max: usize) -> Self {
78        self.config.max_body_bytes = max;
79        self
80    }
81
82    /// Set whether to include hex dumps in log output.
83    pub fn hex_dump(mut self, enabled: bool) -> Self {
84        self.config.hex_dump = enabled;
85        self
86    }
87}
88
89impl Default for DebugLayer {
90    fn default() -> Self {
91        Self::new()
92    }
93}
94
95impl<S> Layer<S> for DebugLayer {
96    type Service = DebugService<S>;
97
98    fn layer(&self, inner: S) -> Self::Service {
99        DebugService::new(inner, self.config.clone())
100    }
101}