o
    i8R                     @   s6  U d Z ddlmZ ddlm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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l0m1Z2 ee3Z4e-e)dddZ5e6de7dvi deddej8d ddd!ej8d"d#dd$ej8d%d#dd&e-ej8d'd(dd)dd*e-ej8d+ddd,e-ej8d-e5 dd.e-ej8d/e5 dd0e-ej8d1e5 dd2dd3e$j9d4e$j:d5e$j;d6e$j<d7e-ej8d8d(dd9e-ej8d:d(dd;e-ej8d<d(dd=e)d>e)d?de-d@e-d@dAe-e)dBddoe-e)dCdddDe-e)dCdddEej8dFd(ddGi dHd ee&ej=Z>e&e?dI< dJe@fdKdLZAdJe7e@e@f fdMdNZBejCdOdP ZDdwdQdRZEejCdSdT ZFdxdUdVZGdWdX ZHdYZIdxdZd[ZJejCd\d] ZKejCd^d_ ZLejCd`da ZMejCdbdc ZNejCddde ZOejCdfdg ZPejCdhdi ZQdjdk ZRdldm ZSdndo ZTdpdq ZUdrds ZVdtdu ZWdS dDe-e)dCdddEej8dFd(ddGi dHd ee&ej=Z>e&e?dI< dJe@fdKdLZAdJe7e@e@f fdMdNZBejCdOdP ZDdwdQdRZEejCdSdT ZFdxdUdVZGdWdX ZHdYZIdxdZd[ZJejCd\d] ZKejCd^d_ ZLejCd`da ZMejCdbdc ZNejCddde ZOejCdfdg ZPejCdhdi ZQdjdk ZRdldm ZSdndo ZTdpdq ZUdrds ZVdtdu ZWdS )yz
The Django patching works as follows:

Django internals are instrumented via normal `patch()`.

`django.apps.registry.Apps.populate` is patched to add instrumentation for any
specific Django apps like Django Rest Framework (DRF).
    )getmro)unwrapN)cast)when_imported)config)Pin)trace_utils)_DjangoUserInfoRetriever)core)
is_wrapted	COMPONENT)
ResultType)endpoint_collection)
get_logger)schematize_service_name)schematize_url_operation)SpanDirection)IntegrationConfig)
get_config)get_argument_value)asbool)	func_name)parseDD_DJANGO_TRACING_MINIMALT)defaultdjango_default_servicecache_service_nameDD_DJANGO_CACHE_SERVICE_NAMEdatabase_service_name_prefix&DD_DJANGO_DATABASE_SERVICE_NAME_PREFIX database_service_nameDD_DJANGO_DATABASE_SERVICE_NAMEtrace_fetch_methodsDD_DJANGO_TRACE_FETCH_METHODSFdistributed_tracing_enabledinstrument_middlewareDD_DJANGO_INSTRUMENT_MIDDLEWAREinstrument_templatesDD_DJANGO_INSTRUMENT_TEMPLATESinstrument_databasesDD_DJANGO_INSTRUMENT_DATABASESinstrument_cachesDD_DJANGO_INSTRUMENT_CACHEStrace_query_stringinclude_user_nameinclude_user_emailinclude_user_logininclude_user_realname)use_handler_with_url_name_resource_format3DD_DJANGO_USE_HANDLER_WITH_URL_NAME_RESOURCE_FORMATuse_handler_resource_format%DD_DJANGO_USE_HANDLER_RESOURCE_FORMATuse_legacy_resource_format$DD_DJANGO_USE_LEGACY_RESOURCE_FORMATtrace_asgi_websocket_messages#DD_TRACE_WEBSOCKET_MESSAGES_ENABLEDDD_ASGI_TRACE_WEBSOCKET)r   modifier(asgi_websocket_messages_inherit_sampling,DD_TRACE_WEBSOCKET_MESSAGES_INHERIT_SAMPLING+DD_TRACE_WEBSOCKET_MESSAGES_SEPARATE_TRACES"websocket_messages_separate_tracesobfuscate_404_resourceDD_ASGI_OBFUSCATE_404_RESOURCEviews_tracerconfig_djangoreturnc                  C   s   dd l } | jS )Nr   )r   __version__r    rK   Y/home/ubuntu/.local/lib/python3.10/site-packages/ddtrace/contrib/internal/django/patch.pyget_versionZ   s   rM   c                   C   s   ddiS )Nr   z>=2.2.8rK   rK   rK   rK   rL   _supported_versions`   s   rN   c                 C   s  |j rtd ||i |S ||i |}|j s td |S | jj}tjrDzddlm} ||  W n t	yC   tjddd Y nw tj
rdzddlm
}	 |	|  W n t	yc   tjd	dd Y nw t|d
g }
d|
v rzddlm} ||  W |S  t	y   tjddd Y |S w |S )a  django.apps.registry.Apps.populate is the method used to populate all the apps.

    It is used as a hook to install instrumentation for 3rd party apps (like DRF).

    `populate()` works in 3 phases:

        - Phase 1: Initializes the app configs and imports the app modules.
        - Phase 2: Imports models modules for each app.
        - Phase 3: runs ready() of each app config.

    If all 3 phases successfully run then `instance.ready` will be `True`.
    z3Django instrumentation already installed, skipping.z+populate() failed skipping instrumentation.   )instrument_dbsz/Error instrumenting Django database connectionsTexc_info)r.   z!Error instrumenting Django cachesINSTALLED_APPSrest_framework)patch_restframeworkzError patching rest_framework)readylogdebugconfsettingsrG   r,   databaserP   	Exceptionr.   cachegetattrrestframeworkrU   )r   pinfuncinstanceargskwargsretrZ   rP   r.   rS   rU   rK   rK   rL   traced_populated   sB   


