turbomcp_telemetry/lib.rs
1//! OpenTelemetry integration and observability for TurboMCP SDK
2//!
3//! This crate provides comprehensive telemetry capabilities for MCP servers and clients:
4//!
5//! - **Distributed Tracing**: OpenTelemetry traces with MCP-specific span attributes
6//! - **Metrics Collection**: Request counts, latencies, error rates with Prometheus export
7//! - **Structured Logging**: JSON-formatted logs correlated with traces
8//! - **Tower Middleware**: Automatic instrumentation for MCP request handling
9//!
10//! # Quick Start
11//!
12//! ```rust,ignore
13//! use turbomcp_telemetry::{TelemetryConfig, TelemetryGuard};
14//!
15//! #[tokio::main]
16//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
17//! // Initialize telemetry with OTLP export
18//! let config = TelemetryConfig::builder()
19//! .service_name("my-mcp-server")
20//! .otlp_endpoint("http://localhost:4317")
21//! .build();
22//!
23//! let _guard = config.init()?;
24//!
25//! // Your MCP server code here...
26//! Ok(())
27//! }
28//! ```
29//!
30//! # Feature Flags
31//!
32//! - `opentelemetry` - Full OpenTelemetry integration with OTLP export
33//! - `prometheus` - Standalone Prometheus metrics (without OpenTelemetry)
34//! - `tower` - Tower middleware for automatic request instrumentation
35//! - `full` - All features enabled
36//!
37//! # Architecture
38//!
39//! ```text
40//! ┌─────────────────────────────────────────────────────────────┐
41//! │ TurboMCP Application │
42//! ├─────────────────────────────────────────────────────────────┤
43//! │ TelemetryLayer (Tower Middleware) │
44//! │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
45//! │ │ Tracing │ │ Metrics │ │ Context Propagation │ │
46//! │ └─────────────┘ └─────────────┘ └─────────────────────┘ │
47//! ├─────────────────────────────────────────────────────────────┤
48//! │ Export Layer │
49//! │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
50//! │ │ OTLP │ │ Prometheus │ │ Stdout │ │
51//! │ └─────────────┘ └─────────────┘ └─────────────────────┘ │
52//! └─────────────────────────────────────────────────────────────┘
53//! ```
54
55#![cfg_attr(docsrs, feature(doc_cfg))]
56// Allow missing error/panic docs - telemetry errors are self-documenting through TelemetryError type
57#![allow(clippy::missing_errors_doc, clippy::missing_panics_doc)]
58
59mod config;
60mod error;
61mod init;
62
63pub mod attributes;
64
65#[cfg(feature = "tower")]
66#[cfg_attr(docsrs, doc(cfg(feature = "tower")))]
67pub mod tower;
68
69#[cfg(feature = "prometheus")]
70#[cfg_attr(docsrs, doc(cfg(feature = "prometheus")))]
71pub mod metrics;
72
73// Re-exports
74pub use config::{TelemetryConfig, TelemetryConfigBuilder};
75pub use error::{TelemetryError, TelemetryResult};
76pub use init::TelemetryGuard;
77
78// Re-export tracing macros for convenience
79pub use tracing::{Instrument, instrument};
80pub use tracing::{debug, error, info, trace, warn};
81pub use tracing::{debug_span, error_span, info_span, trace_span, warn_span};
82
83/// MCP span attribute keys following OpenTelemetry semantic conventions
84pub mod span_attributes {
85 /// MCP method name (e.g., "tools/call", "resources/read")
86 pub const MCP_METHOD: &str = "mcp.method";
87 /// Tool name for tools/call requests
88 pub const MCP_TOOL_NAME: &str = "mcp.tool.name";
89 /// Resource URI for resources/read requests
90 pub const MCP_RESOURCE_URI: &str = "mcp.resource.uri";
91 /// Prompt name for prompts/get requests
92 pub const MCP_PROMPT_NAME: &str = "mcp.prompt.name";
93 /// JSON-RPC request ID
94 pub const MCP_REQUEST_ID: &str = "mcp.request.id";
95 /// MCP session ID
96 pub const MCP_SESSION_ID: &str = "mcp.session.id";
97 /// Client implementation name
98 pub const MCP_CLIENT_NAME: &str = "mcp.client.name";
99 /// Client implementation version
100 pub const MCP_CLIENT_VERSION: &str = "mcp.client.version";
101 /// Server implementation name
102 pub const MCP_SERVER_NAME: &str = "mcp.server.name";
103 /// Server implementation version
104 pub const MCP_SERVER_VERSION: &str = "mcp.server.version";
105 /// Transport type (stdio, http, websocket, tcp, unix)
106 pub const MCP_TRANSPORT: &str = "mcp.transport";
107 /// Protocol version
108 pub const MCP_PROTOCOL_VERSION: &str = "mcp.protocol.version";
109 /// Tenant ID for multi-tenant deployments
110 pub const MCP_TENANT_ID: &str = "mcp.tenant.id";
111 /// User ID from authentication
112 pub const MCP_USER_ID: &str = "mcp.user.id";
113 /// Request duration in milliseconds
114 pub const MCP_DURATION_MS: &str = "mcp.duration_ms";
115 /// Response status (success, error)
116 pub const MCP_STATUS: &str = "mcp.status";
117 /// Error code if request failed
118 pub const MCP_ERROR_CODE: &str = "mcp.error.code";
119 /// Error message if request failed
120 pub const MCP_ERROR_MESSAGE: &str = "mcp.error.message";
121}
122
123/// Prelude module for convenient imports
124pub mod prelude {
125 pub use super::config::{TelemetryConfig, TelemetryConfigBuilder};
126 pub use super::error::{TelemetryError, TelemetryResult};
127 pub use super::init::TelemetryGuard;
128 pub use super::span_attributes;
129 pub use tracing::{Instrument, debug, error, info, instrument, trace, warn};
130
131 #[cfg(feature = "tower")]
132 pub use super::tower::{TelemetryLayer, TelemetryLayerConfig};
133}
134
135#[cfg(test)]
136mod tests {
137 use super::*;
138
139 #[test]
140 fn test_span_attributes_defined() {
141 // Verify all span attributes are properly defined
142 assert_eq!(span_attributes::MCP_METHOD, "mcp.method");
143 assert_eq!(span_attributes::MCP_TOOL_NAME, "mcp.tool.name");
144 assert_eq!(span_attributes::MCP_RESOURCE_URI, "mcp.resource.uri");
145 assert_eq!(span_attributes::MCP_SESSION_ID, "mcp.session.id");
146 assert_eq!(span_attributes::MCP_TRANSPORT, "mcp.transport");
147 }
148}