o
    i                     @   s   d Z ddlZddlmZ ddlmZ ddlmZ ddlmZ ddlm	Z	 dd	l
mZ eeZG d
d dZG dd dee ZdS )a  
This files implements the subscribers models for ``core.dispatch_event`` and ``core.context_with_event``.

Subscribers are meant to replace ``core.on()`` by automatically register hook for events registered in
event_names attribute.

Subscriber class automatically register hook for the name of the events stored in event_names attribute.
ContextSubscriber class automatically register hooks for context.started.event_name and context.ended.event_name
with event_name being the name of the events stored in event_names attribute.

Subscribers also allow to compose hook capabilities: you can specialized a Subscriber by inheriting it.

Finally, subscribers can listen to multiple event names to allow integration specific events that wants to trigger
the same subscriber.
    N)TracebackType)Generic)Optional)Sequence)core   )	EventTypec                       sR   e Zd ZU dZee ed< dZeed<  fddZ	e
dd Ze
d	d
 Z  ZS )
Subscriberax  Base class for event subscribers.

    Subclasses that define ``event_names`` automatically register themselves to handle those events.
    This provides a clean pattern for handling events from the Events API (Event class).

    The subscriber pattern automatically:
    - Registers the subscriber when the class is defined
    - Collects all ``on_event`` methods from the inheritance chain and calls them in order (parent to child)

    Example:
        @dataclass
        class MyEvent(Event):
            event_name = "my.event"
            data: str

        class MySubscriber(Subscriber):
            event_names = ("my.event",)

            @classmethod
            def on_event(cls, event_instance):
                print(f"Received: {event_instance.data}")

        # Subscriber is automatically registered, just dispatch:
        core.dispatch_event(MyEvent(data="hello"))
    event_names _event_handlersc                    sv   t  jdi | tdd t| jdd D | _d| jvr(td| j	 dS | j
D ]}tj|| j| j	 d q+dS )	Automatically register listeners at subclass definition.
        Handlers are registered from Base class to Children classes to allow
        behavior composition (a child class benefit from the parent class hook)
        c                 s   s2    | ]}t |trd |jv r|tur|jV  qdS )on_eventN)
issubclassr	   __dict__r   .0base_clsr   r   T/home/ubuntu/.local/lib/python3.10/site-packages/ddtrace/internal/core/subscriber.py	<genexpr>D   s    z/Subscriber.__init_subclass__.<locals>.<genexpr>Nr
   NSubscriber class %s does not define 'event_names' and will not be registered. namer   )super__init_subclass__tuplereversed__mro__r   r   logdebug__name__r
   r   on	_on_eventclskwargs
event_name	__class__r   r   r   =   s   


zSubscriber.__init_subclass__c                 C      dS )zOverride this method in child classes to handle the event.

        Args:
            event_instance: The Event instance that was dispatched
        Nr   )r%   event_instancer   r   r   r   W      zSubscriber.on_eventc                 C      | j D ]}|| qdS )zIInternal handler that calls all _on_event methods from parent to childrenN)r   )r%   r+   handlerr   r   r   r#   `      

zSubscriber._on_event)r!   
__module____qualname____doc__r   str__annotations__r   r   r   classmethodr   r#   __classcell__r   r   r(   r   r	      s   
 
r	   c                	       s   e Zd ZU dZee ed< dZeed< dZ	eed<  fddZ
edeje fd	d
Zedeje deee ee ee f fddZedeje ddfddZedeje deee ee ee f ddfddZ  ZS )ContextSubscribera  Base class for context event subscribers.

    Subclasses that define ``event_names`` automatically register themselves to handle context lifecycle events:
    - ``context.started.{event_name}`` when the context begins
    - ``context.ended.{event_name}`` when the context ends

    Example:
        @dataclass
        class MyContextEvent(ContextEvent):
            event_name = "my.context"

            user_id: str = event_field()

        class MyContextSubscriber(ContextSubscriber):
            event_names = ("my.context",)

            @classmethod
            def on_started(cls, ctx):
                user_id = ctx.get_item("user_id")
                print(f"Context started for user {user_id}")

            @classmethod
            def on_ended(cls, ctx, exc_info):
                if exc_info[1]:
                    print(f"Context ended with error: {exc_info[1]}")

        with core.context_with_event(MyContextEvent(url="/api", user_id="123")):
            pass
    r
   r   _started_handlers_ended_handlersc                    s   t  jdi | tdd t| jdd D | _tdd t| jdd D | _d| jvr9t	d| j
 dS | jD ]"}tjd| | j| j
 d	d
 tjd| | j| j
 dd
 q<dS )r   c                 s   2    | ]}t |trd |jv r|tur|jV  qdS )
on_startedN)r   r7   r   r;   r   r   r   r   r          
z6ContextSubscriber.__init_subclass__.<locals>.<genexpr>Nr   c                 s   r:   )on_endedN)r   r7   r   r=   r   r   r   r   r      r<   r
   r   zcontext.started.z.startedr   zcontext.ended.z.endedr   )r   r   r   r   r   r8   r9   r   r   r    r!   r
   r   r"   _on_context_started_on_context_endedr$   r(   r   r   r      s,   






z#ContextSubscriber.__init_subclass__ctxc                 C   r*   )zOverride this method in child classes to handle context start events.

        Args:
            ctx: The ExecutionContext instance
        Nr   )r%   r@   r   r   r   r;      r,   zContextSubscriber.on_startedexc_infoc                 C   r*   )zOverride this method in child classes to handle context end events.

        Args:
            ctx: The ExecutionContext instance
            exc_info: Tuple of (exception_type, exception_value, traceback) or (None, None, None)
        Nr   )r%   r@   rA   r   r   r   r=      s   zContextSubscriber.on_endedreturnNc                 C   r-   )zSInternal handler that calls all _on_context_started methods from parent to childrenN)r8   )r%   r@   r.   r   r   r   r>      r/   z%ContextSubscriber._on_context_startedc                 C   s   | j D ]}||| qdS )zQInternal handler that calls all _on_context_ended methods from parent to childrenN)r9   )r%   r@   rA   r.   r   r   r   r?      s   
z#ContextSubscriber._on_context_ended)r!   r0   r1   r2   r   r3   r4   r8   r   r9   r   r5   r   ExecutionContextr   r;   r   typeBaseExceptionr   r=   r>   r?   r6   r   r   r(   r   r7   g   s0   
 )r7   )r2   loggingtypesr   typingr   r   r   ddtrace.internalr   eventsr   	getLoggerr!   r   r	   r7   r   r   r   r   <module>   s    
H