Skip to content

Commit c8d9555

Browse files
Merge branch 'main' into feature/http-route-in-metric
2 parents 304c88b + e6c27e0 commit c8d9555

File tree

35 files changed

+726
-1494
lines changed

35 files changed

+726
-1494
lines changed

.github/workflows/instrumentations_0.yml

-11
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ jobs:
6666
- "redis"
6767
- "remoulade"
6868
- "requests"
69-
- "sklearn"
7069
- "sqlalchemy"
7170
- "sqlite3"
7271
- "starlette"
@@ -75,14 +74,6 @@ jobs:
7574
- "tortoiseorm"
7675
os: [ubuntu-20.04]
7776
exclude:
78-
- python-version: py39
79-
package: "sklearn"
80-
- python-version: py310
81-
package: "sklearn"
82-
- python-version: py311
83-
package: "sklearn"
84-
- python-version: py312
85-
package: "sklearn"
8677
- python-version: py312
8778
package: "boto"
8879
- python-version: py312
@@ -103,8 +94,6 @@ jobs:
10394
package: "remoulade"
10495
- python-version: pypy3
10596
package: "requests"
106-
- python-version: pypy3
107-
package: "sklearn"
10897
- python-version: pypy3
10998
package: "confluent-kafka"
11099
- python-version: pypy3

.github/workflows/lint.yml

-28
Original file line numberDiff line numberDiff line change
@@ -93,31 +93,3 @@ jobs:
9393
key: v7-build-tox-cache-${{ matrix.package }}-${{ hashFiles('tox.ini', 'gen-requirements.txt', 'dev-requirements.txt') }}
9494
- name: run tox
9595
run: tox -e lint-${{ matrix.package }}
96-
97-
lint-3_8:
98-
strategy:
99-
fail-fast: false # ensures the entire test matrix is run, even if one permutation fails
100-
matrix:
101-
package:
102-
- "instrumentation-sklearn"
103-
os: [ubuntu-20.04]
104-
runs-on: ubuntu-20.04
105-
steps:
106-
- name: Checkout Contrib Repo @ SHA - ${{ github.sha }}
107-
uses: actions/checkout@v4
108-
- name: Set up Python 3.8
109-
uses: actions/setup-python@v5
110-
with:
111-
python-version: 3.8
112-
- name: Install tox
113-
run: pip install tox
114-
- name: Cache tox environment
115-
# Preserves .tox directory between runs for faster installs
116-
uses: actions/cache@v4
117-
with:
118-
path: |
119-
.tox
120-
~/.cache/pip
121-
key: v7-build-tox-cache-${{ matrix.package }}-${{ hashFiles('tox.ini', 'gen-requirements.txt', 'dev-requirements.txt') }}
122-
- name: run tox
123-
run: tox -e lint-${{ matrix.package }}

CHANGELOG.md

