o
    Á¿i´%  ã                   @   s  d dl m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 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efdd„Zdeeef fdd„ZG dd„ dƒZeƒ ZG dd„ dƒZG dd„ deƒZdd„ Zdd„ Z dd„ Z!dd „ Z"d!d"„ Z#dS )#é    )Úimport_moduleN)Ú	ERROR_MSG)Ú
ERROR_TYPE)Úis_cold_start)Úset_cold_start)Ú
get_logger)Úin_aws_lambda)Ú_get_config)Úget_argument_value)Úunwrap)Úwrap)ÚtracerÚreturnc                   C   s   dS )NÚ © r   r   r   ú]/home/ubuntu/.local/lib/python3.10/site-packages/ddtrace/contrib/internal/aws_lambda/patch.pyÚget_version   s   r   c                   C   s   ddiS )NÚdatadog_lambdaÚ*r   r   r   r   r   Ú_supported_versions   s   r   c                   @   s.   e Zd ZdZdd„ Zddœdd„Zdd	„ Zd
S )ÚDDLambdaLoggerz6Uses `DDLogger` to log only on cold start invocations.c                 C   s   t tƒ| _tƒ | _d S ©N)r   Ú__name__Úloggerr   ©Úselfr   r   r   Ú__init__   s   
zDDLambdaLogger.__init__T)Úexc_infoc                O   s,   | j r| jj|g|¢R d|i|¤Ž d S d S )Nr   )r   r   Úerror)r   Úmsgr   ÚargsÚkwargsr   r   r   Ú	exception    s   "ÿzDDLambdaLogger.exceptionc                 O   s(   | j r| jj|g|¢R i |¤Ž d S d S r   )r   r   Úwarning)r   r   r    r!   r   r   r   r#   $   s   ÿzDDLambdaLogger.warningN)r   Ú
__module__Ú__qualname__Ú__doc__r   r"   r#   r   r   r   r   r      s
    r   c                   @   s<   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ Zdd„ ZdS )ÚTimeoutChannelc                 C   s   d| _ || _d | _d S )NF)ÚcrashedÚcontextÚ_original_signal)r   r)   r   r   r   r   -   s   
zTimeoutChannel.__init__c                    sP   t  |¡ˆ_‡ ‡fdd„}tˆjƒrˆjˆ ksˆj|kr"t   |ˆ ¡S t   ||¡S )zä
        Returns a signal of type `sig` with function `f`, if there are
        no previously defined signals.

        Else, wraps the given signal with the previously defined one,
        so no signals are overridden.
        c                     s,   ˆj d urˆj | i |¤Ž ˆ | i |¤Ž d S r   )r*   )r    r!   ©Úfr   r   r   Úwrap_signals<   s   
z3TimeoutChannel._handle_signal.<locals>.wrap_signals)ÚsignalÚ	getsignalr*   Úcallable)r   Úsigr,   r-   r   r+   r   Ú_handle_signal2   s
   
zTimeoutChannel._handle_signalc                 C   sZ   |   tj| j¡ | j ¡ }tddtƒ}|dk rdn|}t|| d dƒ}t 	tj
|¡ d S )NÚ"DD_APM_FLUSH_DEADLINE_MILLISECONDSéd   r   iè  )r2   r.   ÚSIGALRMÚ_crash_flushr)   Úget_remaining_time_in_millisr	   ÚintÚmaxÚ	setitimerÚITIMER_REAL)r   Úremaining_time_in_millisÚapm_flush_deadlineÚremaining_time_in_secondsr   r   r   Ú_startK   s   
zTimeoutChannel._startc                 C   sh   |   ¡  d| _t ¡ }|durd|_| td¡ | td¡ nt 	d¡ t 
¡ }|dur2| ¡  dS dS )zŠ
        Tags the current root span with an Impending Timeout error.
        Finishes spans with ancestors from the current span.
        TNé   z%Datadog detected an Impending TimeoutzImpending TimeoutzVAn impending timeout was reached, but no root span was found. No error will be tagged.)Ú_remove_alarm_signalr(   r   Úcurrent_root_spanr   Ú_set_tag_strr   r   Úlogr#   Úcurrent_spanÚ_finish_with_ancestors)r   Ú_Ú__Ú	root_spanrE   r   r   r   r6   W   s   
ÿzTimeoutChannel._crash_flushc                 C   s<   t  d¡ | jdurt   t j| j¡ dS t   t jt j¡ dS )zSRemoves the handler set for the signal `SIGALRM` and restores the original handler.r   N)r.   Úalarmr*   r5   ÚSIG_DFLr   r   r   r   rA   k   s   

