o
    i4                     @   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 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edddd dd Z G dd dej!Z"G dd de"Z#G dd  d ej!Z$d!d" Z%d#d$ Z&dS )%z
Generic dbapi tracing code.
    N)config)core)	COMPONENT)
get_logger)ArgumentError)get_argument_value)tracer   )Pin)_SPAN_MEASURED_KEY)	SPAN_KIND)SpanKind)	SpanTypes)db)sql   )ext_service)	iswrappeddbapi2r   r   )_default_service_dbapi_span_name_prefixtrace_fetch_methodsc                   C   s   dS )N  r   r   r   I/home/ubuntu/.local/lib/python3.10/site-packages/ddtrace/contrib/dbapi.pyget_version'   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  ZS )TracedCursorz8TracedCursor wraps a psql cursor and traces its queries.c                    s   t t| | ||  |rd|v r|d ntjd }|r&d|v r&|d nd|}|| _d | _|p5tj| _	t
| j	dd | _d S )Nr   _dbapi_span_operation_namez{}.query_dbm_propagator)superr   __init__ontor   r   format_self_datadog_name_self_last_execute_operation_self_configgetattr_self_dbm_propagator)selfcursorpincfgspan_name_prefix	span_name	__class__r   r   r    /   s$   
zTracedCursor.__init__c                 C   
   | j  S N)__wrapped____iter__r(   r   r   r   r3   B      
zTracedCursor.__iter__c                 C   r0   r1   )r2   __next__r4   r   r   r   r6   E   r5   zTracedCursor.__next__c              
   O   s(  t | }|r| s||i |S || jk}	tj|t|| j|tj	de}
|	r.|

td |
|j |
| |
t| jj |
ttj td||| jj|f |rot| jj d| j|
||fj}|ro|j\}
}}z||i |W | |
 W  d   S | |
 w 1 sw   Y  dS )a  
        Internal function to trace the call to the underlying cursor method
        :param method: The callable to be wrapped
        :param name: The name of the resulting span.
        :param resource: The sql query. Sql queries are obfuscated on the agent side.
        :param extra_tags: A dict of tags to store into the span's meta
        :param dbm_propagator: _DBM_Propagator, prepends dbm comments to sql statements
        :param args: The args that will be passed as positional args to the wrapped method
        :param kwargs: The args that will be passed as kwargs to the wrapped method
        :return: The result of the wrapped method invocation
        )serviceresource	span_typer   db_query_checkz.executeN)r
   get_fromenabledr#   r   tracer   r%   r   SQL
set_metricr   set_tagstags_set_tag_strr   integration_namer   r   CLIENTr   dispatchdispatch_with_resultsresultvalue_set_post_execute_tags)r(   methodnamer8   
extra_tagsdbm_propagatorargskwargsr*   measuredsrG   r   r   r   _trace_methodH   s:   



 zTracedCursor._trace_methodc                 O   sH   || _ td| |||f | j| jj| j|ddi| j|g|R i |S )z#Wraps the cursor.executemany methodasm.block.dbapi.executezsql.executemanytrue)r$   r   rE   rR   r2   executemanyr#   r'   r(   queryrN   rO   r   r   r   rU   {   s   zTracedCursor.executemanyc                 O   sD   || _ td| |||f | j| jj| j|i | j|g|R i |S )zWraps the cursor.execute methodrS   )r$   r   rE   rR   r2   executer#   r'   rV   r   r   r   rX      s   zTracedCursor.executec                 G   s(   || _ | j| jj| j|i d|g|R  S )z Wraps the cursor.callproc methodN)r$   rR   r2   callprocr#   )r(   procrN   r   r   r   rY      s   "zTracedCursor.callprocc                 C   sT   t | jdd }|d u rd S |tj| t|tr&|dkr(|tj| d S d S d S )Nrowcountr   )r&   r2   r?   r   ROWCOUNT