+11-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
- `opentelemetry-instrumentation-flask` Add `http.route` and `http.target` to metric attributes
1313
([#2621](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2621))
14+
- `opentelemetry-instrumentation-sklearn` Deprecated the sklearn instrumentation
15+
([#2708](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2708))
1416
- `opentelemetry-instrumentation-pyramid` Record exceptions raised when serving a request
1517
([#2622](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2622))
1618
- `opentelemetry-sdk-extension-aws` Add AwsXrayLambdaPropagator
@@ -31,6 +33,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3133
([#2630](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2630))
3234
- `opentelemetry-instrumentation-system-metrics` Add support for capture open file descriptors
3335
([#2652](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2652))
36+
- `opentelemetry-instrumentation-httpx` Add support for instrument client with proxy
37+
([#2664](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2664))
38+
- `opentelemetry-instrumentation-aiohttp-client` Implement new semantic convention opt-in migration
39+
([#2673](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2673))
40+
- `opentelemetry-instrumentation-django` Add `http.target` to Django duration metric attributes
41+
([#2624](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2624))
3442

3543
### Breaking changes
3644

@@ -42,7 +50,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4250
([#2682](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2682))
4351

4452
### Fixed
45-
53+
- Handle `redis.exceptions.WatchError` as a non-error event in redis instrumentation
54+
([#2668](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2668))
4655
- `opentelemetry-instrumentation-httpx` Ensure httpx.get or httpx.request like methods are instrumented
4756
([#2538](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2538))
4857
- Add Python 3.12 support
@@ -58,7 +67,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5867
- `opentelemetry-instrumentation-asgi` Fix generation of `http.target` and `http.url` attributes for ASGI apps
5968
using sub apps
6069
([#2477](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2477))
61-
- `opentelemetry-instrumentation-aws-lambda` Bugfix: AWS Lambda event source key incorrect for SNS in instrumentation library.
70+
- `opentelemetry-instrumentation-aws-lambda` Bugfix: AWS Lambda event source key incorrect for SNS in instrumentation library.
6271
([#2612](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2612))
6372
- `opentelemetry-instrumentation-asyncio` instrumented `asyncio.wait_for` properly raises `asyncio.TimeoutError` as expected
6473
([#2637](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2637))

eachdist.ini

-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ packages=
5454
[lintroots]
5555
extraroots=examples/*,scripts/
5656
subglob=*.py,tests/,test/,src/*,examples/*
57-
ignore=sklearn
5857

5958
[testroots]
6059
extraroots=examples/*,tests/

instrumentation/README.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
| Instrumentation | Supported Packages | Metrics support | Semconv status |
33
| --------------- | ------------------ | --------------- | -------------- |
44
| [opentelemetry-instrumentation-aio-pika](./opentelemetry-instrumentation-aio-pika) | aio_pika >= 7.2.0, < 10.0.0 | No | experimental
5-
| [opentelemetry-instrumentation-aiohttp-client](./opentelemetry-instrumentation-aiohttp-client) | aiohttp ~= 3.0 | No | experimental
5+
| [opentelemetry-instrumentation-aiohttp-client](./opentelemetry-instrumentation-aiohttp-client) | aiohttp ~= 3.0 | No | migration
66
| [opentelemetry-instrumentation-aiohttp-server](./opentelemetry-instrumentation-aiohttp-server) | aiohttp ~= 3.0 | No | experimental
77
| [opentelemetry-instrumentation-aiopg](./opentelemetry-instrumentation-aiopg) | aiopg >= 0.13.0, < 2.0.0 | No | experimental
88
| [opentelemetry-instrumentation-asgi](./opentelemetry-instrumentation-asgi) | asgiref ~= 3.0 | Yes | migration
@@ -38,7 +38,6 @@
3838
| [opentelemetry-instrumentation-redis](./opentelemetry-instrumentation-redis) | redis >= 2.6 | No | experimental
3939
| [opentelemetry-instrumentation-remoulade](./opentelemetry-instrumentation-remoulade) | remoulade >= 0.50 | No | experimental
4040
| [opentelemetry-instrumentation-requests](./opentelemetry-instrumentation-requests) | requests ~= 2.0 | Yes | migration
41-
| [opentelemetry-instrumentation-sklearn](./opentelemetry-instrumentation-sklearn) | scikit-learn ~= 0.24.0 | No | experimental
4241
| [opentelemetry-instrumentation-sqlalchemy](./opentelemetry-instrumentation-sqlalchemy) | sqlalchemy | Yes | experimental
4342
| [opentelemetry-instrumentation-sqlite3](./opentelemetry-instrumentation-sqlite3) | sqlite3 | No | experimental
4443
| [opentelemetry-instrumentation-starlette](./opentelemetry-instrumentation-starlette) | starlette ~= 0.13.0 | Yes | experimental

instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py

+81-18
Original file line numberDiff line numberDiff line change
@@ -90,19 +90,28 @@ def response_hook(span: Span, params: typing.Union[
9090

9191
from opentelemetry import context as context_api
9292
from opentelemetry import trace
93+
from opentelemetry.instrumentation._semconv import (
94+
_get_schema_url,
95+
_HTTPStabilityMode,
96+
_OpenTelemetrySemanticConventionStability,
97+
_OpenTelemetryStabilitySignalType,
98+
_report_new,
99+
_set_http_method,
100+
_set_http_url,
101+
_set_status,
102+
)
93103
from opentelemetry.instrumentation.aiohttp_client.package import _instruments
94104
from opentelemetry.instrumentation.aiohttp_client.version import __version__
95105
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
96106
from opentelemetry.instrumentation.utils import (
97-
http_status_to_status_code,
98107
is_instrumentation_enabled,
99108
unwrap,
100109
)
101110
from opentelemetry.propagate import inject
102-
from opentelemetry.semconv.trace import SpanAttributes
111+
from opentelemetry.semconv.attributes.error_attributes import ERROR_TYPE
103112
from opentelemetry.trace import Span, SpanKind, TracerProvider, get_tracer
104113
from opentelemetry.trace.status import Status, StatusCode
105-
from opentelemetry.util.http import remove_url_credentials
114+
from opentelemetry.util.http import remove_url_credentials, sanitize_method
106115

107116
_UrlFilterT = typing.Optional[typing.Callable[[yarl.URL], str]]
108117
_RequestHookT = typing.Optional[
@@ -122,11 +131,46 @@ def response_hook(span: Span, params: typing.Union[
122131
]
123132

124133

134+
def _get_span_name(method: str) -> str:
135+
method = sanitize_method(method.upper().strip())
136+
if method == "_OTHER":
137+
method = "HTTP"
138+
139+
return method
140+
141+
142+
def _set_http_status_code_attribute(
143+
span,
144+
status_code,
145+
metric_attributes=None,
146+
sem_conv_opt_in_mode=_HTTPStabilityMode.DEFAULT,
147+
):
148+
status_code_str = str(status_code)
149+
try:
150+
status_code = int(status_code)
151+
except ValueError:
152+
status_code = -1
153+
if metric_attributes is None:
154+
metric_attributes = {}
155+
# When we have durations we should set metrics only once
156+
# Also the decision to include status code on a histogram should
157+
# not be dependent on tracing decisions.
158+
_set_status(
159+
span,
160+
metric_attributes,
161+
status_code,
162+
status_code_str,
163+
server_span=False,
164+
sem_conv_opt_in_mode=sem_conv_opt_in_mode,
165+
)
166+
167+
125168
def create_trace_config(
126169
url_filter: _UrlFilterT = None,
127170
request_hook: _RequestHookT = None,
128171
response_hook: _ResponseHookT = None,
129172
tracer_provider: TracerProvider = None,
173+
sem_conv_opt_in_mode: _HTTPStabilityMode = _HTTPStabilityMode.DEFAULT,
130174
) -> aiohttp.TraceConfig:
131175
"""Create an aiohttp-compatible trace configuration.
132176
@@ -167,9 +211,12 @@ def create_trace_config(
167211
__name__,
168212
__version__,
169213
tracer_provider,
170-
schema_url="https://opentelemetry.io/schemas/1.11.0",
214+
schema_url=_get_schema_url(sem_conv_opt_in_mode),
171215
)
172216

217+
# TODO: Use this when we have durations for aiohttp-client
218+
metric_attributes = {}
219+
173220
def _end_trace(trace_config_ctx: types.SimpleNamespace):
174221
context_api.detach(trace_config_ctx.token)
175222
trace_config_ctx.span.end()
@@ -183,18 +230,22 @@ async def on_request_start(
183230
trace_config_ctx.span = None
184231
return
185232

186-
http_method = params.method.upper()
187-
request_span_name = f"{http_method}"
233+
http_method = params.method
234+
request_span_name = _get_span_name(http_method)
188235
request_url = (
189236
remove_url_credentials(trace_config_ctx.url_filter(params.url))
190237
if callable(trace_config_ctx.url_filter)
191238
else remove_url_credentials(str(params.url))
192239
)
193240

194-
span_attributes = {
195-
SpanAttributes.HTTP_METHOD: http_method,
196-
SpanAttributes.HTTP_URL: request_url,
197-
}
241+
span_attributes = {}
242+
_set_http_method(
243+
span_attributes,
244+
http_method,
245+
request_span_name,
246+
sem_conv_opt_in_mode,
247+
)
248+
_set_http_url(span_attributes, request_url, sem_conv_opt_in_mode)
198249

199250
trace_config_ctx.span = trace_config_ctx.tracer.start_span(
200251
request_span_name, kind=SpanKind.CLIENT, attributes=span_attributes
@@ -219,14 +270,13 @@ async def on_request_end(
219270

220271
if callable(response_hook):
221272
response_hook(trace_config_ctx.span, params)
273+
_set_http_status_code_attribute(
274+
trace_config_ctx.span,
275+
params.response.status,
276+
metric_attributes,
277+
sem_conv_opt_in_mode,
278+
)
222279

223-
if trace_config_ctx.span.is_recording():
224-
trace_config_ctx.span.set_status(
225-
Status(http_status_to_status_code(int(params.response.status)))
226-
)
227-
trace_config_ctx.span.set_attribute(
228-
SpanAttributes.HTTP_STATUS_CODE, params.response.status
229-
)
230280
_end_trace(trace_config_ctx)
231281

232282
async def on_request_exception(
@@ -238,7 +288,13 @@ async def on_request_exception(
238288
return
239289

240290
if trace_config_ctx.span.is_recording() and params.exception:
241-
trace_config_ctx.span.set_status(Status(StatusCode.ERROR))
291+
exc_type = type(params.exception).__qualname__
292+
if _report_new(sem_conv_opt_in_mode):
293+
trace_config_ctx.span.set_attribute(ERROR_TYPE, exc_type)
294+
295+
trace_config_ctx.span.set_status(
296+
Status(StatusCode.ERROR, exc_type)
297+
)
242298
trace_config_ctx.span.record_exception(params.exception)
243299

244300
if callable(response_hook):
@@ -271,6 +327,7 @@ def _instrument(
271327
trace_configs: typing.Optional[
272328
typing.Sequence[aiohttp.TraceConfig]
273329
] = None,
330+
sem_conv_opt_in_mode: _HTTPStabilityMode = _HTTPStabilityMode.DEFAULT,
274331
):
275332
"""Enables tracing of all ClientSessions
276333
@@ -293,6 +350,7 @@ def instrumented_init(wrapped, instance, args, kwargs):
293350
request_hook=request_hook,
294351
response_hook=response_hook,
295352
tracer_provider=tracer_provider,
353+
sem_conv_opt_in_mode=sem_conv_opt_in_mode,
296354
)
297355
trace_config._is_instrumented_by_opentelemetry = True
298356
client_trace_configs.append(trace_config)
@@ -344,12 +402,17 @@ def _instrument(self, **kwargs):
344402
``trace_configs``: An optional list of aiohttp.TraceConfig items, allowing customize enrichment of spans
345403
based on aiohttp events (see specification: https://docs.aiohttp.org/en/stable/tracing_reference.html)
346404
"""
405+
_OpenTelemetrySemanticConventionStability._initialize()
406+
_sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
407+
_OpenTelemetryStabilitySignalType.HTTP,
408+
)
347409
_instrument(
348410
tracer_provider=kwargs.get("tracer_provider"),
349411
url_filter=kwargs.get("url_filter"),
350412
request_hook=kwargs.get("request_hook"),
351413
response_hook=kwargs.get("response_hook"),
352414
trace_configs=kwargs.get("trace_configs"),
415+
sem_conv_opt_in_mode=_sem_conv_opt_in_mode,
353416
)
354417

355418
def _uninstrument(self, **kwargs):

instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/package.py

+4
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,7 @@
1414

1515

1616
_instruments = ("aiohttp ~= 3.0",)
17+
18+
_supports_metrics = False
19+
20+
_semconv_status = "migration"

0 commit comments

Comments
 (0)