o
    i/                  	   @   s  d dl Z d dlZ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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 dl#m$Z$ d dl%m&Z& d dl'm(Z( e"e)Z*e+dde&e j,dddi eZ-e	Z.G dd dej/Z0G d d! d!e0Z1G d"d# d#e0Z2e1e._3d$d% Z4d&d' Z5d(d) Z6dS )*    N)Iterable)Client)PooledClient)
HashClient)MemcacheClientError)MemcacheIllegalInputError)MemcacheServerError)MemcacheUnknownCommandError)MemcacheUnknownError)config)Pin)_SPAN_MEASURED_KEY)	SPAN_KIND)SpanKind)	SpanTypes)db)	memcached)net)	COMPONENT)
get_logger)schematize_cache_operation)asbool)tracer
pymemcachecommand_enabled"DD_TRACE_MEMCACHED_COMMAND_ENABLEDF)defaultc                       s$   e Zd Z fddZdd Z  ZS )_WrapperBasec                    s`   ||i |}t t| | t|i |}tt}|r$|j|d}nt|d}||  d S )N)tags)	superr   __init___get_address_tagsr   get_fromr   cloneonto)selfwrapped_classargskwargscr   
parent_pinpin	__class__ ^/home/ubuntu/.local/lib/python3.10/site-packages/ddtrace/contrib/internal/pymemcache/client.pyr    4   s   

