
    g                       d Z ddlmZ ddl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mZmZmZmZ ddlmZ dd	lmZmZ dd
lmZmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z, ddl-m.Z.m/Z/m0Z0 ddl1m2Z2 ddl3m4Z4 ddl5m6Z6 ddl7m8Z8 ddl9m:Z:m;Z; ddl<m=Z=m>Z>m?Z? ddl@mAZA ddlBmCZC ddlDmEZE ddlFmGZG ddlHmIZImJZJmKZKmLZLmMZMmNZNmOZOmPZPmQZQmRZR  G d de:eS         ZT eT       ZU G d de;eS         ZV eV       ZWej                  fdZY	 	 	 	 	 	 	 	 	 	 d&dZZd Z[dej                  fdZ\d'dZ]	 	 	 	 d(d Z^ G d! d"      Z_ej                  fd#Z`ej                  fd$Zad% Zby))aa  
The opentelemetry-instrumentation-asgi package provides an ASGI middleware that can be used
on any ASGI framework (such as Django-channels / Quart) to track request timing through OpenTelemetry.

Usage (Quart)
-------------

.. code-block:: python

    from quart import Quart
    from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware

    app = Quart(__name__)
    app.asgi_app = OpenTelemetryMiddleware(app.asgi_app)

    @app.route("/")
    async def hello():
        return "Hello!"

    if __name__ == "__main__":
        app.run(debug=True)


Usage (Django 3.0)
------------------

Modify the application's ``asgi.py`` file as shown below.

.. code-block:: python

    import os
    from django.core.asgi import get_asgi_application
    from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware

    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'asgi_example.settings')

    application = get_asgi_application()
    application = OpenTelemetryMiddleware(application)


Usage (Raw ASGI)
----------------

.. code-block:: python

    from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware

    app = ...  # An ASGI application.
    app = OpenTelemetryMiddleware(app)


Configuration
-------------

Request/Response hooks
**********************

This instrumentation supports request and response hooks. These are functions that get called
right after a span is created for a request and right before the span is finished for the response.

- The server request hook is passed a server span and ASGI scope object for every incoming request.
- The client request hook is called with the internal span and an ASGI scope when the method ``receive`` is called.
- The client response hook is called with the internal span and an ASGI event when the method ``send`` is called.

For example,

.. code-block:: python

    def server_request_hook(span: Span, scope: dict[str, Any]):
        if span and span.is_recording():
            span.set_attribute("custom_user_attribute_from_request_hook", "some-value")

    def client_request_hook(span: Span, scope: dict[str, Any], message: dict[str, Any]):
        if span and span.is_recording():
            span.set_attribute("custom_user_attribute_from_client_request_hook", "some-value")

    def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, Any]):
        if span and span.is_recording():
            span.set_attribute("custom_user_attribute_from_response_hook", "some-value")

   OpenTelemetryMiddleware().(application, server_request_hook=server_request_hook, client_request_hook=client_request_hook, client_response_hook=client_response_hook)

Capture HTTP request and response headers
*****************************************
You can configure the agent to capture specified HTTP headers as span attributes, according to the
`semantic convention <https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-request-and-response-headers>`_.

Request headers
***************
To capture HTTP request headers as span attributes, set the environment variable
``OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST`` to a comma delimited list of HTTP header names.

For example,
::

    export OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST="content-type,custom_request_header"

will extract ``content-type`` and ``custom_request_header`` from the request headers and add them as span attributes.

Request header names in ASGI are case-insensitive. So, giving the header name as ``CUStom-Header`` in the environment
variable will capture the header named ``custom-header``.

Regular expressions may also be used to match multiple headers that correspond to the given pattern.  For example:
::

    export OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST="Accept.*,X-.*"

Would match all request headers that start with ``Accept`` and ``X-``.

To capture all request headers, set ``OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST`` to ``".*"``.
::

    export OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST=".*"

The name of the added span attribute will follow the format ``http.request.header.<header_name>`` where ``<header_name>``
is the normalized HTTP header name (lowercase, with ``-`` replaced by ``_``). The value of the attribute will be a
list containing the header values.