rf   c                    s    fdd}t || S )Nc              
      s   t tji}tjd||dB}|j. td||t| jjdr&| jjj	j
nt| f ||i |W  d    W  d    S 1 sDw   Y  W d    d S 1 sTw   Y  d S )Nzdjango.func.wrapped)	span_nameresourcetagsr`   wsgi)r   rG   integration_namer
   context_with_dataspandispatchhasattrhandlersrj   WSGIRequestobject)r   r`   ra   rb   rc   rd   ri   ctxignored_excsnamerh   rK   rL   wrapped   s"   

Rztraced_func.<locals>.wrapped)r   with_traced_module)r   rv   rh   ru   rw   rK   rt   rL   traced_func   s   ry   c           
      C   s|   ddl m} g }t| jjddr|| jjj7 }t| jjddr&|| jjj7 }|D ]}| jj	|}	||	| q(||i |S )zj
    Patches django.core.handlers.base.BaseHandler.load_middleware to instrument all
    middlewares.
    r   )wrap_middleware
MIDDLEWARENMIDDLEWARE_CLASSES)
*ddtrace.contrib.internal.django.middlewarerz   r^   rY   rZ   r{   r|   utilsmodule_loadingimport_string)
r   r`   ra   rb   rc   rd   rz   settings_middlewaremw_pathmwrK   rK   rL   traced_load_middleware   s   r   c                 C   s4   t |drtt|D ]}t| | qt| ||dS )z
    Helper to wrap Django views.

    We want to wrap all lifecycle/http method functions for every class in the MRO for this view
    __mro__path)ro   reversedr   _instrument_view)r   viewr   clsrK   rK   rL   instrument_view   s   
r   c                 C   sp   z,d| j jv r| j| j jd j} d| j jv sd| j jv r*| j| j jd jW S g W S  ty7   g  Y S w )N	view_funcrequest_method_list)__code__co_freevars__closure__indexcell_contentsr\   )r   rK   rK   rL   extract_request_method_list   s   r   )getdeletepostoptionsheadc              
   C   s  ddl m} t|s|S tdt|f t|dd}t|p |}|dur5|p)dgD ]
}tj	||dd	 q*d
}t
|p;tt
| D ]=}z)t||d}	|	rPt|	rRW qAdt||}
d|}t||t| ||
d W qA ty~   tjd||dd Y qAw t|dd}|rd}|D ]=}z)t||d}	|	rt|	rW qdt||}
d|}t||t| ||
d W q ty   tjd||dd Y qw t|s||t| dt|| jjgd}|S )zHelper to wrap Django views.rO   r~   zservice_entrypoint.patchhttp_method_namesrK   N*django.request)operation_name)setuprn   http_method_not_allowedz{0}.{1}zdjango.view.{0})rv   rh   z/Failed to instrument Django view %r function %sTrQ   response_class)renderzdjango.response.{0}z3Failed to instrument Django response %r function %sdjango.view)rh   ru   )r"   r~   callabler
   rn   r   r^   r   r   add_endpointlist_DEFAULT_METHODSr   formatr   r   wrapry   r\   rW   rX   DjangoViewProxyhttpHttp404)r   r   r   r~   r   r   methodlifecycle_methodsrv   ra   rh   op_nameresponse_clsmethodsrK   rK   rL   r      sP   

r   c           	   	   C   s   zGd}| dd}| dd}|du rt|dkr|d }d}|du r)|r)|d }|r=t|}t| ||d|d< t|}n	t| ||d|d< W n tyY   tjd	||dd
 Y nw ||i |S )zOWrapper for url path helpers to ensure all views registered as urls are traced.Fr   NrouterO   Tr   r   z*Failed to instrument Django url path %r %rrQ   )r   lenr   r   tupler\   rW   rX   )	r   r`   rw   rb   rc   rd   view_from_argsr   r   rK   rK   rL   traced_urls_path   s&   
