
    g/                       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	m
Z
mZmZmZ d dlmZ d dlZd dlmZmZ d dlmZmZ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$m%Z% ddl&m'Z'm(Z( ddl)m*Z*m+Z+ ddl,m-Z- 	 d dl.m/Z/ d dl0m1Z1 d$dZ4ddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d%dZ5ed        Z6 G d d      Z7	 	 	 	 d&dZ8 G d  d!e9      Z:d"Z;d'd#Z<y# e2$ r	  e3d      w xY w)(    )annotationsN)contextmanager)	lru_cache)Any	AwaitableCallableContextManagerIterable)WeakKeyDictionary)BackgroundTasksFastAPI)APIRouteAPIWebSocketRouteMount)SecurityScopes)SpanAttributes)Span)Request)Response)	WebSocket   )Logfireset_user_attributes_on_raw_span)	StackInfoget_code_object_info)handle_internal_errorsmaybe_capture_server_headers   ) tweak_asgi_spans_tracer_provider)ServerRequestHook)FastAPIInstrumentorzThe `logfire.instrument_fastapi()` requires the `opentelemetry-instrumentation-fastapi` package.
You can install this with:
    pip install 'logfire[fastapi]'c                    g }| j                   D ]O  }t        |t              s|j                  }t        |t              s1|j                  |       |t        |      z  }Q |S )zGFetch all sub-apps mounted to a FastAPI app, including nested sub-apps.)routes
isinstancer   appr   appendfind_mounted_apps)r%   mounted_appsroute_apps       [/var/www/openai/venv/lib/python3.12/site-packages/logfire/_internal/integrations/fastapi.pyr'   r'   $   sX    "$LeU#		D$(##D) 1$ 77      F)capture_headersrequest_attributes_mapperexcluded_urlsrecord_send_receivec          
       	
 t        |t        t        d      f      sdj                  |      }t	        |       t        | |      | j                  j                         d|}t        j                  |f|t        |j                  dd            d| t               
|
v rt        d      t        |      		j                  |       	D ]  }t!        | |xs t"              
|<    t$        	
fd       } |       S )zInstrument a FastAPI app so that spans and logs are automatically created for each request.

    See `Logfire.instrument_fastapi` for more details.
    N,)tracer_providermeter_providerserver_request_hook)r/   r5   z'This app has already been instrumented.c               3     K   	 d  D ]  } | = t        j                  |         y # D ]  } | = t        j                  |         w xY wwN)r!   uninstrument_app)r*   r(   registrys    r+   uninstrument_contextz0instrument_fastapi.<locals>.uninstrument_contextd   sM     
	;$TN#44T: %TN#44T: %s   A)  A!A

A)r$   strtypejoinr   r   configget_meter_providerr!   instrument_app_server_request_hookpoppatch_fastapi
ValueErrorr'   r&   FastAPIInstrumentation"_default_request_attributes_mapperr   )logfire_instancer%   r-   r.   r/   r0   opentelemetry_kwargsr*   r:   r(   r9   s            @@r+   instrument_fastapirI   0   s   , mc4:%67/ 1;<LNab*11DDF 
 &&#01E1I1IJ_ae1fg 	 H
hBCC$S)L/%K)K
  	; 	;  !!r,   c                     t               dfd} t        j                  j                  | t        j                  _        dfd}t        j                  j                  |t        j                  _        S )zlGlobally monkeypatch fastapi functions and return a dictionary for recording instrumentation config per app.c                   K    dd| i|}j                  | j                        x}r|j                  | |       d {   S | d {   S 7 7 w)Nrequest )getr%   solve_dependencies)rL   kwargsoriginalinstrumentationoriginal_solve_dependenciesr9   s       r+   patched_solve_dependenciesz1patch_fastapi.<locals>.patched_solve_dependenciesx   sY     .IwI&I&ll7;;77?7(;;GXNNN!>! O!s#   =A A	A
AAAc                   K   t        |t              rG|j                  }j                  |j                        x}r |j
                  || |fi | d {   S  d| |d| d {   S 7 7 w)N	dependantvaluesrM   )r$   _InstrumentedValuesrL   rN   r%   run_endpoint_function)rW   rX   rP   rL   rR   original_run_endpoint_functionr9   s        r+   patched_run_endpoint_functionz4patch_fastapi.<locals>.patched_run_endpoint_function   s     f12nnG"*,,w{{";;;B_BB2GYRX   4aiPVaZ`aaa bs$   AA2A.A2)A0*A20A2)rL   Request | WebSocketrP   r   returnr   )rW   r   rX   dict[str, Any]rP   r   r^   r   )r   fastapiroutingrO   rZ   )rT   r\   r[   rS   r9   s     @@@r+   rC   rC   s   s[     DUCVH" #*//"D"D)CGOO&b &-__%J%J",IGOO)Or,   c                  D    e Zd Z	 	 	 	 ddZddZ	 	 	 	 	 	 	 	 	 	 	 	 ddZy)rE   c                @    |j                  d      | _        || _        y )Nr`   )custom_scope_suffix)with_settingsrG   r.   )selfrG   r.   s      r+   __init__zFastAPIInstrumentation.__init__   s#     !1 > >S\ > ])B&r,   c                  K   |j                   j                  t              }|r|j                         s
