o
    i                     @   s   d Z ddlmZmZ ddlmZmZ ddlmZm	Z	m
Z
mZmZmZ ddlmZ ddlmZ ddlmZmZ ddlmZ G d	d
 d
eZG dd deZdS )zDebug logging observer for frame activity monitoring.

This module provides a debug observer that logs detailed frame activity
to the console, making it useful for debugging pipeline behavior and
understanding frame flow between processors.
    )fieldsis_dataclass)Enumauto)DictOptionalSetTupleTypeUnion)logger)Frame)BaseObserverFramePushed)FrameDirectionc                   @   s   e Zd ZdZe Ze ZdS )FrameEndpointzSpecifies which endpoint (source or destination) to filter on.

    Parameters:
        SOURCE: Filter on the source component that is pushing the frame.
        DESTINATION: Filter on the destination component receiving the frame.
    N)__name__
__module____qualname____doc__r   SOURCEDESTINATION r   r   `/home/ubuntu/.local/lib/python3.10/site-packages/pipecat/observers/loggers/debug_log_observer.pyr      s    
r   c                       s   e Zd ZdZ		ddeeeee df e	ee eeee
f  f f  deee  f fddZdd	 Zd
d ZdefddZ  ZS )DebugLogObserveram  Observer that logs frame activity with detailed content to the console.

    Automatically extracts and formats data from any frame type, making it useful
    for debugging pipeline behavior without needing frame-specific observers.

    Examples:
        Log all frames from all services::

            observers = DebugLogObserver()

        Log specific frame types from any source/destination::

            from pipecat.frames.frames import LLMTextFrame, TranscriptionFrame
            observers=[
                DebugLogObserver(frame_types=(LLMTextFrame,TranscriptionFrame,)),
            ]

        Log frames with specific source/destination filters::

            from pipecat.frames.frames import InterruptionFrame, UserStartedSpeakingFrame, LLMTextFrame
            from pipecat.observers.loggers.debug_log_observer import DebugLogObserver, FrameEndpoint
            from pipecat.transports.base_output import BaseOutputTransport
            from pipecat.services.stt_service import STTService

            observers=[
                DebugLogObserver(
                    frame_types={
                        # Only log InterruptionFrame when source is BaseOutputTransport
                        InterruptionFrame: (BaseOutputTransport, FrameEndpoint.SOURCE),
                        # Only log UserStartedSpeakingFrame when destination is STTService
                        UserStartedSpeakingFrame: (STTService, FrameEndpoint.DESTINATION),
                        # Log LLMTextFrame regardless of source or destination type
                        LLMTextFrame: None,
                    }
                ),
            ]
    Nframe_types.exclude_fieldsc                    sb   t  jdi | i | _|dur!t|trdd |D | _n|| _|dur*|| _dS h d| _dS )a  Initialize the debug log observer.

        Args:
            frame_types: Frame types to log. Can be:

                - Tuple of frame types to log all instances
                - Dict mapping frame types to filter configurations
                - None to log all frames

                Filter configurations can be None (log all instances) or a tuple
                of (service_type, endpoint) to filter on specific services.
            exclude_fields: Field names to exclude from logging. Defaults to
                excluding binary data fields like 'audio', 'image', 'images'.
            **kwargs: Additional arguments passed to parent class.
        Nc                 S   s   i | ]}|d qS )Nr   ).0
frame_typer   r   r   
<dictcomp>k   s    z-DebugLogObserver.__init__.<locals>.<dictcomp>>   audioimageimagesr   )super__init__frame_filters
isinstancetupler   )selfr   r   kwargs	__class__r   r   r$   L   s   
zDebugLogObserver.__init__c                 C   s   |du rdS t |tr|S t |ttfr5t|dkrdS t |d tr1t|dkr1t| dS t|S t |ttfrCt| dS t|drZt	t
|drZ|jj d	|  S t|S )
zFormat a value for logging.NNoner   z[]   z itemsz bytesget_messages_for_loggingz with messages: )r&   strlistr'   lendictbytes	bytearrayhasattrcallablegetattrr+   r   r.   )r(   valuer   r   r   _format_value{   s"   
zDebugLogObserver._format_valuec                 C   sr   | j sdS | j  D ],\}}t||r6|du r dS |\}}|tjkr*t||  S |tjkr6t||  S q
dS )z7Determine if a frame should be logged based on filters.TNF)r%   itemsr&   r   r   r   )r(   framesrcdstr   filter_configservice_typeendpointr   r   r   _should_log_frame   s   


z"DebugLogObserver._should_log_framedatac              	      s  |j }|j}|j}|j}|j}| |||sdS |tjkr dnd}|d }|jj	}	g }
t
|rYt|D ]$}|j| jv r=q4t||j}|du rHq4| |}|
|j d|  q4|
rmd|
}|	 d| d|d	d
}n	|	 d|d	d
}t| d| d| d|  dS )zProcess a frame being pushed into the pipeline.

        Logs frame details to the console with all relevant fields and values.

        Args:
            data: Event data containing the frame, source, destination, direction, and timestamp.
        Nu   →u   ←i ʚ;z: z,  z at z.2fs)sourcedestinationr;   	direction	timestamprA   r   
DOWNSTREAMr+   r   r   r   namer   r7   r9   appendjoinr   debug)r(   rB   r<   r=   r;   rG   rH   arrowtime_sec
class_nameframe_detailsfieldr8   formatted_valuedetailsmessager   r   r   on_push_frame   s4   

$zDebugLogObserver.on_push_frame)NN)r   r   r   r   r   r   r	   r
   r   r   r   r   r/   r$   r9   rA   r   rV   __classcell__r   r   r*   r   r   %   s    *.
/r   N)r   dataclassesr   r   enumr   r   typingr   r   r   r	   r
   r   logurur   pipecat.frames.framesr   pipecat.observers.base_observerr   r   "pipecat.processors.frame_processorr   r   r   r   r   r   r   <module>   s    