r   c                 C   sZ   zt | | W n ty   tjd|dd Y nw ||i |}t|t| dt|dS )z8
    Wrapper for django's View.as_view class method
    z#Failed to instrument Django view %rTrQ   r   )rh   )r   r\   rW   rX   wraptFunctionWrapperry   r   )r   r`   ra   rb   rc   rd   r   rK   rK   rL   traced_as_view8  s   r   c                 C   s   ||i |}z*t ||dd}t ||dd}t ||dd}	t ||dd}
td	||||	|
f W |S  tyB   tjd
dd Y |S w )zA
    Wrapper for django's views.debug.technical_500_response
    r   requestrO   exc_type   	exc_value   tbzdjango.technical_500_responsez9Error while trying to trace Django technical 500 responseTrQ   )r   r
   rn   r\   rW   rX   )r   r`   ra   rb   rc   rd   responser   r   r   r   rK   rK   rL   traced_technical_500_responseE  s   r   c                    s<   ddl m} ddlm   fdd}|||i |t|dS )Nr   )TraceMiddlewarer   c                    s$   t ddtjd| _|  tj d S )Nr   r   )protocol	direction)r   r   INBOUNDrv   _set_tag_strrG   rk   )rm   scoper   rK   rL   django_asgi_modifier[  s   z9traced_get_asgi_application.<locals>.django_asgi_modifier)integration_configspan_modifier)ddtrace.contrib.asgir   ddtrace.internal.constantsr   rG   )r   r`   ra   rb   rc   rd   r   r   rK   r   rL   traced_get_asgi_applicationV  s   r   c           	   	   C   s   ||i | t j}|dkrd S zt||dd}t||dd}td||||t|tf W d S  ty@   tj	ddd	 Y d S w )
Ndisabledr   r   rO   userzdjango.loginz(Error while trying to trace Django loginTrQ   )