For example:
``http.request.header.custom_request_header = ["<value1>", "<value2>"]``

Response headers
****************
To capture HTTP response headers as span attributes, set the environment variable
``OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE`` to a comma delimited list of HTTP header names.

For example,
::

    export OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE="content-type,custom_response_header"

will extract ``content-type`` and ``custom_response_header`` from the response headers and add them as span attributes.

Response header names in ASGI are case-insensitive. So, giving the header name as ``CUStom-Header`` in the environment
variable will capture the header named ``custom-header``.

Regular expressions may also be used to match multiple headers that correspond to the given pattern.  For example:
::

    export OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE="Content.*,X-.*"

Would match all response headers that start with ``Content`` and ``X-``.

To capture all response headers, set ``OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE`` to ``".*"``.
::

    export OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE=".*"

The name of the added span attribute will follow the format ``http.response.header.<header_name>`` where ``<header_name>``
is the normalized HTTP header name (lowercase, with ``-`` replaced by ``_``). The value of the attribute will be a
list containing the header values.

For example:
``http.response.header.custom_response_header = ["<value1>", "<value2>"]``

Sanitizing headers
******************
In order to prevent storing sensitive data such as personally identifiable information (PII), session keys, passwords,
etc, set the environment variable ``OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS``
to a comma delimited list of HTTP header names to be sanitized.  Regexes may be used, and all header names will be
matched in a case-insensitive manner.

For example,
::

    export OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS=".*session.*,set-cookie"

will replace the value of headers such as ``session-id`` and ``set-cookie`` with ``[REDACTED]`` in the span.

Note:
    The environment variable names used to capture HTTP headers are still experimental, and thus are subject to change.

API
---
    )annotationsN)defaultdictwraps)default_timer)Any	AwaitableCallableDefaultDictTuple)guarantee_single_callable)contexttrace))_filter_semconv_active_request_count_attr_filter_semconv_duration_attrs_get_schema_url_HTTPStabilityMode)_OpenTelemetrySemanticConventionStability!_OpenTelemetryStabilitySignalType_report_new_report_old'_server_active_requests_count_attrs_new'_server_active_requests_count_attrs_old_server_duration_attrs_new_server_duration_attrs_old_set_http_flavor_version_set_http_host_server_set_http_method_set_http_net_host_port_set_http_peer_ip_server_set_http_peer_port_server_set_http_scheme_set_http_target_set_http_url_set_http_user_agent_set_status)ClientRequestHookClientResponseHookServerRequestHook)__version__)get_global_response_propagator)_start_internal_or_server_span)	get_meter)GetterSetter)"create_http_server_active_requests$create_http_server_request_body_size%create_http_server_response_body_size)MetricInstruments)HTTP_SERVER_REQUEST_DURATION)SpanAttributes)set_span_in_context)
9OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS8OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST9OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSESanitizeValue_parse_url_queryget_custom_headersnormalise_request_header_namenormalise_response_header_nameremove_url_credentialssanitize_methodc                  (    e Zd Z	 	 	 	 	 	 ddZddZy)
ASGIGetterc                    |j                  d      }|sy|j                         }|D cg c],  \  }}t        |      j                         |k(  rt        |      . }}}|sy|S c c}}w )a/  Getter implementation to retrieve a HTTP header value from the ASGI
        scope.

        Args:
            carrier: ASGI scope object
            key: header name in scope
        Returns:
            A list with a single string with the header value if it exists,
                else None.
        headersN)getlower_decode_header_item)selfcarrierkeyrD   _key_valuedecodeds          `/var/www/openai/venv/lib/python3.12/site-packages/opentelemetry/instrumentation/asgi/__init__.pyrE   zASGIGetter.get  sx     ++i( iik #*
")v"4(..0C7  '") 	 

 
s   1A#c                t    |j                  d      xs g }|D cg c]  \  }}t        |       c}}S c c}}w )NrD   )rE   rG   )rH   rI   rD   rK   rL   s        rN   keyszASGIGetter.keys'  s7    ++i(.B@GHntV#D)HHHs   4N)rI   dictrJ   strreturnz!typing.Optional[typing.List[str]])rI   rQ   rS   ztyping.List[str])__name__
__module____qualname__rE   rP        rN   rB   rB   
  s%    "%	*8IrX   rB   c                      e Zd ZddZy)
ASGISetterc                    |j                  d      }|sg }||d<   |j                  |j                         j                         |j                         g       y)aN  Sets response header values on an ASGI scope according to `the spec <https://asgi.readthedocs.io/en/latest/specs/www.html#response-start-send-event>`_.

        Args:
            carrier: ASGI scope object
            key: response header name to set
            value: response header value
        Returns:
            None
        rD   N)rE   appendrF   encode)rH   rI   rJ   valuerD   s        rN   setzASGISetter.set0  sJ     ++i(G!(GI		**,elln=>rX   N)rI   rQ   rJ   rR   r^   rR   rS   None)rT   rU   rV   r_   rW   rX   rN   rZ   rZ   /  s    ?rX   rZ   c                V   t        |       \  }}}| j                  d      }|rH|rFt        |t              r|j	                  d      }|dt
        j                  j                  |      z   z  }i }| j                  d      }|rt        |||       |rt        |||       |rt        |||       | j                  d      }|rt        |||       | j                  d      }	|	rt        ||	|	||       |r/t        |      r$t        |t        |      t         j"                         | j                  dd      }
|
rt%        ||
t'        |
      |       t(        j                  | d	      }|r-t        |      r"d
j+                  |      |t,        j.                  <   t(        j                  | d      }|rt1        ||d   |       d| v rC| d   >t3        || j                  d      d   |       t5        || j                  d      d   |       |j7                         D ci c]  \  }}|	|| }}}|S c c}}w )zyCollects HTTP request attributes from the ASGI scope and returns a
    dictionary to be used as span creation attributes.query_stringutf8?schemehttp_versionpathmethod host,z
user-agentr   client   )get_host_port_url_tuplerE   
isinstancebytesdecodeurllibparseunquoter"   r   r   r   r#   r   r$   r?   r   DEFAULTr   r@   asgi_getterjoinr5   HTTP_SERVER_NAMEr%   r    r!   items)scopesem_conv_opt_in_modeserver_hostporthttp_urlrb   resultre   flavorrg   http_methodhttp_host_value_listhttp_user_agentkvs                  rN   collect_request_attributesr   F  s"   
 #:%"@Kx99^,LlE*'..v6LC&,,..|<<<FYYx F)=>fk3GH.BCYY~&F 1EF99VDD$.B	
 +,&x0"**
 ))Hb)KK( 		
 '??5&9+,69hh$7F>223 "ooe\:OV_Q%79MN5U8_8 EIIh'*,@	
 	#EIIh'*,@	

  &||~?~tq!ad~F?M @s   
H%H%c                    t        t              }| j                  d      }|r0|D ]+  \  }}|t        |         j	                  t        |             - |j                  |||      S )a'  
    Returns custom HTTP request or response headers to be added into SERVER span as span attributes.

    Refer specifications:
     - https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-request-and-response-headers
    rD   )r   listrE   rG   r\   sanitize_header_values)scope_or_response_messagesanitizeheader_regexesnormalize_namesrD   raw_headersrJ   r^   s           rN   !collect_custom_headers_attributesr     sn     ,7t+<G+//	:K%JC',-44#E* & ** rX   c                    | j                  d      xs ddg}|d   }|d   t        |      dk7  rdt        |      z   ndz   }| j                  d	d      }| j                  d
