Skip to content

opentelemetry-instrumentation-starlette: remove starlette version ceiling #3529

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

anuraaga
Copy link
Contributor

@anuraaga anuraaga commented May 22, 2025

Description

Removes the starlette version ceiling which is currently set to a very ancient version of starlette. I think this is fairly sane to do since the instrumentation only uses starlette's public API (add_middleware) and should be relatively stable.

There was test failure when bumping but it was an issue with the test code itself, not the instrumentation, so I fixed it.

Fixes #3317

/cc @xrmx

Type of change

  • This change requires a documentation update

How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration

  • Unit tests of latest and oldest

Does This PR Require a Core Repo Change?

  • Yes. - Link to PR:
  • No.

Checklist:

See contributing.md for styleguide, changelog guidelines, and more.

  • Followed the style guidelines of this project
  • Changelogs have been updated
  • Unit tests have been added
  • Documentation has been updated

@anuraaga anuraaga requested a review from a team as a code owner May 22, 2025 06:36
@@ -239,7 +239,7 @@ def instrument_app(
meter_provider,
schema_url="https://opentelemetry.io/schemas/1.11.0",
)
if not getattr(app, "is_instrumented_by_opentelemetry", False):
if not getattr(app, "_is_instrumented_by_opentelemetry", False):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to match the setting at https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3529/files#diff-a4901479b7a21ad4f5d45a7f3e47b2ada3f9d8ae4ae7f9e68c2001e8b8067611L330

I think the problem becomes double telemetry, but presumably no one uses such an old version of starlette to allow the auto-instrumentation to kick in to trigger it.

@@ -331,9 +332,6 @@ def __init__(self, *args: Any, **kwargs: Any):
# adding apps to set for uninstrumenting
_InstrumentedStarlette._instrumented_starlette_apps.add(self)

def __del__(self):
_InstrumentedStarlette._instrumented_starlette_apps.remove(self)
Copy link
Contributor Author

@anuraaga anuraaga May 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would fail if the app isn't in the set, which would happen in the .clear() call in StarletteInstrumentation.uninstrument(). And actually, __del__ could only ever be called after such a call because the set held a strong reference, preventing __del__ from being called. I am guessing older versions of starlette had a similar memory leak that was fixed, causing the newer ones to trigger the crash here.

I changed to WeakSet which should fix it, and we don't need __del__ since it's automatically cleaned when the object goes away

def setUp(self) -> None:
patcher = patch.dict(
Copy link
Contributor Author

@anuraaga anuraaga May 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously patch was decorating setUp - it was active only for the duration of setUp, not the entire test case. Recent starlette seems to initialize middleware lazily so the patch needs to be active during the test case for it. I switched to this pattern that activates it both for setUp (for older eager starlette) and the test cases (for newer lazy starlette). Note, moving the decorator to the class level would loose the former.

@anuraaga anuraaga changed the title Remove starlette version ceiling opentelemetry-instrumentation-starlette: remove starlette version ceiling May 22, 2025
@anuraaga anuraaga marked this pull request as draft May 22, 2025 06:59
@xrmx
Copy link
Contributor

xrmx commented May 22, 2025

@anuraaga this is ready to review since you fixed the testcase right?

@@ -230,7 +230,8 @@ def test_basic_post_request_metric_success(self):
dict(point.attributes), expected_duration_attributes
)
if metric.name == "http.server.duration":
self.assertAlmostEqual(duration, point.sum, delta=30)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

latest had trouble with this assertion because it initializes middleware lazily, so the duration ends up being way longer than the actual request's duration. I think in principal, it's only safe to check the request duration is not larger than the test duration rather than comparing the actual values so I changed the assertions.

I wanted to use self.assertGreater(point.sum, 0) but the old ms metric is rounded and easily 0 on a fastish machine - not sure if the rounding is actually required for it but that would be a change in the ASGI middleware

@anuraaga anuraaga marked this pull request as ready for review May 22, 2025 07:17
@anuraaga
Copy link
Contributor Author

FYI @codefromthecrypt

@anuraaga
Copy link
Contributor Author

@anuraaga this is ready to review since you fixed the testcase right?

Yup should be ok now

@anuraaga
Copy link
Contributor Author

Oh no, I didn't check existing PRs before making this one and now see @MattiasDC's #3456 is quite similar. I found the tests seem to pass fine for the current baseline version so didn't raise it here which is the main difference. Feel free to reject this PR as a duplicate and get that one in instead though, then I can send another one with just the WeakSet and other fixes which should still apply.

Copy link
Member

@emdneto emdneto May 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Funny that running the same command, I got different result for this file 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah to get it to update, I removed the file first and ran the command

Copy link
Member

@emdneto emdneto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@anuraaga Thank you for the fix! To be fair with the already opened PR #3456 I would suggest that we proceed with #3456 and later you can modify your PR with the changes you are proposing here (weakset and the fix for the already instrumented flag)

@anuraaga anuraaga marked this pull request as draft May 23, 2025 05:28
@emdneto
Copy link
Member

emdneto commented May 23, 2025

@anuraaga #3456 was merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Starlette instrumentation tests fail recent versions starlette >= 0.15.0
3 participants