Fix type errors in observers and add to pyright checked set
Group three co-assigned fields (_start_frame_id, _start_frame_arrival_ns, _start_wall_clock) into a single _StartFrameInfo dataclass. This makes the "always set together" invariant structural rather than implicit, and fixes the incorrect str | None annotation on _start_frame_id (Frame.id is int).
This commit is contained in:
@@ -6,7 +6,8 @@
|
|||||||
"src/pipecat/clocks",
|
"src/pipecat/clocks",
|
||||||
"src/pipecat/metrics",
|
"src/pipecat/metrics",
|
||||||
"src/pipecat/transcriptions",
|
"src/pipecat/transcriptions",
|
||||||
"src/pipecat/frames"
|
"src/pipecat/frames",
|
||||||
|
"src/pipecat/observers"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"**/*_pb2.py",
|
"**/*_pb2.py",
|
||||||
|
|||||||
@@ -49,6 +49,15 @@ from pipecat.processors.frame_processor import FrameProcessor
|
|||||||
_INTERNAL_TYPES = (PipelineSource, BasePipeline)
|
_INTERNAL_TYPES = (PipelineSource, BasePipeline)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class _StartFrameInfo:
|
||||||
|
"""Captured once when the first StartFrame arrives at a processor."""
|
||||||
|
|
||||||
|
frame_id: int
|
||||||
|
arrival_ns: int
|
||||||
|
wall_clock: float
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class _ArrivalInfo:
|
class _ArrivalInfo:
|
||||||
"""Internal record of when a StartFrame arrived at a processor."""
|
"""Internal record of when a StartFrame arrived at a processor."""
|
||||||
@@ -175,8 +184,8 @@ class StartupTimingObserver(BaseObserver):
|
|||||||
# Collected timings in pipeline order.
|
# Collected timings in pipeline order.
|
||||||
self._timings: list[ProcessorStartupTiming] = []
|
self._timings: list[ProcessorStartupTiming] = []
|
||||||
|
|
||||||
# Lock onto the first StartFrame we see (by frame ID).
|
# Captured once when the first StartFrame arrives.
|
||||||
self._start_frame_id: str | None = None
|
self._start_frame: _StartFrameInfo | None = None
|
||||||
|
|
||||||
# Whether we've already emitted the startup timing report.
|
# Whether we've already emitted the startup timing report.
|
||||||
self._startup_timing_reported = False
|
self._startup_timing_reported = False
|
||||||
@@ -184,15 +193,9 @@ class StartupTimingObserver(BaseObserver):
|
|||||||
# Whether we've already measured transport timing.
|
# Whether we've already measured transport timing.
|
||||||
self._transport_timing_reported = False
|
self._transport_timing_reported = False
|
||||||
|
|
||||||
# Timestamp (ns) when we first see a StartFrame arrive at a processor.
|
|
||||||
self._start_frame_arrival_ns: int | None = None
|
|
||||||
|
|
||||||
# Bot connected timing (stored for inclusion in the transport report).
|
# Bot connected timing (stored for inclusion in the transport report).
|
||||||
self._bot_connected_secs: float | None = None
|
self._bot_connected_secs: float | None = None
|
||||||
|
|
||||||
# Wall clock time when the StartFrame was first seen.
|
|
||||||
self._start_wall_clock: float | None = None
|
|
||||||
|
|
||||||
self._register_event_handler("on_startup_timing_report")
|
self._register_event_handler("on_startup_timing_report")
|
||||||
self._register_event_handler("on_transport_timing_report")
|
self._register_event_handler("on_transport_timing_report")
|
||||||
|
|
||||||
@@ -233,11 +236,13 @@ class StartupTimingObserver(BaseObserver):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Lock onto the first StartFrame.
|
# Lock onto the first StartFrame.
|
||||||
if self._start_frame_id is None:
|
if self._start_frame is None:
|
||||||
self._start_frame_id = data.frame.id
|
self._start_frame = _StartFrameInfo(
|
||||||
self._start_frame_arrival_ns = data.timestamp
|
frame_id=data.frame.id,
|
||||||
self._start_wall_clock = time.time()
|
arrival_ns=data.timestamp,
|
||||||
elif data.frame.id != self._start_frame_id:
|
wall_clock=time.time(),
|
||||||
|
)
|
||||||
|
elif data.frame.id != self._start_frame.frame_id:
|
||||||
return
|
return
|
||||||
|
|
||||||
if self._should_track(data.processor):
|
if self._should_track(data.processor):
|
||||||
@@ -268,16 +273,16 @@ class StartupTimingObserver(BaseObserver):
|
|||||||
if not isinstance(data.frame, StartFrame):
|
if not isinstance(data.frame, StartFrame):
|
||||||
return
|
return
|
||||||
|
|
||||||
if self._start_frame_id is not None and data.frame.id != self._start_frame_id:
|
if self._start_frame is not None and data.frame.id != self._start_frame.frame_id:
|
||||||
return
|
return
|
||||||
|
|
||||||
arrival = self._arrivals.pop(data.source.id, None)
|
arrival = self._arrivals.pop(data.source.id, None)
|
||||||
if arrival is None:
|
if arrival is None or self._start_frame is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
duration_ns = data.timestamp - arrival.arrival_ts_ns
|
duration_ns = data.timestamp - arrival.arrival_ts_ns
|
||||||
duration_secs = duration_ns / 1e9
|
duration_secs = duration_ns / 1e9
|
||||||
start_offset_secs = (arrival.arrival_ts_ns - self._start_frame_arrival_ns) / 1e9
|
start_offset_secs = (arrival.arrival_ts_ns - self._start_frame.arrival_ns) / 1e9
|
||||||
|
|
||||||
self._timings.append(
|
self._timings.append(
|
||||||
ProcessorStartupTiming(
|
ProcessorStartupTiming(
|
||||||
@@ -289,22 +294,22 @@ class StartupTimingObserver(BaseObserver):
|
|||||||
|
|
||||||
def _handle_bot_connected(self, data: FramePushed):
|
def _handle_bot_connected(self, data: FramePushed):
|
||||||
"""Record bot connected timing on first BotConnectedFrame."""
|
"""Record bot connected timing on first BotConnectedFrame."""
|
||||||
if self._bot_connected_secs is not None or self._start_frame_arrival_ns is None:
|
if self._bot_connected_secs is not None or self._start_frame is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
delta_ns = data.timestamp - self._start_frame_arrival_ns
|
delta_ns = data.timestamp - self._start_frame.arrival_ns
|
||||||
self._bot_connected_secs = delta_ns / 1e9
|
self._bot_connected_secs = delta_ns / 1e9
|
||||||
|
|
||||||
async def _handle_client_connected(self, data: FramePushed):
|
async def _handle_client_connected(self, data: FramePushed):
|
||||||
"""Emit transport timing report on first ClientConnectedFrame."""
|
"""Emit transport timing report on first ClientConnectedFrame."""
|
||||||
if self._transport_timing_reported or self._start_frame_arrival_ns is None:
|
if self._transport_timing_reported or self._start_frame is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
self._transport_timing_reported = True
|
self._transport_timing_reported = True
|
||||||
delta_ns = data.timestamp - self._start_frame_arrival_ns
|
delta_ns = data.timestamp - self._start_frame.arrival_ns
|
||||||
client_connected_secs = delta_ns / 1e9
|
client_connected_secs = delta_ns / 1e9
|
||||||
report = TransportTimingReport(
|
report = TransportTimingReport(
|
||||||
start_time=self._start_wall_clock or 0.0,
|
start_time=self._start_frame.wall_clock,
|
||||||
bot_connected_secs=self._bot_connected_secs,
|
bot_connected_secs=self._bot_connected_secs,
|
||||||
client_connected_secs=client_connected_secs,
|
client_connected_secs=client_connected_secs,
|
||||||
)
|
)
|
||||||
@@ -319,7 +324,7 @@ class StartupTimingObserver(BaseObserver):
|
|||||||
total = sum(t.duration_secs for t in self._timings)
|
total = sum(t.duration_secs for t in self._timings)
|
||||||
|
|
||||||
report = StartupTimingReport(
|
report = StartupTimingReport(
|
||||||
start_time=self._start_wall_clock or 0.0,
|
start_time=self._start_frame.wall_clock if self._start_frame else 0.0,
|
||||||
total_duration_secs=total,
|
total_duration_secs=total,
|
||||||
processor_timings=self._timings,
|
processor_timings=self._timings,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user