asm_config_user_event_moder   r
   rn   r	   rG   r\   rW   rX   )	r   r`   ra   rb   rc   rd   moder   r   rK   rK   rL   traced_loginb  s   "r   c           	      C   s   ||i |}t j}|dkr|S z$td||||t||dtfj}|r/|jd r2|jd W S W |S W |S  tyE   t	j
ddd Y |S w )	Nr   zdjango.auth)credentialsr   rO   z/Error while trying to trace Django authenticateTrQ   )r   r   r
   dispatch_with_resultsr	   rG   r   valuer\   rW   rX   )	r   r`   ra   rb   rc   rd   result_userr   resultrK   rK   rL   traced_authenticatep  s*   r   c                 C   s2   ||i |}t dt||||||t|f |S )Nzdjango.create_user)r
   rn   rG   r	   )r   r`   ra   rb   rc   rd   r   rK   rK   rL   patch_create_user  s
   r   c                 C   sJ   ddl m} t||dd}|D ]}t|j|jr|jj|_q| |i |S )a%  
    Django channels uses path() and re_path() to route asgi applications. This broke our initial
    assumption that
    django path/re_path/url functions only accept views. Here we unwrap ddtrace view
    instrumentation from asgi
    applications.

    Ex. ``channels.routing.URLRouter([path('', get_asgi_application())])``
    On startup ddtrace.contrib.internal.django.path.instrument_view() will wrap get_asgi_application in a
    DjangoViewProxy.
    Since get_asgi_application is not a django view callback this function will unwrap it.
    rO   r   r   routes)r"   r~   r   
isinstancecallbackr   __wrapped__)ra   rb   rc   rd   r~   r   r   rK   rK   rL   unwrap_views  s   
r   c                    sH  t    td fdd tjrtd fdd tddd  tdd	 td fd
d}td fdd} jdkrNtd fdd tjr^ddl	m
} td|j  jdk rmtd fdd  jdkr|td fdd}td fdd td fdd tddd }td  fd!d d S )"Nzdjango.apps.registryc                       t | dt S )NzApps.populate)r   r   rf   mrJ   rK   rL   <lambda>      z_patch.<locals>.<lambda>zdjango.core.handlers.basec                    r   )NzBaseHandler.load_middleware)r   r   r   r   rJ   rK   rL   r     r   zdjango.core.handlers.wsgic                 S   s   t | dtS )NzWSGIRequest.__init__)r   r   wrap_wsgi_environr   rK   rK   rL   r     s    zdjango.patchrK   c                    s   ddl m} | |  d S )NrO   )instrument_module)r   r   )r   r   rJ   rK   rL   _  s   z_patch.<locals>._zdjango.contrib.authc                    s(   t | dt  t | dt  d S )Nloginauthenticate)r   r   r   r   r   rJ   rK   rL   r        )r   rO   zdjango.core.asgic                    r   )Nget_asgi_application)r   r   r   r   rJ   rK   rL   r     r   rO   	templateszdjango.template.base)   r   r   zdjango.conf.urlsc                    r   )Nurlr   r   r   r   rJ   rK   rL   r     r   r   r   r   zdjango.urlsc                    s(   t | dt  t | dt  d S )Nr   re_pathr   r   rJ   rK   rL   r     r   zdjango.views.generic.basec                    r   )NzView.as_view)r   r   r   r   rJ   rK   rL   r     r   zdjango.views.debugc                    r   )Ntechnical_500_response)r   r   r   r   rJ   rK   rL   r     r   zchannels.routingc                 S   s>   dd l }t|dd}t|}|tdkrt| dt d S d S )Nr   rI   r"   z3.0zURLRouter.__init__)channelsr^   parse_versionr   r   r   )r   r   channels_version_strchannels_versionrK   rK   rL   r     s   zdjango.contrib.auth.modelsc                    r   )NzUserManager.create_user)r   r   r   r   rJ   rK   rL   r     r   )r   ontor   rG   r(   r
   rn   VERSIONr*   r"   r   r   )r   r   r   rK   rJ   rL   _patch  sB   






	
r   c                 C   sJ   t d| |||fj}|r|jS |jtjkr| |i |S |jr#|jd S )Nzdjango.wsgi_environ)r
   r   wrapped_resultr   response_typer   RESULT_UNDEFINED	exception)rw   	_instancerc   rd   r   rK   rK   rL   r     s   r   c                  C   s*   dd l } t| ddrd S t|  d| _d S )Nr   _datadog_patchFT)r   r^   r   r   rJ   rK   rK   rL   patch  s
   
r  c                 C   s<  t | jjjd t | jjjjd t | j	jj
d t | jjjd t | jjd t | jjjd t | jjjd t | jjjd | jd	kr[t | jd
 t | jd t | jjjjd | jj D ]}t |d qkt | jjjd tjj rddl!m"} |#| j	j ddl$m#} || | jjj d S )Npopulateload_middlewarer   staticr   r   r   r   r   r   r   as_viewcursor__getitem__rO   r   )uninstrument_module)%r   r   appsregistryAppsr
   rp   baseBaseHandlertemplateTemplaterY   urlsr  contribauthr   r   r   rX   r   r   rE   genericViewdbconnectionsallr~   ConnectionHandlerr   r   r*   r"   r   r  r   )r   connr   r  rK   rK   rL   _unpatch  s(   
r  c                  C   s*   dd l } t| ddsd S t|  d| _d S )Nr   r   F)r   r^   r  r   rJ   rK   rK   rL   unpatch  s
   
r  rK   )NN)N)X__doc__inspectr   r   ostypingr   r   wrapt.importerr   ddtracer   ddtrace._trace.pinr   ddtrace.contribr   $ddtrace.contrib.internal.django.userr	   ddtrace.internalr
   ddtrace.internal.compatr   r   r   ddtrace.internal.core.event_hubr   ddtrace.internal.endpointsr   ddtrace.internal.loggerr   ddtrace.internal.schemar   r   -ddtrace.internal.schema.span_attribute_schemar   ddtrace.internal.settings.asmr   %ddtrace.internal.settings.integrationr   ddtrace.internal.telemetryr   _get_configddtrace.internal.utilsr   ddtrace.internal.utils.formatsr    ddtrace.internal.utils.importlibr    ddtrace.vendor.packaging.versionr   r   __name__rW   DJANGO_TRACING_MINIMAL_adddictgetenv_django_include_user_name_django_include_user_email_django_include_user_login_django_include_user_realnamer   rG   __annotations__strrM   rN   rx   rf   ry   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  rK   rK   rK   rL   <module>   sX   		


!"$+

;


7






C
   
!"$+

;


7






C