z#TimeoutChannel._remove_alarm_signalc                 C   s   |   ¡  d S r   )rA   r   r   r   r   Ústops   s   zTimeoutChannel.stopN)	r   r$   r%   r   r2   r?   r6   rA   rL   r   r   r   r   r'   ,   s    r'   c                   @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )ÚDatadogInstrumentationzCPatches an AWS Lambda handler function for Datadog instrumentation.c                 C   s@   || _ |  ||¡ z| j |i |¤Ž| _| jW |  ¡  S |  ¡  w r   )ÚfuncÚ_beforeÚresponseÚ_after)r   rN   r    r!   r   r   r   Ú__call__z   s   zDatadogInstrumentation.__call__c                 C   s6   t ||ddƒ}t|dƒr|| _dS t ||ddƒ| _dS )zSets the context attribute.r@   r)   r7   é   N)r
   Úhasattrr)   )r   r    r!   Ú_contextr   r   r   Ú_set_contextƒ   s   

z#DatadogInstrumentation._set_contextc                 C   s,   t ƒ  |  ||¡ t| jƒ| _| j ¡  d S r   )r   rV   r'   r)   ÚtimeoutChannelr?   )r   r    r!   r   r   r   rO   “   s   zDatadogInstrumentation._beforec                 C   s   | j js| j  ¡  d S d S r   )rW   r(   rL   r   r   r   r   rQ   š   s   ÿzDatadogInstrumentation._afterN)r   r$   r%   r&   rR   rV   rO   rQ   r   r   r   r   rM   w   s    	rM   c                 C   s   d  |  d¡¡S )z0Returns a valid modified module to get imported.Ú.ú/)ÚjoinÚsplit)Úmodule_namer   r   r   Ú_modify_module_nameŸ   s   r]   c                  C   sâ   t ddtƒ} tƒ }| du rddlm} |}|j}|||fS |  dd¡}|\}}t|ƒ}t|ƒ}	t	|	|ƒ}
t
|
ƒrmt|
ƒj}t|
tƒ oKt|
dƒoK|dk}|rS|
|	|fS t	|	|ƒ}|j}t|
tƒrht|d	ƒrh|j}|||fS td
ƒ‚)z/Returns the user AWS Lambda handler and module.ÚDD_LAMBDA_HANDLERNr   )Údatadog_lambda_wrapperrX   r@   Ú__code__ÚfunctionÚ__func__z'Handler type is not supported to patch.)r	   ÚstrrM   Údatadog_lambda.wrapperr_   rR   Úrsplitr]   r   Úgetattrr0   Útyper   Ú
isinstancerT   rb   Ú	TypeError)ÚpathÚ_datadog_instrumentationr_   Úwrapper_moduleÚwrapper_handlerÚpartsÚmod_nameÚhandler_nameÚmodified_mod_nameÚhandler_moduleÚhandlerÚ
class_nameÚis_functionÚclass_moduleÚclass_handlerr   r   r   Ú_get_handler_and_module¤   s0   







rx   c                  C   sX   t ddtƒ} | du rztdƒ W dS  ty   Y dS w |  dd¡}t|ƒdkr*dS dS )	zÀ
    Ensures that the `aws_lambda` integration can be patched.

    It checks either the user has the DD_LAMBDA_HANDLER set correctly.
    Or if the `datadog_lambda` package is installed.
    r^   Nzdatadog_lambda.wrapperFrX   r@   rS   T)r	   rc   r   Ú	Exceptionre   Úlen)rj   rn   r   r   r   Ú_has_patch_moduleÒ   s   
úÿr{   c                  C   sv   t ƒ stƒ sdS ztƒ \} }}t|ddƒrW dS t| |ƒ d|_W dS  ty,   Y dS  ty:   t 	d¡ Y dS w )zAPatches an AWS Lambda using the `datadog-lambda-py` Lambda layer.NÚ_datadog_patchFTz<Error patching handler. Timeout spans will not be generated.)
r   r{   rx   rf   r   r|   ÚAttributeErrorry   rD   r"   ©rs   rr   Úwrapperr   r   r   Úpatchæ   s   

ýr€   c                  C   sv   t ƒ stƒ sd S ztƒ \} }}t|ddƒsW d S t| |ƒ d|_W d S  ty,   Y d S  ty:   t 	d¡ Y d S w )Nr|   FzError unpatching handler.)
r   r{   rx   rf   r   r|   r}   ry   rD   r"   r~   r   r   r   Úunpatch  s   

ýr   )$Ú	importlibr   r.   Úddtrace.constantsr   r   Ú/ddtrace.contrib.internal.aws_lambda._cold_startr   r   Úddtrace.internal.loggerr   Úddtrace.internal.serverlessr   Ú!ddtrace.internal.settings._configr	   Úddtrace.internal.utilsr
   Úddtrace.internal.wrappingr   r   Úddtrace.tracer   rc   r   Údictr   r   rD   r'   ÚobjectrM   r]   rx   r{   r€   r   r   r   r   r   Ú<module>   s0    K(.