diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d79a899ba..918bbd6084 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added + +- `opentelemetry-instrumentation-aiohttp-client`: add typechecking for aiohttp-client instrumentation + ([#4006](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/4006)) + ## Version 1.39.0/0.60b0 (2025-12-03) ### Added diff --git a/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py b/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py index 5db778a06a..250eae965e 100644 --- a/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py @@ -102,10 +102,20 @@ def response_hook(span: Span, params: typing.Union[ --- """ +from __future__ import annotations + import types import typing from timeit import default_timer -from typing import Collection +from typing import ( + TYPE_CHECKING, + Any, + Callable, + Collection, + TypedDict, + Union, + cast, +) from urllib.parse import urlparse import aiohttp @@ -143,7 +153,9 @@ def response_hook(span: Span, params: typing.Union[ from opentelemetry.metrics import MeterProvider, get_meter from opentelemetry.propagate import inject from opentelemetry.semconv.attributes.error_attributes import ERROR_TYPE -from opentelemetry.semconv.metrics import MetricInstruments +from opentelemetry.semconv.metrics import ( + MetricInstruments, # type: ignore[reportDeprecated] +) from opentelemetry.semconv.metrics.http_metrics import ( HTTP_CLIENT_REQUEST_DURATION, ) @@ -155,22 +167,39 @@ def response_hook(span: Span, params: typing.Union[ sanitize_method, ) -_UrlFilterT = typing.Optional[typing.Callable[[yarl.URL], str]] -_RequestHookT = typing.Optional[ - typing.Callable[[Span, aiohttp.TraceRequestStartParams], None] -] -_ResponseHookT = typing.Optional[ - typing.Callable[ - [ - Span, - typing.Union[ - aiohttp.TraceRequestEndParams, - aiohttp.TraceRequestExceptionParams, +if TYPE_CHECKING: + from typing_extensions import Unpack + + UrlFilterT = typing.Optional[typing.Callable[[yarl.URL], str]] + RequestHookT = typing.Optional[ + typing.Callable[[Span, aiohttp.TraceRequestStartParams], None] + ] + ResponseHookT = typing.Optional[ + typing.Callable[ + [ + Span, + typing.Union[ + aiohttp.TraceRequestEndParams, + aiohttp.TraceRequestExceptionParams, + ], ], - ], - None, + None, + ] ] -] + + class ClientSessionInitKwargs(TypedDict, total=False): + trace_configs: typing.Sequence[aiohttp.TraceConfig] + + class InstrumentKwargs(TypedDict, total=False): + tracer_provider: trace.TracerProvider + meter_provider: MeterProvider + url_filter: UrlFilterT + request_hook: RequestHookT + response_hook: ResponseHookT + trace_configs: typing.Sequence[aiohttp.TraceConfig] + + class UninstrumentKwargs(TypedDict, total=False): + pass def _get_span_name(method: str) -> str: @@ -181,10 +210,10 @@ def _get_span_name(method: str) -> str: def _set_http_status_code_attribute( - span, - status_code, - metric_attributes=None, - sem_conv_opt_in_mode=_StabilityMode.DEFAULT, + span: Span, + status_code: int, + metric_attributes: Union[dict[str, Any], None] = None, + sem_conv_opt_in_mode: _StabilityMode = _StabilityMode.DEFAULT, ): status_code_str = str(status_code) try: @@ -209,11 +238,11 @@ def _set_http_status_code_attribute( # pylint: disable=too-many-locals # pylint: disable=too-many-statements def create_trace_config( - url_filter: _UrlFilterT = None, - request_hook: _RequestHookT = None, - response_hook: _ResponseHookT = None, - tracer_provider: TracerProvider = None, - meter_provider: MeterProvider = None, + url_filter: UrlFilterT = None, + request_hook: RequestHookT = None, + response_hook: ResponseHookT = None, + tracer_provider: Union[TracerProvider, None] = None, + meter_provider: Union[MeterProvider, None] = None, sem_conv_opt_in_mode: _StabilityMode = _StabilityMode.DEFAULT, ) -> aiohttp.TraceConfig: """Create an aiohttp-compatible trace configuration. @@ -268,12 +297,10 @@ def create_trace_config( schema_url, ) - start_time = 0 - duration_histogram_old = None if _report_old(sem_conv_opt_in_mode): duration_histogram_old = meter.create_histogram( - name=MetricInstruments.HTTP_CLIENT_DURATION, + name=MetricInstruments.HTTP_CLIENT_DURATION, # type: ignore[reportDeprecated] unit="ms", description="measures the duration of the outbound HTTP request", explicit_bucket_boundaries_advisory=HTTP_DURATION_HISTOGRAM_BUCKETS_OLD, @@ -293,32 +320,39 @@ def _end_trace(trace_config_ctx: types.SimpleNamespace): elapsed_time = max(default_timer() - trace_config_ctx.start_time, 0) if trace_config_ctx.token: context_api.detach(trace_config_ctx.token) - trace_config_ctx.span.end() + if trace_config_ctx.span: + trace_config_ctx.span.end() if trace_config_ctx.duration_histogram_old is not None: - duration_attrs_old = _filter_semconv_duration_attrs( - trace_config_ctx.metric_attributes, - _client_duration_attrs_old, - _client_duration_attrs_new, - _StabilityMode.DEFAULT, + duration_attrs_old = cast( + dict[str, Any], + _filter_semconv_duration_attrs( + trace_config_ctx.metric_attributes, + _client_duration_attrs_old, + _client_duration_attrs_new, + _StabilityMode.DEFAULT, + ), ) trace_config_ctx.duration_histogram_old.record( max(round(elapsed_time * 1000), 0), attributes=duration_attrs_old, ) if trace_config_ctx.duration_histogram_new is not None: - duration_attrs_new = _filter_semconv_duration_attrs( - trace_config_ctx.metric_attributes, - _client_duration_attrs_old, - _client_duration_attrs_new, - _StabilityMode.HTTP, + duration_attrs_new = cast( + dict[str, Any], + _filter_semconv_duration_attrs( + trace_config_ctx.metric_attributes, + _client_duration_attrs_old, + _client_duration_attrs_new, + _StabilityMode.HTTP, + ), ) trace_config_ctx.duration_histogram_new.record( elapsed_time, attributes=duration_attrs_new ) async def on_request_start( - unused_session: aiohttp.ClientSession, + _session: aiohttp.ClientSession, trace_config_ctx: types.SimpleNamespace, params: aiohttp.TraceRequestStartParams, ): @@ -326,19 +360,22 @@ async def on_request_start( not is_http_instrumentation_enabled() or trace_config_ctx.excluded_urls.url_disabled(str(params.url)) ): - trace_config_ctx.span = None return trace_config_ctx.start_time = default_timer() method = params.method request_span_name = _get_span_name(method) request_url = ( - redact_url(trace_config_ctx.url_filter(params.url)) + redact_url( + cast(Callable[[yarl.URL], str], trace_config_ctx.url_filter)( + params.url + ) + ) if callable(trace_config_ctx.url_filter) else redact_url(str(params.url)) ) - span_attributes = {} + span_attributes: dict[str, Any] = {} _set_http_method( span_attributes, method, @@ -399,7 +436,7 @@ async def on_request_start( inject(params.headers) async def on_request_end( - unused_session: aiohttp.ClientSession, + _session: aiohttp.ClientSession, trace_config_ctx: types.SimpleNamespace, params: aiohttp.TraceRequestEndParams, ): @@ -418,7 +455,7 @@ async def on_request_end( _end_trace(trace_config_ctx) async def on_request_exception( - unused_session: aiohttp.ClientSession, + _session: aiohttp.ClientSession, trace_config_ctx: types.SimpleNamespace, params: aiohttp.TraceRequestExceptionParams, ): @@ -441,21 +478,25 @@ async def on_request_exception( _end_trace(trace_config_ctx) - def _trace_config_ctx_factory(**kwargs): + def _trace_config_ctx_factory(**kwargs: Any) -> types.SimpleNamespace: kwargs.setdefault("trace_request_ctx", {}) return types.SimpleNamespace( tracer=tracer, - url_filter=url_filter, - start_time=start_time, + span=None, + token=None, duration_histogram_old=duration_histogram_old, duration_histogram_new=duration_histogram_new, - excluded_urls=excluded_urls, metric_attributes={}, + url_filter=url_filter, + excluded_urls=excluded_urls, + start_time=0, **kwargs, ) trace_config = aiohttp.TraceConfig( - trace_config_ctx_factory=_trace_config_ctx_factory + trace_config_ctx_factory=cast( + type[types.SimpleNamespace], _trace_config_ctx_factory + ) ) trace_config.on_request_start.append(on_request_start) @@ -466,11 +507,11 @@ def _trace_config_ctx_factory(**kwargs): def _instrument( - tracer_provider: TracerProvider = None, - meter_provider: MeterProvider = None, - url_filter: _UrlFilterT = None, - request_hook: _RequestHookT = None, - response_hook: _ResponseHookT = None, + tracer_provider: Union[TracerProvider, None] = None, + meter_provider: Union[MeterProvider, None] = None, + url_filter: UrlFilterT = None, + request_hook: RequestHookT = None, + response_hook: ResponseHookT = None, trace_configs: typing.Optional[ typing.Sequence[aiohttp.TraceConfig] ] = None, @@ -485,7 +526,12 @@ def _instrument( trace_configs = trace_configs or () # pylint:disable=unused-argument - def instrumented_init(wrapped, instance, args, kwargs): + def instrumented_init( + wrapped: Callable[..., None], + _instance: aiohttp.ClientSession, + args: tuple[Any, ...], + kwargs: ClientSessionInitKwargs, + ): client_trace_configs = list(kwargs.get("trace_configs") or []) client_trace_configs.extend(trace_configs) @@ -497,13 +543,13 @@ def instrumented_init(wrapped, instance, args, kwargs): meter_provider=meter_provider, sem_conv_opt_in_mode=sem_conv_opt_in_mode, ) - trace_config._is_instrumented_by_opentelemetry = True + setattr(trace_config, "_is_instrumented_by_opentelemetry", True) client_trace_configs.append(trace_config) kwargs["trace_configs"] = client_trace_configs return wrapped(*args, **kwargs) - wrapt.wrap_function_wrapper( + wrapt.wrap_function_wrapper( # type: ignore[reportUnknownVariableType] aiohttp.ClientSession, "__init__", instrumented_init ) @@ -533,7 +579,7 @@ class AioHttpClientInstrumentor(BaseInstrumentor): def instrumentation_dependencies(self) -> Collection[str]: return _instruments - def _instrument(self, **kwargs): + def _instrument(self, **kwargs: Unpack[InstrumentKwargs]): """Instruments aiohttp ClientSession Args: @@ -562,7 +608,7 @@ def _instrument(self, **kwargs): sem_conv_opt_in_mode=_sem_conv_opt_in_mode, ) - def _uninstrument(self, **kwargs): + def _uninstrument(self, **kwargs: Unpack[UninstrumentKwargs]): _uninstrument() @staticmethod diff --git a/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/py.typed b/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/py.typed new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/_semconv.py b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/_semconv.py index 1b1748e206..0f9e21ab70 100644 --- a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/_semconv.py +++ b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/_semconv.py @@ -12,9 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations + import os import threading from enum import Enum +from typing import Container, Mapping, MutableMapping from opentelemetry.instrumentation.utils import http_status_to_status_code from opentelemetry.semconv._incubating.attributes.http_attributes import ( @@ -63,7 +66,9 @@ USER_AGENT_ORIGINAL, ) from opentelemetry.semconv.schemas import Schemas +from opentelemetry.trace import Span from opentelemetry.trace.status import Status, StatusCode +from opentelemetry.util.types import AttributeValue # Values defined in milliseconds HTTP_DURATION_HISTOGRAM_BUCKETS_OLD = ( @@ -259,11 +264,11 @@ def _get_opentelemetry_stability_opt_in_mode( def _filter_semconv_duration_attrs( - attrs, - old_attrs, - new_attrs, - sem_conv_opt_in_mode=_StabilityMode.DEFAULT, -): + attrs: Mapping[str, AttributeValue], + old_attrs: Container[AttributeValue], + new_attrs: Container[AttributeValue], + sem_conv_opt_in_mode: _StabilityMode = _StabilityMode.DEFAULT, +) -> dict[str, AttributeValue]: filtered_attrs = {} # duration is two different metrics depending on sem_conv_opt_in_mode, so no DUP attributes allowed_attributes = ( @@ -276,11 +281,11 @@ def _filter_semconv_duration_attrs( def _filter_semconv_active_request_count_attr( - attrs, - old_attrs, - new_attrs, - sem_conv_opt_in_mode=_StabilityMode.DEFAULT, -): + attrs: Mapping[str, AttributeValue], + old_attrs: Container[AttributeValue], + new_attrs: Container[AttributeValue], + sem_conv_opt_in_mode: _StabilityMode = _StabilityMode.DEFAULT, +) -> dict[str, AttributeValue]: filtered_attrs = {} if _report_old(sem_conv_opt_in_mode): for key, val in attrs.items(): @@ -293,12 +298,20 @@ def _filter_semconv_active_request_count_attr( return filtered_attrs -def set_string_attribute(result, key, value): +def set_string_attribute( + result: MutableMapping[str, AttributeValue], + key: str, + value: AttributeValue, +) -> None: if value: result[key] = value -def set_int_attribute(result, key, value): +def set_int_attribute( + result: MutableMapping[str, AttributeValue], + key: str, + value: AttributeValue, +) -> None: if value: try: result[key] = int(value) @@ -306,7 +319,12 @@ def set_int_attribute(result, key, value): return -def _set_http_method(result, original, normalized, sem_conv_opt_in_mode): +def _set_http_method( + result: MutableMapping[str, AttributeValue], + original: str, + normalized: str, + sem_conv_opt_in_mode: _StabilityMode, +) -> None: original = original.strip() normalized = normalized.strip() # See https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-spans.md#common-attributes @@ -320,35 +338,55 @@ def _set_http_method(result, original, normalized, sem_conv_opt_in_mode): set_string_attribute(result, HTTP_REQUEST_METHOD, normalized) -def _set_http_status_code(result, code, sem_conv_opt_in_mode): +def _set_http_status_code( + result: MutableMapping[str, AttributeValue], + code: str | int, + sem_conv_opt_in_mode: _StabilityMode, +) -> None: if _report_old(sem_conv_opt_in_mode): set_int_attribute(result, HTTP_STATUS_CODE, code) if _report_new(sem_conv_opt_in_mode): set_int_attribute(result, HTTP_RESPONSE_STATUS_CODE, code) -def _set_http_url(result, url, sem_conv_opt_in_mode): +def _set_http_url( + result: MutableMapping[str, AttributeValue], + url: str, + sem_conv_opt_in_mode: _StabilityMode, +) -> None: if _report_old(sem_conv_opt_in_mode): set_string_attribute(result, HTTP_URL, url) if _report_new(sem_conv_opt_in_mode): set_string_attribute(result, URL_FULL, url) -def _set_http_scheme(result, scheme, sem_conv_opt_in_mode): +def _set_http_scheme( + result: MutableMapping[str, AttributeValue], + scheme: str, + sem_conv_opt_in_mode: _StabilityMode, +) -> None: if _report_old(sem_conv_opt_in_mode): set_string_attribute(result, HTTP_SCHEME, scheme) if _report_new(sem_conv_opt_in_mode): set_string_attribute(result, URL_SCHEME, scheme) -def _set_http_flavor_version(result, version, sem_conv_opt_in_mode): +def _set_http_flavor_version( + result: MutableMapping[str, AttributeValue], + version: str, + sem_conv_opt_in_mode: _StabilityMode, +) -> None: if _report_old(sem_conv_opt_in_mode): set_string_attribute(result, HTTP_FLAVOR, version) if _report_new(sem_conv_opt_in_mode): set_string_attribute(result, NETWORK_PROTOCOL_VERSION, version) -def _set_http_user_agent(result, user_agent, sem_conv_opt_in_mode): +def _set_http_user_agent( + result: MutableMapping[str, AttributeValue], + user_agent: str, + sem_conv_opt_in_mode: _StabilityMode, +) -> None: if _report_old(sem_conv_opt_in_mode): set_string_attribute(result, HTTP_USER_AGENT, user_agent) if _report_new(sem_conv_opt_in_mode): @@ -358,28 +396,44 @@ def _set_http_user_agent(result, user_agent, sem_conv_opt_in_mode): # Client -def _set_http_host_client(result, host, sem_conv_opt_in_mode): +def _set_http_host_client( + result: MutableMapping[str, AttributeValue], + host: str, + sem_conv_opt_in_mode: _StabilityMode, +) -> None: if _report_old(sem_conv_opt_in_mode): set_string_attribute(result, HTTP_HOST, host) if _report_new(sem_conv_opt_in_mode): set_string_attribute(result, SERVER_ADDRESS, host) -def _set_http_net_peer_name_client(result, peer_name, sem_conv_opt_in_mode): +def _set_http_net_peer_name_client( + result: MutableMapping[str, AttributeValue], + peer_name: str, + sem_conv_opt_in_mode: _StabilityMode, +) -> None: if _report_old(sem_conv_opt_in_mode): set_string_attribute(result, NET_PEER_NAME, peer_name) if _report_new(sem_conv_opt_in_mode): set_string_attribute(result, SERVER_ADDRESS, peer_name) -def _set_http_peer_port_client(result, port, sem_conv_opt_in_mode): +def _set_http_peer_port_client( + result: MutableMapping[str, AttributeValue], + port: str | int, + sem_conv_opt_in_mode: _StabilityMode, +) -> None: if _report_old(sem_conv_opt_in_mode): set_int_attribute(result, NET_PEER_PORT, port) if _report_new(sem_conv_opt_in_mode): set_int_attribute(result, SERVER_PORT, port) -def _set_http_network_protocol_version(result, version, sem_conv_opt_in_mode): +def _set_http_network_protocol_version( + result: MutableMapping[str, AttributeValue], + version: str, + sem_conv_opt_in_mode: _StabilityMode, +) -> None: if _report_old(sem_conv_opt_in_mode): set_string_attribute(result, HTTP_FLAVOR, version) if _report_new(sem_conv_opt_in_mode): @@ -389,21 +443,35 @@ def _set_http_network_protocol_version(result, version, sem_conv_opt_in_mode): # Server -def _set_http_net_host(result, host, sem_conv_opt_in_mode): +def _set_http_net_host( + result: MutableMapping[str, AttributeValue], + host: str, + sem_conv_opt_in_mode: _StabilityMode, +) -> None: if _report_old(sem_conv_opt_in_mode): set_string_attribute(result, NET_HOST_NAME, host) if _report_new(sem_conv_opt_in_mode): set_string_attribute(result, SERVER_ADDRESS, host) -def _set_http_net_host_port(result, port, sem_conv_opt_in_mode): +def _set_http_net_host_port( + result: MutableMapping[str, AttributeValue], + port: str | int, + sem_conv_opt_in_mode: _StabilityMode, +) -> None: if _report_old(sem_conv_opt_in_mode): set_int_attribute(result, NET_HOST_PORT, port) if _report_new(sem_conv_opt_in_mode): set_int_attribute(result, SERVER_PORT, port) -def _set_http_target(result, target, path, query, sem_conv_opt_in_mode): +def _set_http_target( + result: MutableMapping[str, AttributeValue], + target: str, + path: str | None, + query: str | None, + sem_conv_opt_in_mode: _StabilityMode, +) -> None: if _report_old(sem_conv_opt_in_mode): set_string_attribute(result, HTTP_TARGET, target) if _report_new(sem_conv_opt_in_mode): @@ -413,7 +481,11 @@ def _set_http_target(result, target, path, query, sem_conv_opt_in_mode): set_string_attribute(result, URL_QUERY, query) -def _set_http_host_server(result, host, sem_conv_opt_in_mode): +def _set_http_host_server( + result: MutableMapping[str, AttributeValue], + host: str, + sem_conv_opt_in_mode: _StabilityMode, +) -> None: if _report_old(sem_conv_opt_in_mode): set_string_attribute(result, HTTP_HOST, host) if _report_new(sem_conv_opt_in_mode): @@ -426,7 +498,11 @@ def _set_http_host_server(result, host, sem_conv_opt_in_mode): # net.sock.peer.addr -> client.socket.address for server spans (TODO) AND client.address if missing # https://github.com/open-telemetry/semantic-conventions/blob/v1.21.0/CHANGELOG.md#v1210-2023-07-13 # https://github.com/open-telemetry/semantic-conventions/blob/main/docs/non-normative/http-migration.md#common-attributes-across-http-client-and-server-spans -def _set_http_peer_ip_server(result, ip, sem_conv_opt_in_mode): +def _set_http_peer_ip_server( + result: MutableMapping[str, AttributeValue], + ip: str, + sem_conv_opt_in_mode: _StabilityMode, +) -> None: if _report_old(sem_conv_opt_in_mode): set_string_attribute(result, NET_PEER_IP, ip) if _report_new(sem_conv_opt_in_mode): @@ -435,14 +511,22 @@ def _set_http_peer_ip_server(result, ip, sem_conv_opt_in_mode): set_string_attribute(result, CLIENT_ADDRESS, ip) -def _set_http_peer_port_server(result, port, sem_conv_opt_in_mode): +def _set_http_peer_port_server( + result: MutableMapping[str, AttributeValue], + port: str | int, + sem_conv_opt_in_mode: _StabilityMode, +) -> None: if _report_old(sem_conv_opt_in_mode): set_int_attribute(result, NET_PEER_PORT, port) if _report_new(sem_conv_opt_in_mode): set_int_attribute(result, CLIENT_PORT, port) -def _set_http_net_peer_name_server(result, name, sem_conv_opt_in_mode): +def _set_http_net_peer_name_server( + result: MutableMapping[str, AttributeValue], + name: str, + sem_conv_opt_in_mode: _StabilityMode, +) -> None: if _report_old(sem_conv_opt_in_mode): set_string_attribute(result, NET_PEER_NAME, name) if _report_new(sem_conv_opt_in_mode): @@ -450,13 +534,13 @@ def _set_http_net_peer_name_server(result, name, sem_conv_opt_in_mode): def _set_status( - span, - metrics_attributes: dict, + span: Span, + metrics_attributes: MutableMapping[str, AttributeValue], status_code: int, status_code_str: str, server_span: bool = True, sem_conv_opt_in_mode: _StabilityMode = _StabilityMode.DEFAULT, -): +) -> None: if status_code < 0: if _report_new(sem_conv_opt_in_mode): metrics_attributes[ERROR_TYPE] = status_code_str diff --git a/pyproject.toml b/pyproject.toml index aebb47166b..97a3d433ef 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -206,6 +206,7 @@ include = [ "instrumentation-genai/opentelemetry-instrumentation-weaviate", "util/opentelemetry-util-genai", "exporter/opentelemetry-exporter-credential-provider-gcp", + "instrumentation/opentelemetry-instrumentation-aiohttp-client", ] # We should also add type hints to the test suite - It helps on finding bugs. # We are excluding for now because it's easier, and more important to add to the instrumentation packages. @@ -220,6 +221,7 @@ exclude = [ "instrumentation-genai/opentelemetry-instrumentation-weaviate/tests/**/*.py", "instrumentation-genai/opentelemetry-instrumentation-weaviate/examples/**/*.py", "util/opentelemetry-util-genai/tests/**/*.py", + "instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/**/*.py", ] [dependency-groups] diff --git a/tox.ini b/tox.ini index d85d158529..f818d455fa 100644 --- a/tox.ini +++ b/tox.ini @@ -1091,6 +1091,7 @@ deps = {toxinidir}/instrumentation/opentelemetry-instrumentation-aiokafka[instruments] {toxinidir}/instrumentation/opentelemetry-instrumentation-asyncclick[instruments] {toxinidir}/exporter/opentelemetry-exporter-credential-provider-gcp + {toxinidir}/instrumentation/opentelemetry-instrumentation-aiohttp-client[instruments] commands = pyright