From 80fecab4dea32de38966e83ff71bd4438cc1c297 Mon Sep 17 00:00:00 2001 From: Radhika Gupta Date: Fri, 17 Apr 2026 14:48:36 +0530 Subject: [PATCH] Fix SentryMetrics dropping MetricsFrame from stop_ttfb/stop_processing SentryMetrics.stop_ttfb_metrics and stop_processing_metrics called the base FrameProcessorMetrics implementation but discarded its return value (implicit `return None`). FrameProcessorMetrics.stop_ttfb_metrics / stop_processing_metrics build and return a MetricsFrame, which FrameProcessor.stop_ttfb_metrics / stop_processing_metrics then pushes downstream so observers (e.g. UserBotLatencyObserver, MetricsLogObserver) can see TTFB / processing metrics. Because SentryMetrics returned None, the FrameProcessor never pushed the MetricsFrame, so any pipeline using metrics=SentryMetrics() on STT / LLM / TTS services silently lost all downstream TTFB and processing MetricsFrames. The metrics were still calculated and logged internally, and Sentry transactions still finished correctly, but observers never saw them. Forward the MetricsFrame returned by the base class so FrameProcessor can push it into the pipeline. --- changelog/4325.fixed.md | 1 + src/pipecat/processors/metrics/sentry.py | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 changelog/4325.fixed.md diff --git a/changelog/4325.fixed.md b/changelog/4325.fixed.md new file mode 100644 index 000000000..b87a97bfb --- /dev/null +++ b/changelog/4325.fixed.md @@ -0,0 +1 @@ +- Fixed `SentryMetrics` silently dropping `MetricsFrame`s from `stop_ttfb_metrics` and `stop_processing_metrics`. `SentryMetrics` called the base `FrameProcessorMetrics` implementation but discarded its return value, so `FrameProcessor` never pushed the `MetricsFrame` downstream. This prevented observers (e.g. `UserBotLatencyObserver`, `MetricsLogObserver`) from seeing TTFB and processing metrics for any service using `metrics=SentryMetrics()`. The metrics were still calculated and Sentry transactions still completed — only the downstream frame push was affected. diff --git a/src/pipecat/processors/metrics/sentry.py b/src/pipecat/processors/metrics/sentry.py index b043b9058..0484995db 100644 --- a/src/pipecat/processors/metrics/sentry.py +++ b/src/pipecat/processors/metrics/sentry.py @@ -97,13 +97,20 @@ class SentryMetrics(FrameProcessorMetrics): Args: end_time: Optional end timestamp override. + + Returns: + MetricsFrame produced by the base class, or None if not measuring. + Returning the frame is required so ``FrameProcessor.stop_ttfb_metrics`` + can push it downstream to observers. """ - await super().stop_ttfb_metrics(end_time=end_time) + frame = await super().stop_ttfb_metrics(end_time=end_time) if self._sentry_available and self._ttfb_metrics_tx: await self._sentry_queue.put(self._ttfb_metrics_tx) self._ttfb_metrics_tx = None + return frame + async def start_processing_metrics(self, *, start_time: float | None = None): """Start tracking frame processing metrics. @@ -126,13 +133,20 @@ class SentryMetrics(FrameProcessorMetrics): Args: end_time: Optional end timestamp override. + + Returns: + MetricsFrame produced by the base class, or None if not measuring. + Returning the frame is required so ``FrameProcessor.stop_processing_metrics`` + can push it downstream to observers. """ - await super().stop_processing_metrics(end_time=end_time) + frame = await super().stop_processing_metrics(end_time=end_time) if self._sentry_available and self._processing_metrics_tx: await self._sentry_queue.put(self._processing_metrics_tx) self._processing_metrics_tx = None + return frame + async def _sentry_task_handler(self): """Background task handler for completing Sentry transactions.""" running = True