Skip to main content

tonic_debug/
lib.rs

1//! # tonic-debug
2//!
3//! A debugging and diagnostics middleware for [tonic](https://github.com/hyperium/tonic)
4//! gRPC servers.
5//!
6//! ## Overview
7//!
8//! Debugging gRPC services built with tonic can be challenging — messages are
9//! binary-encoded protobufs, connection issues are opaque, and the standard
10//! logging often lacks the detail needed to quickly diagnose problems.
11//!
12//! `tonic-debug` solves this by providing:
13//!
14//! - **Human-readable protobuf inspection** — decodes protobuf wire format
15//!   without needing `.proto` schemas, showing field numbers, types, and values.
16//! - **Connection lifecycle observability** — tracks connection events (connect,
17//!   disconnect, errors) with active/total counters via tower/hyper integration.
18//! - **Structured logging via `tracing`** — all output goes through the
19//!   `tracing` crate with structured fields for easy filtering and aggregation.
20//! - **Optional OpenTelemetry export** — enable the `opentelemetry` feature to
21//!   forward spans and attributes to your OTel collector.
22//!
23//! ## Quick Start
24//!
25//! ```rust,no_run
26//! use tonic_debug::DebugLayer;
27//!
28//! // Add the debug layer to your tonic server
29//! // tonic::transport::Server::builder()
30//! //     .layer(DebugLayer::new())
31//! //     .add_service(my_service)
32//! //     .serve(addr)
33//! //     .await?;
34//! ```
35//!
36//! ## Configuration
37//!
38//! ```rust
39//! use tonic_debug::{DebugLayer, DebugConfig};
40//! use std::collections::HashSet;
41//!
42//! let layer = DebugLayer::with_config(DebugConfig {
43//!     log_headers: true,
44//!     log_bodies: true,
45//!     log_response_frames: true,
46//!     max_body_bytes: 8192,
47//!     hex_dump: false,
48//!     sensitive_headers: HashSet::new(),
49//!     reveal_sensitive_headers: false,
50//! });
51//! ```
52//!
53//! ## Connection Tracking
54//!
55//! ```rust
56//! use tonic_debug::ConnectionMetrics;
57//!
58//! let metrics = ConnectionMetrics::new();
59//! // Use metrics.active_connections(), metrics.total_connections(), etc.
60//! ```
61//!
62//! ## Feature Flags
63//!
64//! | Feature        | Description                                      |
65//! |----------------|--------------------------------------------------|
66//! | `opentelemetry`| Adds OpenTelemetry span attributes and export    |
67
68pub mod body;
69pub mod connection;
70pub mod inspect;
71pub mod layer;
72#[cfg(feature = "opentelemetry")]
73pub mod otel;
74pub mod service;
75
76// Re-export primary types for ergonomic usage.
77pub use connection::{ConnectionGuard, ConnectionMetrics, ConnectionTrackerLayer};
78pub use layer::{DebugConfig, DebugLayer};
79pub use service::DebugService;
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84
85    #[test]
86    fn test_debug_layer_default() {
87        let layer = DebugLayer::new();
88        // Should compile and create without panicking.
89        let _ = layer;
90    }
91
92    #[test]
93    fn test_debug_layer_builder() {
94        let layer = DebugLayer::new()
95            .log_headers(false)
96            .log_bodies(true)
97            .log_response_frames(false)
98            .max_body_bytes(1024)
99            .hex_dump(true);
100        let _ = layer;
101    }
102
103    #[test]
104    fn test_debug_config_default() {
105        let config = DebugConfig::default();
106        assert!(config.log_headers);
107        assert!(config.log_bodies);
108        assert!(config.log_response_frames);
109        assert_eq!(config.max_body_bytes, 4096);
110        assert!(!config.hex_dump);
111    }
112
113    #[test]
114    fn test_connection_metrics_default() {
115        let metrics = ConnectionMetrics::new();
116        assert_eq!(metrics.active_connections(), 0);
117        assert_eq!(metrics.total_connections(), 0);
118        assert_eq!(metrics.connection_errors(), 0);
119    }
120}