@@ -93,6 +93,13 @@ func NewHTTPMiddleware(
93
93
// to leverage the parsed MCP data.
94
94
func (m * HTTPMiddleware ) Handler (next http.Handler ) http.Handler {
95
95
return http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
96
+ // Ultimate safety net - telemetry must NEVER crash the service
97
+ defer func () {
98
+ if rec := recover (); rec != nil {
99
+ logger .Errorf ("Telemetry middleware panic (non-fatal): %v" , rec )
100
+ }
101
+ }()
102
+
96
103
ctx := r .Context ()
97
104
98
105
// Handle SSE endpoints specially - they are long-lived connections
@@ -123,7 +130,15 @@ func (m *HTTPMiddleware) Handler(next http.Handler) http.Handler {
123
130
// Create span name based on MCP method if available, otherwise use HTTP method + path
124
131
spanName := m .createSpanName (ctx , r )
125
132
ctx , span := m .tracer .Start (ctx , spanName , trace .WithSpanKind (trace .SpanKindServer ))
126
- defer span .End ()
133
+ // End span with error handling - this is where OTLP export happens
134
+ defer func () {
135
+ defer func () {
136
+ if rec := recover (); rec != nil {
137
+ logger .Debugf ("Telemetry span.End() panic (non-fatal): %v" , rec )
138
+ }
139
+ }()
140
+ span .End ()
141
+ }()
127
142
128
143
// Create a response writer wrapper to capture response details
129
144
rw := & responseWriter {
@@ -405,9 +420,16 @@ type responseWriter struct {
405
420
bytesWritten int64
406
421
}
407
422
408
- // WriteHeader captures the status code.
423
+ // WriteHeader captures the status code with panic protection .
409
424
func (rw * responseWriter ) WriteHeader (statusCode int ) {
410
425
rw .statusCode = statusCode
426
+
427
+ // Wrap the actual WriteHeader call to catch any panics (including duplicate calls)
428
+ defer func () {
429
+ if rec := recover (); rec != nil {
430
+ logger .Debugf ("WriteHeader panic recovered (non-fatal): %v" , rec )
431
+ }
432
+ }()
411
433
rw .ResponseWriter .WriteHeader (statusCode )
412
434
}
413
435
@@ -418,6 +440,13 @@ func (rw *responseWriter) Write(data []byte) (int, error) {
418
440
return n , err
419
441
}
420
442
443
+ // Flush implements http.Flusher if the underlying ResponseWriter supports it.
444
+ func (rw * responseWriter ) Flush () {
445
+ if flusher , ok := rw .ResponseWriter .(http.Flusher ); ok {
446
+ flusher .Flush ()
447
+ }
448
+ }
449
+
421
450
// recordMetrics records request metrics.
422
451
func (m * HTTPMiddleware ) recordMetrics (ctx context.Context , r * http.Request , rw * responseWriter , duration time.Duration ) {
423
452
// Get MCP method from context if available
0 commit comments