d      dz   |z   |z   }|||fS )z%Returns (host, port, full_url) tuple.serverz0.0.0.0P   rm   r   80:ri   rg   re   httpz://)rE   rR   )rz   r   r}   r|   	full_pathr~   s         rN   rn   rn     s    YYx 3YOF!9D)#d)t2CsSYLK 		&"%Iyy6*U2[@9LHh&&rX   c                ~    t        |      }	 t        |      }|i }t        | |||d|       y# t        $ r d}Y #w xY w)zEAdds HTTP response attributes to span using the status_code argument.NT)server_spanr{   )rR   int
ValueErrorr&   )spanstatus_codemetric_attributesr{   status_code_strs        rN   set_status_coder     s[     +&O+&  1	  s   . <<c                    | j                  dd      j                         }t        | j                  dd      j                               }|dk(  rd}|r|r	| d| i fS |r|i fS |i fS )a  
    Default span name is the HTTP method and URL path, or just the method.
    https://github.com/open-telemetry/opentelemetry-specification/pull/3165
    https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/http/#name

    Args:
        scope: the ASGI scope dictionary
    Returns:
        a tuple of the span name, and any attributes to attach to the span.
    rg   ri   rh   _OTHERHTTP )rE   stripr@   )rz   rg   rh   s      rN   get_default_span_detailsr     sy     99VR &&(DUYYx4::<=F$4&!2%%Rx2:rX   c                t    | j                  dd      }| j                  d      }t        |dd      }|r| | S y)a
  
    Returns the target path as defined by the Semantic Conventions.

    This value is suitable to use in metrics as it should replace concrete
    values with a parameterized name. Example: /api/users/{user_id}

    Refer to the specification
    https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/http-metrics.md#parameterized-attributes

    Note: this function requires specific code for each framework, as there's no
    standard attribute to use.
    	root_pathri   routepath_formatN)rE   getattr)rz   r   r   r   s       rN   _collect_target_attributer     sE      		+r*IIIgE%5K[M**rX   c                  ~    e Zd ZdZ	 	 	 	 	 	 	 	 	 	 	 	 	 d		 	 	 	 	 	 	 	 	 	 	 	 	 d
dZ	 	 	 	 	 	 	 	 ddZd Zd Zd Zd Z	y)OpenTelemetryMiddlewarea  The ASGI application middleware.

    This class is an ASGI middleware that starts and annotates spans for any
    requests it is invoked with.

    Args:
        app: The ASGI application callable to forward requests to.
        default_span_details: Callback which should return a string and a tuple, representing the desired default span name and a
                      dictionary with any additional span attributes to set.
                      Optional: Defaults to get_default_span_details.
        server_request_hook: Optional callback which is called with the server span and ASGI
                      scope object for every incoming request.
        client_request_hook: Optional callback which is called with the internal span, and ASGI
                      scope and event which are sent as dictionaries for when the method receive is called.
        client_response_hook: Optional callback which is called with the internal span, and ASGI
                      scope and event which are sent as dictionaries for when the method send is called.
        tracer_provider: The optional tracer provider to use. If omitted
            the current globally configured one is used.
        meter_provider: The optional meter provider to use. If omitted
            the current globally configured one is used.
        exclude_spans: Optionally exclude HTTP `send` and/or `receive` spans from the trace.
    Nc                   t        j                          t        j                  t        j                        }t        |      | _        |	*t        j                  t        t        |t        |            n|	| _        |
 t        t        t        |t        |            n|
| _        d | _        t!        |      r1| j                  j#                  t$        j&                  dd      | _        d | _        t+        |      r'| j                  j#                  t,        dd      | _        d | _        t!        |      r1| j                  j#                  t$        j0                  dd	      | _        d | _        t+        |      rt5        | j                        | _        d | _        t!        |      r1| j                  j#                  t$        j8                  dd
      | _        d | _        t+        |      rt=        | j                        | _        t?        | j                        | _         || _!        |xs tD        | _#        || _$        || _%        || _&        d | _'        || _(        |xs tS        tT              xs d | _+        |xs tS        tX              xs d | _-        t]        |xs tS        t^              xs g       | _0        |rd|v nd| _1        |r
