starlette: Remove maximum version constraint (#3456)

* ISSUE-3317: Remove maximum version constraint on starlette, by fixing unit tests. Fixed some warnings in unit tests.

* Updae changelog

* Implement code review remarks: update starlette dependencies in bootstrap/test-requirements. Use setUp/tearDown iso decorator on test class

* Increase minimal version of starlette to 0.37.2 to have functional 'oldest' tests.

* add uv.lock

* Revert "add uv.lock"

This reverts commit 08df2bee1ebe6943bcb6c2a66bd1b903f1fa0cde.

* Prevent massive changes of uv.lock due to newer uv which adds upload-time keyword

* Update test-requirements.in file of starlette instrumentation

* fixes

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* fix tests

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* increase delta

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* using same delta as fastapi

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* commit uv.lock back

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>

* Update CHANGELOG.md

Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>

* Update CHANGELOG.md

---------

Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: emdneto <9735060+emdneto@users.noreply.github.com>
Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
This commit is contained in:
Mattias De Charleroy
2025-05-23 14:22:31 +02:00
committed by GitHub
parent 4e42ed674a
commit e2ba6d43c0
9 changed files with 2441 additions and 1217 deletions

View File

@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#3533](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3533))
- `opentelemetry-instrumentation-fastapi`: fix wrapping of middlewares
([#3012](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3012))
- `opentelemetry-instrumentation-starlette` Remove max version constraint on starlette
([#3456](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3456))
- `opentelemetry-instrumentation-urllib3`: proper bucket boundaries in stable semconv http duration metrics
([#3518](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3518))
- `opentelemetry-instrumentation-urllib`: proper bucket boundaries in stable semconv http duration metrics
@ -70,7 +72,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `opentelemetry-instrumentation-botocore` Capture server attributes for botocore API calls
([#3448](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3448))
## Version 1.32.0/0.53b0 (2025-04-10)
### Added

View File

@ -44,7 +44,7 @@
| [opentelemetry-instrumentation-requests](./opentelemetry-instrumentation-requests) | requests ~= 2.0 | Yes | migration
| [opentelemetry-instrumentation-sqlalchemy](./opentelemetry-instrumentation-sqlalchemy) | sqlalchemy >= 1.0.0, < 2.1.0 | Yes | development
| [opentelemetry-instrumentation-sqlite3](./opentelemetry-instrumentation-sqlite3) | sqlite3 | No | development
| [opentelemetry-instrumentation-starlette](./opentelemetry-instrumentation-starlette) | starlette >= 0.13, <0.15 | Yes | development
| [opentelemetry-instrumentation-starlette](./opentelemetry-instrumentation-starlette) | starlette >= 0.13 | Yes | development
| [opentelemetry-instrumentation-system-metrics](./opentelemetry-instrumentation-system-metrics) | psutil >= 5 | No | development
| [opentelemetry-instrumentation-threading](./opentelemetry-instrumentation-threading) | threading | No | development
| [opentelemetry-instrumentation-tornado](./opentelemetry-instrumentation-tornado) | tornado >= 5.1.1 | Yes | development

View File

@ -34,7 +34,7 @@ dependencies = [
]
[project.optional-dependencies]
instruments = ["starlette >= 0.13, <0.15"]
instruments = ["starlette >= 0.13"]
[project.entry-points.opentelemetry_instrumentor]
starlette = "opentelemetry.instrumentation.starlette:StarletteInstrumentor"

View File

@ -332,7 +332,7 @@ class _InstrumentedStarlette(applications.Starlette):
_InstrumentedStarlette._instrumented_starlette_apps.add(self)
def __del__(self):
_InstrumentedStarlette._instrumented_starlette_apps.remove(self)
_InstrumentedStarlette._instrumented_starlette_apps.discard(self)
def _get_route_details(scope: dict[str, Any]) -> str | None:

View File

@ -13,6 +13,6 @@
# limitations under the License.
_instruments = ("starlette >= 0.13, <0.15",)
_instruments = ("starlette >= 0.13",)
_supports_metrics = True

View File

@ -17,9 +17,13 @@
# opentelemetry-instrumentation-asgi
# opentelemetry-instrumentation-starlette
anyio==4.5.2 ; python_full_version < '3.9'
# via httpx
# via
# httpx
# starlette
anyio==4.8.0 ; python_full_version >= '3.9'
# via httpx
# via
# httpx
# starlette
asgiref==3.8.1
# via opentelemetry-instrumentation-asgi
certifi==2025.1.31
@ -31,10 +35,6 @@ charset-normalizer==3.4.1
# via requests
colorama==0.4.6 ; sys_platform == 'win32'
# via pytest
deprecated==1.2.18
# via
# opentelemetry-api
# opentelemetry-semantic-conventions
exceptiongroup==1.2.2 ; python_full_version < '3.11'
# via
# anyio
@ -72,22 +72,25 @@ requests==2.32.3
# -r instrumentation/opentelemetry-instrumentation-starlette/test-requirements.in
sniffio==1.3.1
# via anyio
starlette==0.14.2
starlette==0.44.0 ; python_full_version < '3.9'
# via opentelemetry-instrumentation-starlette
starlette==0.46.2 ; python_full_version >= '3.9'
# via opentelemetry-instrumentation-starlette
tomli==2.2.1 ; python_full_version < '3.11'
# via pytest
typing-extensions==4.12.2 ; python_full_version < '3.13'
typing-extensions==4.12.2
# via
# anyio
# asgiref
# opentelemetry-api
# opentelemetry-semantic-conventions
# starlette
urllib3==2.2.3 ; python_full_version < '3.9'
# via requests
urllib3==2.3.0 ; python_full_version >= '3.9'
# via requests
wrapt==1.17.2
# via
# deprecated
# opentelemetry-instrumentation
wrapt==1.14.1
# via opentelemetry-instrumentation
zipp==3.20.2 ; python_full_version < '3.9'
# via importlib-metadata
zipp==3.21.0 ; python_full_version >= '3.9'

View File

@ -230,7 +230,7 @@ class TestStarletteManualInstrumentation(TestBase):
dict(point.attributes), expected_duration_attributes
)
if metric.name == "http.server.duration":
self.assertAlmostEqual(duration, point.sum, delta=30)
self.assertAlmostEqual(duration, point.sum, delta=350)
elif metric.name == "http.server.response.size":
self.assertEqual(response_size, point.sum)
elif metric.name == "http.server.request.size":
@ -667,17 +667,22 @@ class TestBaseWithCustomHeaders(TestBase):
class TestHTTPAppWithCustomHeaders(TestBaseWithCustomHeaders):
@patch.dict(
"os.environ",
{
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS: ".*my-secret.*",
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST: "Custom-Test-Header-1,Custom-Test-Header-2,Custom-Test-Header-3,Regex-Test-Header-.*,Regex-Invalid-Test-Header-.*,.*my-secret.*",
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE: "Custom-Test-Header-1,Custom-Test-Header-2,Custom-Test-Header-3,my-custom-regex-header-.*,invalid-regex-header-.*,.*my-secret.*",
},
)
def setUp(self) -> None:
def setUp(self):
self.test_env_patch = patch.dict(
"os.environ",
{
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS: ".*my-secret.*",
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST: "Custom-Test-Header-1,Custom-Test-Header-2,Custom-Test-Header-3,Regex-Test-Header-.*,Regex-Invalid-Test-Header-.*,.*my-secret.*",
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE: "Custom-Test-Header-1,Custom-Test-Header-2,Custom-Test-Header-3,my-custom-regex-header-.*,invalid-regex-header-.*,.*my-secret.*",
},
)
self.test_env_patch.start()
super().setUp()
def tearDown(self):
self.test_env_patch.stop()
super().tearDown()
def test_custom_request_headers_in_span_attributes(self):
expected = {
"http.request.header.custom_test_header_1": (
@ -793,17 +798,22 @@ class TestHTTPAppWithCustomHeaders(TestBaseWithCustomHeaders):
class TestWebSocketAppWithCustomHeaders(TestBaseWithCustomHeaders):
@patch.dict(
"os.environ",
{
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS: ".*my-secret.*",
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST: "Custom-Test-Header-1,Custom-Test-Header-2,Custom-Test-Header-3,Regex-Test-Header-.*,Regex-Invalid-Test-Header-.*,.*my-secret.*",
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE: "Custom-Test-Header-1,Custom-Test-Header-2,Custom-Test-Header-3,my-custom-regex-header-.*,invalid-regex-header-.*,.*my-secret.*",
},
)
def setUp(self) -> None:
def setUp(self):
self.test_env_patch = patch.dict(
"os.environ",
{
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS: ".*my-secret.*",
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST: "Custom-Test-Header-1,Custom-Test-Header-2,Custom-Test-Header-3,Regex-Test-Header-.*,Regex-Invalid-Test-Header-.*,.*my-secret.*",
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE: "Custom-Test-Header-1,Custom-Test-Header-2,Custom-Test-Header-3,my-custom-regex-header-.*,invalid-regex-header-.*,.*my-secret.*",
},
)
self.test_env_patch.start()
super().setUp()
def tearDown(self):
self.test_env_patch.stop()
super().tearDown()
def test_custom_request_headers_in_span_attributes(self):
expected = {
"http.request.header.custom_test_header_1": (
@ -918,23 +928,29 @@ class TestWebSocketAppWithCustomHeaders(TestBaseWithCustomHeaders):
self.assertNotIn(key, server_span.attributes)
@patch.dict(
"os.environ",
{
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS: ".*my-secret.*",
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST: "Custom-Test-Header-1,Custom-Test-Header-2,Custom-Test-Header-3,Regex-Test-Header-.*,Regex-Invalid-Test-Header-.*,.*my-secret.*",
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE: "Custom-Test-Header-1,Custom-Test-Header-2,Custom-Test-Header-3,my-custom-regex-header-.*,invalid-regex-header-.*,.*my-secret.*",
},
)
class TestNonRecordingSpanWithCustomHeaders(TestBaseWithCustomHeaders):
def setUp(self):
super().setUp()
self.test_env_patch = patch.dict(
"os.environ",
{
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS: ".*my-secret.*",
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST: "Custom-Test-Header-1,Custom-Test-Header-2,Custom-Test-Header-3,Regex-Test-Header-.*,Regex-Invalid-Test-Header-.*,.*my-secret.*",
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE: "Custom-Test-Header-1,Custom-Test-Header-2,Custom-Test-Header-3,my-custom-regex-header-.*,invalid-regex-header-.*,.*my-secret.*",
},
)
self.test_env_patch.start()
reset_trace_globals()
set_tracer_provider(tracer_provider=NoOpTracerProvider())
self._app = self.create_app()
self._client = TestClient(self._app)
def tearDown(self):
self.test_env_patch.stop()
super().tearDown()
def test_custom_header_not_present_in_non_recording_span(self):
resp = self._client.get(
"/foobar",

View File

@ -189,7 +189,7 @@ libraries = [
"instrumentation": "opentelemetry-instrumentation-sqlalchemy==0.55b0.dev",
},
{
"library": "starlette >= 0.13, <0.15",
"library": "starlette >= 0.13",
"instrumentation": "opentelemetry-instrumentation-starlette==0.55b0.dev",
},
{

3548
uv.lock generated

File diff suppressed because it is too large Load Diff