z_WrapperBase.__init__c                 O   s>   t | }|r| s||i |S t|||g|R i |S N)r   r"   enabled_trace)r%   funccmdr'   r(   pr.   r.   r/   _trace_function_as_commandE   s   
z'_WrapperBase._trace_function_as_command)__name__
__module____qualname__r    r6   __classcell__r.   r.   r,   r/   r   3   s    r   c                       s   e Zd ZdZ fddZdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ Zd0d1 Z  ZS )2WrappedClientzWrapper providing patched methods of a pymemcache Client.

    Relevant connection information is obtained during initialization and
    attached to each span.

    Keys are tagged in spans for methods that act upon a key.
    c                    "   t t| jtg|R i | d S r0   )r   r;   r    _Clientr%   r'   r(   r,   r.   r/   r    W      "zWrappedClient.__init__c                 O      | j dg|R i |S )Nset_traced_cmdr>   r.   r.   r/   rA   Z      zWrappedClient.setc                 O   r@   )Nset_manyrB   r>   r.   r.   r/   rE   ]   rD   zWrappedClient.set_manyc                 O   r@   )NaddrB   r>   r.   r.   r/   rF   `   rD   zWrappedClient.addc                 O   r@   )NreplacerB   r>   r.   r.   r/   rG   c   rD   zWrappedClient.replacec                 O   r@   )NappendrB   r>   r.   r.   r/   rH   f   rD   zWrappedClient.appendc                 O   r@   )NprependrB   r>   r.   r.   r/   rI   i   rD   zWrappedClient.prependc                 O   r@   )NcasrB   r>   r.   r.   r/   rJ   l   rD   zWrappedClient.casc                 O   r@   NgetrB   r>   r.   r.   r/   rL   o   rD   zWrappedClient.getc                 O   r@   )Nget_manyrB   r>   r.   r.   r/   rM   r   rD   zWrappedClient.get_manyc                 O   r@   NgetsrB   r>   r.   r.   r/   rO   u   rD   zWrappedClient.getsc                 O   r@   )N	gets_manyrB   r>   r.   r.   r/   rP   x   rD   zWrappedClient.gets_manyc                 O   r@   )NdeleterB   r>   r.   r.   r/   rQ   {   rD   zWrappedClient.deletec                 O   r@   )Ndelete_manyrB   r>   r.   r.   r/   rR   ~   rD   zWrappedClient.delete_manyc                 O   r@   )NincrrB   r>   r.   r.   r/   rS      rD   zWrappedClient.incrc                 O   r@   )NdecrrB   r>   r.   r.   r/   rT      rD   zWrappedClient.decrc                 O   r@   )NtouchrB   r>   r.   r.   r/   rU      rD   zWrappedClient.touchc                 O   r@   )NstatsrB   r>   r.   r.   r/   rV      rD   zWrappedClient.statsc                 O   r@   )NversionrB   r>   r.   r.   r/   rW      rD   zWrappedClient.versionc                 O   r@   )N	flush_allrB   r>   r.   r.   r/   rX      rD   zWrappedClient.flush_allc                 O   r@   )NquitrB   r>   r.   r.   r/   rY      rD   zWrappedClient.quitc                 O   r@   )"set_multi is an alias for set_manyrE   rB   r>   r.   r.   r/   	set_multi      zWrappedClient.set_multic                 O   r@   )rZ   rM   rB   r>   r.   r.   r/   	get_multi   r\   zWrappedClient.get_multic                    s$   j  fdd g|R i |S )Nc                     s   t j | i |S r0   )getattr__wrapped___args_kwargscommandr%   r.   r/   <lambda>   s    z+WrappedClient._traced_cmd.<locals>.<lambda>)r6   )r%   rd   r'   r(   r.   rc   r/   rC      s   zWrappedClient._traced_cmd)r7   r8   r9   __doc__r    rA   rE   rF   rG   rH   rI   rJ   rL   rM   rO   rP   rQ   rR   rS   rT   rU   rV   rW   rX   rY   r[   r]   rC   r:   r.   r.   r,   r/   r;   N   s4    r;   c                       s   e Zd ZdZdd Z fddZdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Z  ZS ) WrappedHashClienta  Wrapper that traces HashClient commands

    This wrapper proxies its command invocations to the underlying HashClient instance.
    When the use_pooling setting is in use, this wrapper starts a span before
    doing the proxy call.

    This is necessary because the use_pooling setting causes Client instances to be
    created and destroyed dynamically in a manner that isn't affected by the
    patch() function.
    c                 O   sP   |  |}t|tr| j||||g|R i |S t| j||g|R i |S )aJ  
        PooledClient creates Client instances dynamically on request, which means
        those Client instances aren't affected by the wrappers applied in patch().
        We handle this case here by calling trace() before running the command,
        specifically when the client that will be used for the command is a
        PooledClient.

        To avoid double-tracing when the key's client is not a PooledClient, we
        don't create a span and instead rely on patch(). In this case the
        underlying Client instance is long-lived and has been patched already.
        )_get_client
isinstancer   rC   r^   r_   )r%   r4   keydefault_valr'   r(   client_for_keyr.   r.   r/   _ensure_traced   s   

z WrappedHashClient._ensure_tracedc                    r<   r0   )r   rg   r    _HashClientr>   r,   r.   r/   r       r?   zWrappedHashClient.__init__c                 O      | j d|dg|R i |S )NrA   Frm   r%   rj   r'   r(   r.   r.   r/   rA         zWrappedHashClient.setc                 O   ro   )NrF   Frp   rq   r.   r.   r/   rF      rr   zWrappedHashClient.addc                 O   ro   )NrG   Frp   rq   r.   r.   r/   rG      rr   zWrappedHashClient.replacec                 O   ro   )NrH   Frp   rq   r.   r.   r/   rH      rr   zWrappedHashClient.appendc                 O   ro   )NrI   Frp   rq   r.   r.   r/   rI      rr   zWrappedHashClient.prependc                 O   ro   )NrJ   Frp   rq   r.   r.   r/   rJ      rr   zWrappedHashClient.casc                 O      | j d|d g|R i |S rK   rp   rq   r.   r.   r/   rL      rr   zWrappedHashClient.getc                 O   rs   rN   rp   rq   r.   r.   r/   rO      rr   zWrappedHashClient.getsc                 O   ro   )NrQ   Frp   rq   r.   r.   r/   rQ      rr   zWrappedHashClient.deletec                 O   ro   )NrS   Frp   rq   r.   r.   r/   rS      rr   zWrappedHashClient.incrc                 O   ro   )NrT   Frp   rq   r.   r.   r/   rT      rr   zWrappedHashClient.decrc                 O   ro   )NrU   Frp   rq   r.   r.   r/   rU      rr   zWrappedHashClient.touchc                    sH    d u rS t |}|d| j fddg|R i |S )Nr   c                     s"   j  t g| R i |S r0   )_safely_run_funcr^   r`   clientrd   rk   r%   r.   r/   re      s    z/WrappedHashClient._traced_cmd.<locals>.<lambda>)listinsertr6   )r%   rd   rv   rj   rk   r'   r(   r.   ru   r/   rC      s   zWrappedHashClient._traced_cmd)r7   r8   r9   rf   rm   r    rA   rF   rG   rH   rI   rJ   rL   rO   rQ   rS   rT   rU   rC   r:   r.   r.   r,   r/   rg      s"    rg   c                  O   sb   i }zt | r| d \}}||tj< ||tj< ||tj< W |S W |S  ty0   td Y |S w )zDAttempt to get host and port from args passed to Client initializer.r   z$Error collecting client address tags)lenr   TARGET_HOSTTARGET_PORTSERVER_ADDRESS	Exceptionlogdebug)r'   r(   r   hostportr.   r.   r/   r!      s   

r!   c                 C   s   d}| s|S | d }t |tu rt|}t |tu r|}|S t |tu r*| }|S t |tu rRt|rRt |d tu rCd|}|S t |d tu rRd| }|S )zReturn the query values given the arguments to a pymemcache command.

    If there are multiple query values, they are joined together
    space-separated.
     r        )typedictrw   strbytesdecodery   join)r'   keysargr.   r.   r/   _get_query_string  s&   	
