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}