| d {   S | j                  j                  d      5 }t               5  t        |t              r*|j                  t        j                  |j                         |j                   j                  d      }|rt|j                  t        j                  |j                         d|j                  i}t        |t               r|j"                  |d<   t%        ||       |j'                  |       d d d        | d {   t               5  t        t(              rd   }d   }dfd}	nj*                  }j,                  }dfd}	|j/                         D 
ci c]-  \  }
}t        |t        t0        t2        t4        t6        f      s|
|/ c}}
|j9                         d	}t        |t              rt;        |      }||_         |	|      | j?                  ||      }|s%|jA                  d
       cd d d        cd d d        S |j                  d      r|jA                  d       |j'                  |       d	D ]  }||v s|jC                  |      |d|z   <     t%        ||       d d d        d d d        S 7 # 1 sw Y   xY w7 c c}}
w # 1 sw Y   ,xY w# 1 sw Y   S xY ww)NzFastAPI argumentsr)   zfastapi.route.namezfastapi.route.operation_idr   r   c                    | gdd  S )Nr   rM   
new_valuesresults    r+   solved_with_new_valueszIFastAPIInstrumentation.solve_dependencies.<locals>.solved_with_new_values   s    )6F12J66r,   c                2    t        j                  |       S )N)rX   )dataclassesreplacerj   s    r+   rm   zIFastAPIInstrumentation.solve_dependencies.<locals>.solved_with_new_values   s    *226*MMr,   )rX   errorsdebugrq   errorzfastapi.arguments.)rk   r_   r^   r   )"scoperN   LOGFIRE_SPAN_SCOPE_KEYis_recordingrG   spanr   r$   r   set_attributer   HTTP_METHODmethod
HTTP_ROUTEpathnamer   operation_idr   set_attributestuplerX   rq   itemsr   r   r   r   copyrY   rL   r.   	set_levelrB   )rf   rL   rQ   	root_spanrw   r)   fastapi_route_attributessolved_valuessolved_errorsrm   kv
attributesinstrumented_valueskeyrl   s                  @r+   rO   z)FastAPIInstrumentation.solve_dependencies   s    MM%%&<=	i446!>!""''(;<')gw/&&~'A'A7>>R=D]]=N=Nw=W&&~'@'@%**M@TV[V`V`?a,!%2QVQcQc01MN3I?WX''(@A * !).F') fe,$*1IM$*1IM7 %+MMM$*MMMN %2$7$7$9$9DAq)!gy/Sack-lm 1$9
 ,002
5
 gw/*=m*L'29'/"89L"MF!;;GZP
!
 NN7+!U *) =<x >>(+NN7+##J//Cj(AKPSAT
#7##=> 0 0	:Fi * =J O " *) ).+ *) =J s   7K0J>K0K#%CK1K#>K?K#AK 2K
A%K7	K# 
K0
<K%K,K#4K0K		K#KK 	K##K-(K0c                f  K   t        j                  |j                        }t        |dd       }|rt	        |      ni } | j
                  j                  	 dd|j                  id|j                  d   j                  i|ddi5   |d	||d| d {   cd d d        S 7 # 1 sw Y   y xY ww)
N__code__rz   z
http.router)   _levelrr   rV   )z'{method} {http.route} ({code.function})rM   )
inspectunwrapcallgetattrr   rG   rw   rz   rt   r|   )	rf   r[   rL   rW   rX   rP   callbackcode
stack_infos	            r+   rZ   z,FastAPIInstrumentation.run_endpoint_function   s      >>)..1xT2>B 4T :
'T""''5	
>>	
 W]]73889	
 	
 	
 8e)TZe^dee	
 	
 f	
 	
s0   BB1B%B#B%
B1#B%%B.*B1N)rG   r   r.   zFCallable[[Request | WebSocket, dict[str, Any]], dict[str, Any] | None])rL   r]   rQ   zAwaitable[Any]r^   r   )r[   r   rL   r   rW   r   rX   r_   rP   r   r^   r   )__name__
__module____qualname__rg   rO   rZ   rM   r,   r+   rE   rE      si    C!C$
CJXf(+f f 	f
 f f 
fr,   rE   c                    |S r7   rM   )_requestr   s     r+   rF   rF     s
     r,   c                      e Zd ZU ded<   y)rY   r   rL   N)r   r   r   __annotations__rM   r,   r+   rY   rY     s    r,   rY   zlogfire.spanc                     d fd}|S )Nc                0    | |t         <   r
 | |       y y r7   )ru   )rw   rt   	user_hooks     r+   hookz"_server_request_hook.<locals>.hook  s     (,$%dE" r,   )rw   r   rt   r_   rM   )r   r   s   ` r+   rA   rA     s    #
 Kr,   )r%   r   r^   zlist[FastAPI])rG   r   r%   r   r-   boolr.   zMCallable[[Request | WebSocket, dict[str, Any]], dict[str, Any] | None] | Noner/   zstr | Iterable[str] | Noner0   r   rH   r   r^   zContextManager[None])r   r]   r   r_   )r   zServerRequestHook | None)=
__future__r   ro   r   
contextlibr   	functoolsr   typingr   r   r   r	   r
   weakrefr   fastapi.routingr`   r   r   r   r   r   fastapi.securityr   opentelemetry.semconv.tracer   opentelemetry.tracer   starlette.requestsr   starlette.responsesr   starlette.websocketsr   mainr   r   r   r   r   utilsr   r   asgir   "opentelemetry.instrumentation.asgir    %opentelemetry.instrumentation.fastapir!   ImportErrorRuntimeErrorr'   rI   rC   rE   rF   dictrY   ru   rA   rM   r,   r+   <module>r      s8   "   %  E E %  , > > + 6 $ & ( * ; 8 H 2DI	  " 04 %@"@"	@" 	@"
 @" .@" @"  @"  !@"F  Bpf pff!$  ( u  
	- s   C C+