d|v | _2        y d| _2        y )N)
schema_urlmsz/Measures the duration of inbound HTTP requests.)nameunitdescriptionz!Duration of HTTP server requests.s)r   r   r   Byz9measures the size of HTTP response messages (compressed).z8Measures the size of HTTP request messages (compressed).receiveFsend)3r   _initialize(_get_opentelemetry_stability_opt_in_moder   r   r   appr   
get_tracerrT   r*   r   tracerr-   meterduration_histogram_oldr   create_histogramr3   HTTP_SERVER_DURATIONduration_histogram_newr   r4   server_response_size_histogramHTTP_SERVER_RESPONSE_SIZE#server_response_body_size_histogramr2   server_request_size_histogramHTTP_SERVER_REQUEST_SIZE"server_request_body_size_histogramr1   r0   active_requests_counterexcluded_urlsr   default_span_detailsserver_request_hookclient_request_hookclient_response_hookcontent_length_header_sem_conv_opt_in_moder<   r8   #http_capture_headers_server_requestr9   $http_capture_headers_server_responser:   r7   $http_capture_headers_sanitize_fieldsexclude_receive_spanexclude_send_span)rH   r   r   r   r   r   r   tracer_providermeter_providerr   r   r   r   r   exclude_spansr{   s                   rN   __init__z OpenTelemetryMiddleware.__init__  s   $ 	2==?Hqq-22 
 -S1 ~ *+?@	  	" } *+?@	  	
 '+#+,*.***E*E&;;M +F +D'
 '+#+,*.***E*E1? +F +D'
 /3++,26**2M2M&@@W 3N 3D/
 480+,5djjA 4 .2*+,151L1L&??V 2M 2D.
 37/+,4TZZ@ 3 (JJJ(
$ + <$< 	! $7 #6 $8!%)"%9" 0 "L  	0 1 "M  	1 5B0 "M 5
1 +8I&U 	! (5Fm# 	:? 	rX   c           
        K   t               }|d   dvr| j                  |||       d{   S t        |      \  }}}| j                  r6| j                  j	                  |      r| j                  |||       d{   S | j                  |      \  }}t        || j                        }	|	j                  |       t        | j                  |d|t        |	      \  }
}t        |	| j                        }|d   dk(  r| j                  j                  d|       	 t        j                   |
d      5 }|j#                         r|	j%                         D ]  \  }}|j'                  ||        |j(                  t        j*                  j,                  k(  rS| j.                  r&t1        || j2                  | j.                  t4              ni }t7        |      d	kD  r|j9                  |       t;        | j<                        r| j=                  ||       | j?                  |||      }| jA                  |||||	      }| j                  |||       d{    ddd       |d   dk(  rtC        |      }|r'tE        |      \  }}tG        |	|||| j                         t               |z
  }tI        |	tJ        jL                        }|r||tN        jP                  <   tI        |	tJ        jR                        }| jT                  r2| jT                  jW                  tY        t[        |d
z        d	      |       | j\                  r&| j\                  jW                  tY        |d	      |       | j                  j                  d|       | j^                  rd| j`                  r&| j`                  jW                  | j^                  |       | jb                  r&| jb                  jW                  | j^                  |       t        je                  |d      }|r`	 tg        |d	         }| jh                  r| jh                  jW                  ||       | jj                  r| jj                  jW                  ||       	 |rto        jp                  |       |
j#                         r|
js                          yy7 l7 7 S# 1 sw Y   SxY w# tl        $ r Y Zw xY w# |d   dk(  rtC        |      }|r'tE        |      \  }}tG        |	|||| j                         t               |z
  }tI        |	tJ        jL                        }|r||tN        jP                  <   tI        |	tJ        jR                        }| jT                  r2| jT                  jW                  tY        t[        |d
z        d	      |       | j\                  r&| j\                  jW                  tY        |d	      |       | j                  j                  d|       | j^                  rd| j`                  r&| j`                  jW                  | j^                  |       | jb                  r&| jb                  jW                  | j^                  |       t        je                  |d      }|ro	 tg        |d	         }| jh                  r| jh                  jW                  ||       | jj                  r,| jj                  jW                  ||       n# tl        $ r Y nw xY w|rto        jp                  |       |
j#                         r|
js                          w w xY ww)zThe ASGI application

        Args:
            scope: An ASGI environment.
            receive: An awaitable callable yielding dictionaries
            send: An awaitable callable taking a single dictionary as argument.
        type)r   	websocketN)r   	span_name
start_timecontext_carriercontext_getter
attributesr   rm   F)end_on_exitr   i  r   content-length):r   r   rn   r   url_disabledr   r   r   updater,   r   rv   !_parse_active_request_count_attrsr   addr   use_spanis_recordingry   set_attributekindSpanKindSERVERr   r   r   r=   lenset_attributescallabler   _get_otel_receive_get_otel_sendr   r;   r#   _parse_duration_attrsr   ru   r5   HTTP_TARGETr   r   recordmaxroundr   r   r   r   rE   r   r   r   r   r   detachend)rH   rz   r   r   start_urlr   additional_attributesr   r   tokenactive_requests_count_attrscurrent_spanrJ   r^   custom_attributesotel_receive	otel_sendtargetrg   query
duration_sduration_attrs_oldduration_attrs_newrequest_sizerequest_size_amounts                              rN   __call__z OpenTelemetryMiddleware.__call__  s     = 55%$777+E2	1c$"4"4"A"A#"F%$777+/+D+DU+K(	(/4--

 	/04;;!&!
e 'H&&'
#
 =F"((,,Q0KL`	%8L,,.&0&6&6&8
