
    qi                         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
e      Z G d de      Zy)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                   ,    e Zd ZdZ e       Z e       Zy)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     ^/opt/pipecat/venv/lib/python3.12/site-packages/pipecat/observers/loggers/debug_log_observer.pyr   r      s     VF&Kr   r   c                        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Zd Zd Zdefd	Z x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,
                    }
                ),
            ]
    frame_types.exclude_fieldsc                     t        |   di | i | _        |.t        |t              r|D ci c]  }|d c}| _        n|| _        ||| _        yh d| _        yc c}w )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.
        N>   audioimageimagesr   )super__init__frame_filters
isinstancetupler    )selfr   r    kwargs
frame_type	__class__s        r   r&   zDebugLogObserver.__init__L   sy    . 	"6"  "+u-IT%U:j$&6%U" &1"
 )  	 	 &Vs   
Ac                    |yt        |t              r|S t        |t        t        f      rIt	        |      dk(  ryt        |d   t
              rt	        |      dkD  rt	        |       dS t        |      S t        |t        t        f      rt	        |       dS t        |d      r>t        t        |d            r)|j                  j                   d|j                          S t        |      S )	zFormat a value for logging.Noner   z[]   z itemsz bytesget_messages_for_loggingz with messages: )r(   strlistr)   lendictbytes	bytearrayhasattrcallablegetattrr-   r   r1   )r*   values     r   _format_valuezDebugLogObserver._format_value{   s    =s#Ye}-5zQ%(D)c%j1ne*V,,u:y12%j\((U67HE56=
 oo..//?@^@^@`?abbu:r   c                    | j                   sy| j                   j                         D ]]  \  }}t        ||      s| y|\  }}|t        j                  k(  rt        ||      c S |t        j
                  k(  sQt        ||      c S  y)z7Determine if a frame should be logged based on filters.TF)r'   itemsr(   r   r   r   )r*   framesrcdstr,   filter_configservice_typeendpoints           r   _should_log_framez"DebugLogObserver._should_log_frame   s     !! *.););)A)A)C 	9%J%, ( *7&h}333%c<88!:!::%c<88	9 r   datac           	        K   |j                   }|j                  }|j                  }|j                  }|j                  }| j                  |||      sy|t        j                  k(  rdnd}|dz  }|j                  j                  }	g }
t        |      rst        |      D ]e  }|j                  | j                  v rt        ||j                        }|5| j                  |      }|
j!                  |j                   d|        g |
rdj#                  |
      }|	 d| d|d	d
}n	|	 d|d	d
}t%        j&                  | d| d| d|        yw)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	timestamprE   r   
DOWNSTREAMr-   r   r   r   namer    r:   r<   appendjoinr   debug)r*   rF   r@   rA   r?   rL   rM   arrowtime_sec
class_nameframe_detailsfieldr;   formatted_valuedetailsmessages                   r   on_push_framezDebugLogObserver.on_push_frame   sd     kk

NN	NN	 %%eS#6 #n&?&??U},__--
   	I::!4!44uzz2="&"4"4U";$$

|2o5F%GH	I ii.G#AgYd8C.BG#D#a8G 	uAeWAcU"WI67s   EE)NN)r   r   r   r   r   r   r
   r   r   r   r   r	   r2   r&   r<   rE   r   r[   __classcell__)r-   s   @r   r   r   %   s    $T -1-
%US()4UXeDR_L_F`=a0a+bbc
-

 !S*-
^..08 08r   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   <module>rd      s>    -  : :  ' E =	D 	t8| t8r   