@@ -170,7 +170,9 @@ def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, A
170170---
171171"""
172172
173- from typing import Collection
173+ from __future__ import annotations
174+
175+ from typing import TYPE_CHECKING , Any , Collection , cast
174176
175177from starlette import applications
176178from starlette .routing import Match
@@ -184,18 +186,29 @@ def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, A
184186from opentelemetry .instrumentation .instrumentor import BaseInstrumentor
185187from opentelemetry .instrumentation .starlette .package import _instruments
186188from opentelemetry .instrumentation .starlette .version import __version__
187- from opentelemetry .metrics import get_meter
189+ from opentelemetry .metrics import MeterProvider , get_meter
188190from opentelemetry .semconv .trace import SpanAttributes
189- from opentelemetry .trace import get_tracer
191+ from opentelemetry .trace import TracerProvider , get_tracer
190192from opentelemetry .util .http import get_excluded_urls
191193
194+ if TYPE_CHECKING :
195+ from typing import TypedDict , Unpack
196+
197+ class InstrumentKwargs (TypedDict , total = False ):
198+ tracer_provider : TracerProvider
199+ meter_provider : MeterProvider
200+ server_request_hook : ServerRequestHook
201+ client_request_hook : ClientRequestHook
202+ client_response_hook : ClientResponseHook
203+
204+
192205_excluded_urls = get_excluded_urls ("STARLETTE" )
193206
194207
195208class StarletteInstrumentor (BaseInstrumentor ):
196- """An instrumentor for starlette
209+ """An instrumentor for Starlette.
197210
198- See `BaseInstrumentor`
211+ See `BaseInstrumentor`.
199212 """
200213
201214 _original_starlette = None
@@ -206,8 +219,8 @@ def instrument_app(
206219 server_request_hook : ServerRequestHook = None ,
207220 client_request_hook : ClientRequestHook = None ,
208221 client_response_hook : ClientResponseHook = None ,
209- meter_provider = None ,
210- tracer_provider = None ,
222+ meter_provider : MeterProvider | None = None ,
223+ tracer_provider : TracerProvider | None = None ,
211224 ):
212225 """Instrument an uninstrumented Starlette application."""
213226 tracer = get_tracer (
@@ -253,7 +266,7 @@ def uninstrument_app(app: applications.Starlette):
253266 def instrumentation_dependencies (self ) -> Collection [str ]:
254267 return _instruments
255268
256- def _instrument (self , ** kwargs ):
269+ def _instrument (self , ** kwargs : Unpack [ InstrumentKwargs ] ):
257270 self ._original_starlette = applications .Starlette
258271 _InstrumentedStarlette ._tracer_provider = kwargs .get ("tracer_provider" )
259272 _InstrumentedStarlette ._server_request_hook = kwargs .get (
@@ -269,7 +282,7 @@ def _instrument(self, **kwargs):
269282
270283 applications .Starlette = _InstrumentedStarlette
271284
272- def _uninstrument (self , ** kwargs ):
285+ def _uninstrument (self , ** kwargs : Any ):
273286 """uninstrumenting all created apps by user"""
274287 for instance in _InstrumentedStarlette ._instrumented_starlette_apps :
275288 self .uninstrument_app (instance )
@@ -278,14 +291,14 @@ def _uninstrument(self, **kwargs):
278291
279292
280293class _InstrumentedStarlette (applications .Starlette ):
281- _tracer_provider = None
282- _meter_provider = None
294+ _tracer_provider : TracerProvider | None = None
295+ _meter_provider : MeterProvider | None = None
283296 _server_request_hook : ServerRequestHook = None
284297 _client_request_hook : ClientRequestHook = None
285298 _client_response_hook : ClientResponseHook = None
286- _instrumented_starlette_apps = set ()
299+ _instrumented_starlette_apps : set [ applications . Starlette ] = set ()
287300
288- def __init__ (self , * args , ** kwargs ):
301+ def __init__ (self , * args : Any , ** kwargs : Any ):
289302 super ().__init__ (* args , ** kwargs )
290303 tracer = get_tracer (
291304 __name__ ,
@@ -318,21 +331,22 @@ def __del__(self):
318331 _InstrumentedStarlette ._instrumented_starlette_apps .remove (self )
319332
320333
321- def _get_route_details (scope ) :
334+ def _get_route_details (scope : dict [ str , Any ]) -> str | None :
322335 """
323- Function to retrieve Starlette route from scope.
336+ Function to retrieve Starlette route from ASGI scope.
324337
325338 TODO: there is currently no way to retrieve http.route from
326339 a starlette application from scope.
327340 See: https://github.com/encode/starlette/pull/804
328341
329342 Args:
330- scope: A Starlette scope
343+ scope: The ASGI scope that contains the Starlette application in the "app" key.
344+
331345 Returns:
332- A string containing the route or None
346+ The path to the route if found, otherwise None.
333347 """
334- app = scope ["app" ]
335- route = None
348+ app = cast ( applications . Starlette , scope ["app" ])
349+ route : str | None = None
336350
337351 for starlette_route in app .routes :
338352 match , _ = starlette_route .matches (scope )
@@ -344,18 +358,20 @@ def _get_route_details(scope):
344358 return route
345359
346360
347- def _get_default_span_details (scope ):
348- """
349- Callback to retrieve span name and attributes from scope.
361+ def _get_default_span_details (
362+ scope : dict [str , Any ],
363+ ) -> tuple [str , dict [str , Any ]]:
364+ """Callback to retrieve span name and attributes from ASGI scope.
350365
351366 Args:
352- scope: A Starlette scope
367+ scope: The ASGI scope that contains the Starlette application in the "app" key.
368+
353369 Returns:
354- A tuple of span name and attributes
370+ A tuple of span name and attributes.
355371 """
356372 route = _get_route_details (scope )
357- method = scope .get ("method" , "" )
358- attributes = {}
373+ method : str = scope .get ("method" , "" )
374+ attributes : dict [ str , Any ] = {}
359375 if route :
360376 attributes [SpanAttributes .HTTP_ROUTE ] = route
361377 if method and route : # http
0 commit comments