U$223> '9 $((ENN,A,AA  $GG > % $ I I $ H H =	 "$ * 01A5(778IJD445,,\5A#55ug  !// 	 hhulI>>>E 9H V}&259"26":KD%$"22 +_u4
%: 2 : :&" EK&~'A'AB%: 2 7 7&" ..//66E*t"34a8:L ..//66J*,> ,,003 --::;;BB 668J ??@@GG 668J  +u6FG.1,q/.B+  == >>EE 35G  BB CCJJ 35G u%  "
 #u 8 8t ?E 98b & [ V}&259"26":KD%$"22 +_u4
%: 2 : :&" EK&~'A'AB%: 2 7 7&" ..//66E*t"34a8:L ..//66J*,> ,,003 --::;;BB 668J ??@@GG 668J  +u6FG.1,q/.B+  == >>EE 35G  BB CCJJ 35G &  u%  "
 #s   (\RA\;R<B\R; /DR	R
RR; F'\>R, B\\RR)$R; ,	R85\7R88\;F(\$[2A\	[\[<\\c                V      j                   rS t               fd       }|S )Nc                   K   j                   j                  dj                  d   df            5 }          d {   }t        j                        rj	                  | |       | j                         r5|d   dk(  rt        | dd j                         | j                  d|d          d d d        |S 7 {# 1 sw Y   S xY ww)Nr   r   r   zwebsocket.receive   asgi.event.type)	r   start_as_current_spanrw   r   r   r   r   r   r   )receive_spanmessager   rz   rH   server_span_names     rN   r  z?OpenTelemetryMiddleware._get_otel_receive.<locals>.otel_receive+  s     22*E&M9EF '	/D445,,\5'J,,.v*=='(  66	 !..)76?" N *" Ns.   1C
B=B; A1B=1
C
;B==CC
)r   r   )rH   r  rz   r   r  s   ```` rN   r   z)OpenTelemetryMiddleware._get_otel_receive'  s/    $$N	w	 
	( rX   c                   | j                   j                  dj                  ||d   df            5 }t        | j                        r| j	                  |||       |j                         r/|d   dk(  r|j                  dd      }|j                  d|d          |rt        ||d| j                         ddd       |S # 1 sw Y   |S xY w)	z)Set send span attributes and status code.r   r   r   http.response.starttrailersFr  N)
