Skip to content

Commit 0222c54

Browse files
authored
Merge branch 'main' into botocore-stream-close-handle
2 parents df1d4d4 + dc35754 commit 0222c54

File tree

26 files changed

+478
-172
lines changed

26 files changed

+478
-172
lines changed

CHANGELOG.md

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111
1212
## Unreleased
1313

14+
### Fixed
15+
16+
- `opentelemetry-instrumentation-fastapi`: fix wrapping of middlewares
17+
([#3012](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3012))
18+
- `opentelemetry-instrumentation-falcon`: proper bucket boundaries in stable semconv http duration
19+
([#3525](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3525))
20+
- `opentelemetry-instrumentation-wsgi`: add explicit http duration buckets for stable semconv
21+
([#3527](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3527))
22+
- `opentelemetry-instrumentation-asgi`: add explicit http duration buckets for stable semconv
23+
([#3526](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3526))
24+
- `opentelemetry-instrumentation-flask`: proper bucket boundaries in stable semconv http duration
25+
([#3523](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3523))
26+
- `opentelemetry-instrumentation-django`: proper bucket boundaries in stable semconv http duration
27+
([#3524](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3524))
28+
- `opentelemetry-instrumentation-grpc`: support non-list interceptors
29+
([#3520](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3520))
30+
- `opentelemetry-instrumentation-botocore` Ensure spans end on early stream closure for Bedrock Streaming APIs
31+
([#3481](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3481))
32+
1433
### Breaking changes
1534

1635
- `opentelemetry-instrumentation-botocore` Use `cloud.region` instead of `aws.region` span attribute as per semantic conventions.
1736
([#3474](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3474))
37+
- `opentelemetry-instrumentation-fastapi`: Drop support for FastAPI versions earlier than `0.92`
38+
([#3012](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3012))
1839

19-
### Fixed
20-
21-
- `opentelemetry-instrumentation-botocore` Ensure spans end on early stream closure for Bedrock Streaming APIs
22-
([#3481](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3481))
2340

2441
## Version 1.33.0/0.54b0 (2025-05-09)
2542

RELEASING.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,16 @@ The workflow will create two pull requests, one against the `main` and one again
4141
* Press the "Run workflow" button, then select the release branch from the dropdown list,
4242
e.g. `release/v1.9.x`, then enter the pull request number that you want to backport,
4343
then click the "Run workflow" button below that.
44+
* Add the label `backport` to the generated pull request.
45+
* In case label automation doesn't work, just close and reopen the PR so that the workflow will take into account the label automation we have in place.
4446
* Review and merge the backport pull request that it generates.
4547
* Merge a pull request to the release branch updating the `CHANGELOG.md`.
4648
* The heading for the unreleased entries should be `## Unreleased`.
4749
* Run the [Prepare patch release workflow](https://github.com/open-telemetry/opentelemetry-python-contrib/actions/workflows/prepare-patch-release.yml).
4850
* Press the "Run workflow" button, then select the release branch from the dropdown list,
4951
e.g. `release/v1.9.x`, and click the "Run workflow" button below that.
5052
* Review and merge the pull request that it creates for updating the version.
53+
* Note: If you are doing a patch release in `-contrib` repo, you should also do an equivalent patch release in `-core` repo (even if there's no fix to release), otherwise tests in CI will fail.
5154

5255
### Preparing a patch release for individual package
5356

docs/nitpick-exceptions.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ py-class=
4444
psycopg.Connection
4545
psycopg.AsyncConnection
4646
ObjectProxy
47+
fastapi.applications.FastAPI
4748

4849
any=
4950
; API

instrumentation/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
| --------------- | ------------------ | --------------- | -------------- |
44
| [opentelemetry-instrumentation-aio-pika](./opentelemetry-instrumentation-aio-pika) | aio_pika >= 7.2.0, < 10.0.0 | No | development
55
| [opentelemetry-instrumentation-aiohttp-client](./opentelemetry-instrumentation-aiohttp-client) | aiohttp ~= 3.0 | No | migration
6-
| [opentelemetry-instrumentation-aiohttp-server](./opentelemetry-instrumentation-aiohttp-server) | aiohttp ~= 3.0 | No | development
6+
| [opentelemetry-instrumentation-aiohttp-server](./opentelemetry-instrumentation-aiohttp-server) | aiohttp ~= 3.0 | Yes | development
77
| [opentelemetry-instrumentation-aiokafka](./opentelemetry-instrumentation-aiokafka) | aiokafka >= 0.8, < 1.0 | No | development
88
| [opentelemetry-instrumentation-aiopg](./opentelemetry-instrumentation-aiopg) | aiopg >= 0.13.0, < 2.0.0 | No | development
99
| [opentelemetry-instrumentation-asgi](./opentelemetry-instrumentation-asgi) | asgiref ~= 3.0 | Yes | migration
@@ -22,7 +22,7 @@
2222
| [opentelemetry-instrumentation-django](./opentelemetry-instrumentation-django) | django >= 1.10 | Yes | development
2323
| [opentelemetry-instrumentation-elasticsearch](./opentelemetry-instrumentation-elasticsearch) | elasticsearch >= 6.0 | No | development
2424
| [opentelemetry-instrumentation-falcon](./opentelemetry-instrumentation-falcon) | falcon >= 1.4.1, < 5.0.0 | Yes | migration
25-
| [opentelemetry-instrumentation-fastapi](./opentelemetry-instrumentation-fastapi) | fastapi ~= 0.58 | Yes | migration
25+
| [opentelemetry-instrumentation-fastapi](./opentelemetry-instrumentation-fastapi) | fastapi ~= 0.92 | Yes | migration
2626
| [opentelemetry-instrumentation-flask](./opentelemetry-instrumentation-flask) | flask >= 1.0 | Yes | migration
2727
| [opentelemetry-instrumentation-grpc](./opentelemetry-instrumentation-grpc) | grpcio >= 1.42.0 | No | development
2828
| [opentelemetry-instrumentation-httpx](./opentelemetry-instrumentation-httpx) | httpx >= 0.18.0 | No | migration

instrumentation/opentelemetry-instrumentation-aiohttp-server/src/opentelemetry/instrumentation/aiohttp_server/package.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@
1414

1515

1616
_instruments = ("aiohttp ~= 3.0",)
17+
18+
_supports_metrics = True

instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, A
202202

203203
from opentelemetry import context, trace
204204
from opentelemetry.instrumentation._semconv import (
205+
HTTP_DURATION_HISTOGRAM_BUCKETS_NEW,
205206
_filter_semconv_active_request_count_attr,
206207
_filter_semconv_duration_attrs,
207208
_get_schema_url,
@@ -589,6 +590,7 @@ def __init__(
589590
name=HTTP_SERVER_REQUEST_DURATION,
590591
description="Duration of HTTP server requests.",
591592
unit="s",
593+
explicit_bucket_boundaries_advisory=HTTP_DURATION_HISTOGRAM_BUCKETS_NEW,
592594
)
593595
self.server_response_size_histogram = None
594596
if _report_old(sem_conv_opt_in_mode):
@@ -665,9 +667,9 @@ def __init__(
665667
# pylint: disable=too-many-statements
666668
async def __call__(
667669
self,
668-
scope: dict[str, Any],
669-
receive: Callable[[], Awaitable[dict[str, Any]]],
670-
send: Callable[[dict[str, Any]], Awaitable[None]],
670+
scope: typing.MutableMapping[str, Any],
671+
receive: Callable[[], Awaitable[typing.MutableMapping[str, Any]]],
672+
send: Callable[[typing.MutableMapping[str, Any]], Awaitable[None]],
671673
) -> None:
672674
"""The ASGI application
673675

instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import opentelemetry.instrumentation.asgi as otel_asgi
2424
from opentelemetry import trace as trace_api
2525
from opentelemetry.instrumentation._semconv import (
26+
HTTP_DURATION_HISTOGRAM_BUCKETS_NEW,
2627
OTEL_SEMCONV_STABILITY_OPT_IN,
2728
_OpenTelemetrySemanticConventionStability,
2829
_server_active_requests_count_attrs_new,
@@ -1245,6 +1246,7 @@ async def test_asgi_metrics(self):
12451246
self.assertTrue(number_data_point_seen and histogram_data_point_seen)
12461247

12471248
async def test_asgi_metrics_new_semconv(self):
1249+
# pylint: disable=too-many-nested-blocks
12481250
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
12491251
self.seed_app(app)
12501252
await self.send_default_request()
@@ -1274,6 +1276,11 @@ async def test_asgi_metrics_new_semconv(self):
12741276
for point in data_points:
12751277
if isinstance(point, HistogramDataPoint):
12761278
self.assertEqual(point.count, 3)
1279+
if metric.name == "http.server.request.duration":
1280+
self.assertEqual(
1281+
point.explicit_bounds,
1282+
HTTP_DURATION_HISTOGRAM_BUCKETS_NEW,
1283+
)
12771284
histogram_data_point_seen = True
12781285
if isinstance(point, NumberDataPoint):
12791286
number_data_point_seen = True
@@ -1284,6 +1291,7 @@ async def test_asgi_metrics_new_semconv(self):
12841291
self.assertTrue(number_data_point_seen and histogram_data_point_seen)
12851292

12861293
async def test_asgi_metrics_both_semconv(self):
1294+
# pylint: disable=too-many-nested-blocks
12871295
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
12881296
self.seed_app(app)
12891297
await self.send_default_request()
@@ -1313,6 +1321,11 @@ async def test_asgi_metrics_both_semconv(self):
13131321
for point in data_points:
13141322
if isinstance(point, HistogramDataPoint):
13151323
self.assertEqual(point.count, 3)
1324+
if metric.name == "http.server.request.duration":
1325+
self.assertEqual(
1326+
point.explicit_bounds,
1327+
HTTP_DURATION_HISTOGRAM_BUCKETS_NEW,
1328+
)
13161329
histogram_data_point_seen = True
13171330
if isinstance(point, NumberDataPoint):
13181331
number_data_point_seen = True

instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ def response_hook(span, request, response):
246246
from django.core.exceptions import ImproperlyConfigured
247247

248248
from opentelemetry.instrumentation._semconv import (
249+
HTTP_DURATION_HISTOGRAM_BUCKETS_NEW,
249250
_get_schema_url,
250251
_OpenTelemetrySemanticConventionStability,
251252
_OpenTelemetryStabilitySignalType,
@@ -378,6 +379,7 @@ def _instrument(self, **kwargs):
378379
name=HTTP_SERVER_REQUEST_DURATION,
379380
description="Duration of HTTP server requests.",
380381
unit="s",
382+
explicit_bucket_boundaries_advisory=HTTP_DURATION_HISTOGRAM_BUCKETS_NEW,
381383
)
382384
_DjangoMiddleware._active_request_counter = (
383385
create_http_server_active_requests(meter)

instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626

2727
from opentelemetry import trace
2828
from opentelemetry.instrumentation._semconv import (
29+
HTTP_DURATION_HISTOGRAM_BUCKETS_NEW,
30+
HTTP_DURATION_HISTOGRAM_BUCKETS_OLD,
2931
OTEL_SEMCONV_STABILITY_OPT_IN,
3032
_OpenTelemetrySemanticConventionStability,
3133
)
@@ -814,6 +816,10 @@ def test_wsgi_metrics_new_semconv(self):
814816
expected_duration_attributes,
815817
dict(point.attributes),
816818
)
819+
self.assertEqual(
820+
point.explicit_bounds,
821+
HTTP_DURATION_HISTOGRAM_BUCKETS_NEW,
822+
)
817823
if isinstance(point, NumberDataPoint):
818824
number_data_point_seen = True
819825
self.assertEqual(point.value, 0)
@@ -886,6 +892,10 @@ def test_wsgi_metrics_both_semconv(self):
886892
expected_duration_attributes_new,
887893
dict(point.attributes),
888894
)
895+
self.assertEqual(
896+
point.explicit_bounds,
897+
HTTP_DURATION_HISTOGRAM_BUCKETS_NEW,
898+
)
889899
elif metric.name == "http.server.duration":
890900
self.assertAlmostEqual(
891901
duration, point.sum, delta=100
@@ -894,6 +904,10 @@ def test_wsgi_metrics_both_semconv(self):
894904
expected_duration_attributes_old,
895905
dict(point.attributes),
896906
)
907+
self.assertEqual(
908+
point.explicit_bounds,
909+
HTTP_DURATION_HISTOGRAM_BUCKETS_OLD,
910+
)
897911
if isinstance(point, NumberDataPoint):
898912
number_data_point_seen = True
899913
self.assertEqual(point.value, 0)

instrumentation/opentelemetry-instrumentation-elasticsearch/tests/test_elasticsearch.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@
3131
ElasticsearchInstrumentor,
3232
)
3333
from opentelemetry.instrumentation.elasticsearch.utils import sanitize_body
34-
from opentelemetry.semconv.trace import SpanAttributes
34+
from opentelemetry.semconv._incubating.attributes.db_attributes import (
35+
DB_STATEMENT,
36+
DB_SYSTEM,
37+
)
3538
from opentelemetry.test.test_base import TestBase
3639
from opentelemetry.trace import StatusCode
3740

@@ -76,15 +79,15 @@ def get_elasticsearch_client(*args, **kwargs):
7679
)
7780
class TestElasticsearchIntegration(TestBase):
7881
search_attributes = {
79-
SpanAttributes.DB_SYSTEM: "elasticsearch",
82+
DB_SYSTEM: "elasticsearch",
8083
"elasticsearch.url": "/test-index/_search",
8184
"elasticsearch.method": helpers.dsl_search_method,
8285
"elasticsearch.target": "test-index",
83-
SpanAttributes.DB_STATEMENT: str({"query": {"bool": {"filter": "?"}}}),
86+
DB_STATEMENT: str({"query": {"bool": {"filter": "?"}}}),
8487
}
8588

8689
create_attributes = {
87-
SpanAttributes.DB_SYSTEM: "elasticsearch",
90+
DB_SYSTEM: "elasticsearch",
8891
"elasticsearch.url": "/test-index",
8992
"elasticsearch.method": "HEAD",
9093
}
@@ -361,13 +364,13 @@ def test_dsl_create(self, request_mock):
361364
)
362365

363366
attributes = {
364-
SpanAttributes.DB_SYSTEM: "elasticsearch",
367+
DB_SYSTEM: "elasticsearch",
365368
"elasticsearch.url": "/test-index",
366369
"elasticsearch.method": "PUT",
367370
}
368371
self.assertSpanHasAttributes(span2, attributes)
369372
self.assertEqual(
370-
literal_eval(span2.attributes[SpanAttributes.DB_STATEMENT]),
373+
literal_eval(span2.attributes[DB_STATEMENT]),
371374
helpers.dsl_create_statement,
372375
)
373376

@@ -408,13 +411,13 @@ def test_dsl_index(self, request_mock):
408411
span = spans[0]
409412
self.assertEqual(span.name, helpers.dsl_index_span_name)
410413
attributes = {
411-
SpanAttributes.DB_SYSTEM: "elasticsearch",
414+
DB_SYSTEM: "elasticsearch",
412415
"elasticsearch.url": helpers.dsl_index_url,
413416
"elasticsearch.method": "PUT",
414417
}
415418
self.assertSpanHasAttributes(span, attributes)
416419
self.assertEqual(
417-
literal_eval(span.attributes[SpanAttributes.DB_STATEMENT]),
420+
literal_eval(span.attributes[DB_STATEMENT]),
418421
{
419422
"body": "A few words here, a few words there",
420423
"title": "About searching",

0 commit comments

Comments
 (0)