isinstanceintset_tag)r(   span	row_countr   r   r   rI      s   z#TracedCursor._set_post_execute_tagsc                 C   s   | j j | S r1   )r2   	__enter__r4   r   r   r   rb      s   zTracedCursor.__enter__)__name__
__module____qualname____doc__r    r3   r6   rR   rU   rX   rY   rI   rb   __classcell__r   r   r.   r   r   ,   s    3r   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	FetchTracedCursorz
    Sub-class of :class:`TracedCursor` that also instruments `fetchone`, `fetchall`, and `fetchmany` methods.

    We do not trace these functions by default since they can get very noisy (e.g. `fetchone` with 100k rows).
    c                 O   4   d | jd}| j| jj|| ji dg|R i |S )z Wraps the cursor.fetchone method{}.{}fetchoneN)r"   r#   rR   r2   rk   r$   r(   rN   rO   r-   r   r   r   rk         zFetchTracedCursor.fetchonec                 O   ri   )z Wraps the cursor.fetchall methodrj   fetchallN)r"   r#   rR   r2   rn   r$   rl   r   r   r   rn      rm   zFetchTracedCursor.fetchallc                 O   s   d | jd}d}z|t||ddi}W n ty,   t| jdd}|r(||ini }Y nw | j| jj|| j|dg|R i |S )z!Wraps the cursor.fetchmany methodrj   	fetchmanyzdb.fetch.sizer   size	arraysizeN)	r"   r#   r   r   r&   r2   rR   ro   r$   )r(   rN   rO   r-   size_tag_keyrL   default_array_sizer   r   r   ro      s   zFetchTracedCursor.fetchmanyN)rc   rd   re   rf   rk   rn   ro   r   r   r   r   rh      s
    rh   c                       sJ   e Zd ZdZd fdd	Zdd Zdd Zd	d
 Zdd Zdd Z	  Z
S )TracedConnectionz6TracedConnection wraps a Connection with tracing code.Nc                    sh   |st j}|s|jrtnt}tt| | t|}d	|| _
|p&t|d}||  || _|| _d S )Nz{}.connectionr7   )r   r   r   rh   r   r   rt   r    _get_vendorr"   r#   r
   r!   _self_cursor_clsr%   )r(   connr*   r+   
cursor_clsrK   db_pinr.   r   r   r       s   

zTracedConnection.__init__c                 C   sb   | j  }t|dr|| j u r| S |S t|dr/t|r|S t| }|s'|S | ||| jS |S )a  Context management is not defined by the dbapi spec.

        This means unfortunately that the database clients each define their own
        implementations.

        The ones we know about are:

        - mysqlclient<2.0 which returns a cursor instance. >=2.0 returns a
          connection instance.
        - psycopg returns a connection.
        - pyodbc returns a connection.
        - pymysql doesn't implement it.
        - sqlite3 returns the connection.
        r)   rX   )r2   rb   hasattrr   r
   r;   rw   r%   )r(   rr*   r   r   r   rb      s   




zTracedConnection.__enter__c                 O   s   t | }|r| s||i |S tj|t|| jd)}|t| jj	 |t
tj ||j || ||i |W  d    S 1 sIw   Y  d S )Nru   )r
   r;   r<   r   r=   r   r%   rB   r   rC   r   r   rD   r@   rA   )r(   rJ   rK   rL   rN   rO   r*   rQ   r   r   r   rR   &  s   

$zTracedConnection._trace_methodc                 O   s6   | j j|i |}t| }|s|S | j||| jdS )N)r)   r*   r+   )r2   r)   r
   r;   rw   r%   )r(   rN   rO   r)   r*   r   r   r   r)   6  s
   
zTracedConnection.cursorc                 O   .   d | jd}| j| jj|i g|R i |S )Nrj   commit)r"   r#   rR   r2   r~   rl   r   r   r   r~   =      zTracedConnection.commitc                 O   r}   )Nrj   rollback)r"   r#   rR   r2   r   rl   r   r   r   r   A  r   zTracedConnection.rollback)NNN)rc   rd   re   rf   r    rb   rR   r)   r~   r   rg   r   r   r.   r   rt      s    *rt   c                 C   s<   zt | }W n ty   tjddd d}Y nw t|S )zGReturn the vendor (e.g postgres, mysql) of the given
    database.
    zcouldn't parse module nameT)exc_infor   )_get_module_name	Exceptionlogdebugr   normalize_vendor)rx   rK   r   r   r   rv   F  s   
rv   c                 C   s   | j jdd S )N.r   )r/   rd   split)rx   r   r   r   r   R  s   r   )'rf   wraptddtracer   ddtrace.internalr   ddtrace.internal.constantsr   ddtrace.internal.loggerr   ddtrace.internal.utilsr   r   ddtrace.tracer   
_trace.pinr
   	constantsr   r   extr   r   r   r   internal.trace_utilsr   r   rc   r   _adddictr   ObjectProxyr   rh   rt   rv   r   r   r   r   r   <module>   sD    
 '_