r   r  rw   r   r   r   rE   r   r   r   )rH   r  rz   r   r  r   expecting_trailers	send_spans           rN   _set_send_spanz&OpenTelemetryMiddleware._set_send_spanB  s     [[..HH&fv>?
112)))UGD%%'6?&;;)0Z)G&''(976?K..	
$ "!%
$ "!s   BB==Cc                V   |j                         r~|j                  t        j                  j                  k(  rWd|v rS| j
                  r&t        || j                  | j
                  t              ni }t        |      dkD  r|j                  |       |rt        |||| j                         yy)z+Set server span attributes and status code.rD   r   N)r   r   r   r   r   r   r   r   r>   r   r   r   r   )rH   r   r  r   duration_attrscustom_response_attributess         rN   _set_server_spanz(OpenTelemetryMiddleware._set_server_span`  s    
 $$&  ENN$9$99W$ << 2====2	  ' -.2**+EF**	 rX   c           	     L     dt              d fd       }|S )NFc                r  K   d }| d   dk(  r| d   }n
| d   dk(  rd}j                   sj                  
| |      j                  	| |       t               }|r>|j	                  | t        	t        j                  j                               t               t        j                  | d      }|r	 t        |d         _         |        d {    s| d   d	k(  r| j                  d
d      rr-| d   dk(  r$| j                  dd      s	j                          y y y y # t        $ r Y gw xY w7 _w)Nr   r  statuszwebsocket.sendr  )r   setterr   r   zhttp.response.body	more_bodyFzhttp.response.trailersmore_trailers)r   r  r  r+   injectr6   r   context_apiContextasgi_setterrv   rE   r   r   r   r   )r  r   
propagatorcontent_lengthr  r  rz   rH   r   r   r  s       rN   r  z9OpenTelemetryMiddleware._get_otel_send.<locals>.otel_send  sm     Kv"77%h/$44!))%)%8%8$&&" !!Wk> 89J!!/#U%6%6%>%>%@ ' "  )__W6FGN14^A5F1GD. w- 'FO';;K7"FO'??OU;! < @ # "   s7   B3D77D& 
D7D5AD7&	D2/D71D22D7)r  dict[str, Any]r   )rH   r   r  rz   r   r  r  r  s   `````` @rN   r   z&OpenTelemetryMiddleware._get_otel_send~  s/     #	t4	" 4	" 
4	"l rX   )NNNNNNNNNNNNN)r   r)   r   r'   r   r(   r   list[str] | Noner   r+  r   r+  r   z.list[typing.Literal['receive', 'send']] | None)rz   r*  r   z'Callable[[], Awaitable[dict[str, Any]]]r   z+Callable[[dict[str, Any]], Awaitable[None]]rS   r`   )
rT   rU   rV   __doc__r   r  r   r  r  r   rW   rX   rN   r   r     s    6 !151537@DAEAEHL

 /
 /
 1
 .>
 /?
 /?
 F
DJJ 9J :	J
 
JZ6"<<ArX   r   c                .    t        | t        t        |      S N)r   r   r   	req_attrsr{   s     rN   r   r     s     *""	 rX   c                .    t        | t        t        |      S r.  )r   r   r   r/  s     rN   r   r     s     5//	 rX   c                f    	 | j                  d      S # t        $ r | j                  d      cY S w xY w)Nzutf-8unicode_escape)rq   r   )r^   s    rN   rG   rG     s7    .||G$$ . ||,--	.s    00)
r   r*  r   r:   r   z	list[str]r   zCallable[[str], str]rS   zdict[str, list[str]])rz   rQ   rS   zTuple[str, dict])rz   ztyping.Dict[str, typing.Any]rS   ztyping.Optional[str])cr,  
__future__r   typingrr   collectionsr   	functoolsr   timeitr   r   r	   r
   r   r   asgiref.compatibilityr   opentelemetryr   r   &opentelemetry.instrumentation._semconvr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   (opentelemetry.instrumentation.asgi.typesr'   r(   r)   *opentelemetry.instrumentation.asgi.versionr*   )opentelemetry.instrumentation.propagatorsr+   #opentelemetry.instrumentation.utilsr,   opentelemetry.metricsr-   !opentelemetry.propagators.textmapr.   r/   6opentelemetry.semconv._incubating.metrics.http_metricsr0   r1   r2   opentelemetry.semconv.metricsr3   *opentelemetry.semconv.metrics.http_metricsr4   opentelemetry.semconv.tracer5   opentelemetry.tracer6   opentelemetry.util.httpr7   r8   r9   r:   r;   r<   r=   r>   r?   r@   rQ   rB   rv   rZ   r'  ru   r   r   rn   r   r   r   r   r   r   rG   rW   rX   rN   <module>rH     sy   n` #   #    ? ? ; (      2 
 C O + < 
 < 7 3  I ID l? ?& l
 !3 : :AH-  *	
 8'& +33	2,'4@ @H %7$>$> %7$>$>.rX   