r   c                 O   s  t jttjdd|j|tjd}|t	t
jj |tjtj |ttj |td z"||j t
jjrOt|}d||rDdnd|}|tj| W n ty^   td Y nw zR| |i |}|d	kso|d
kr|tj|rt|t rt!dd |D nd n!|dkr|tj|rdnd n|dkr|tj|d rdnd |W W  d   S  t"t#t$t%t&fy   t'( \}	}
}|)|	|
|  w 1 sw   Y  dS )zRun and trace the given command.

    Any pymemcache exception is caught and span error information is
    set. The exception is then reraised for the application to handle
    appropriately.

    Relevant tags are set in the span.
    r   )cache_provider)serviceresource	span_type   z{}{}{}r   r   z&Error setting relevant pymemcache tagsrM   rP   c                 s   s    | ]}|rd V  qdS )r   Nr.   ).0docr.   r.   r/   	<genexpr>W  s    z_trace.<locals>.<genexpr>r   rL   rO   N)*r   tracer   
memcachedxCMDr   r   CACHE_set_tag_strr   r   r   integration_namer   SYSTEM	DBMS_NAMEr   r   CLIENT
set_metricr   set_tagsr   r   r   formatQUERYr}   r~   r   ROWCOUNTri   r   sumr   r   r	   r
   r   sysexc_infoset_exc_info)r3   r5   method_namer'   r(   spanvalsqueryresulttypvaltbr.   r.   r/   r2   -  sZ   	&*
r2   )7osr   typingr   r   pymemcache.client.baser   r   pymemcache.client.hashr   pymemcache.exceptionsr   r   r   r	   r
   wraptddtracer   ddtrace._trace.pinr   ddtrace.constantsr   r   ddtrace.extr   r   r   r   r   r   ddtrace.internal.constantsr   ddtrace.internal.loggerr   ddtrace.internal.schemar   ddtrace.internal.utils.formatsr   ddtrace.tracer   r7   r~   _addgetenvr=   rn   ObjectProxyr   r;   rg   client_classr!   r   r2   r.   r.   r.   r/   <module>   sT    	VW 