Skip to content
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

Remove URL credentials (httpx integration) #2020

Merged
merged 3 commits into from
Dec 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

- `opentelemetry-instrumentation-httpx` Remove URL credentials
([#2020](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2020))
- `opentelemetry-instrumentation-urllib`/`opentelemetry-instrumentation-urllib3` Fix metric descriptions to match semantic conventions
([#1959](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1959))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ dependencies = [
"opentelemetry-api ~= 1.12",
"opentelemetry-instrumentation == 0.44b0.dev",
"opentelemetry-semantic-conventions == 0.44b0.dev",
"opentelemetry-util-http == 0.44b0.dev",
]

[project.optional-dependencies]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ async def async_response_hook(span, request, response):
from opentelemetry.trace import SpanKind, TracerProvider, get_tracer
from opentelemetry.trace.span import Span
from opentelemetry.trace.status import Status
from opentelemetry.util.http import remove_url_credentials

_logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -269,7 +270,7 @@ def _extract_parameters(args, kwargs):
# In httpx >= 0.20.0, handle_request receives a Request object
request: httpx.Request = args[0]
method = request.method.encode()
url = request.url
url = remove_url_credentials(str(request.url))
Copy link

@anuraaga anuraaga Feb 28, 2024

Choose a reason for hiding this comment

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

Hello - when updating to latest instrumentation, I noticed that url accessed within a request hook stopped being a httpx.URL and is a str now because of the conversion here. Was it intended? If so, the type is still the old one, though I think httpx.URL would be more useful if possible

https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2020/files#diff-eed55d62a8d5f01b055c1bb2d63934c48cfd767416c03826f2c19d4442a76e7bR227

Copy link
Contributor Author

@ods ods Feb 28, 2024

Choose a reason for hiding this comment

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

No, it wasn't intentional. Moreover, it violates current type annotation.

Copy link
Contributor

Choose a reason for hiding this comment

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

@ocelotl This is definitely an breaking issue preventing upgrades on my end to v44. We rely on request.url in my request hooks being httpx.URL type

def request_hook(span: Span, request: Request) -> None request.url is now a string and it used to be a httpx.URL < v44.

The solution is to wrap it back to httpx.URL:

httpx.URL(remove_url_credentials(str(request.url)))

headers = request.headers
stream = request.stream
extensions = request.extensions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,13 @@ def perform_request(
return self.client.request(method, url, headers=headers)
return client.request(method, url, headers=headers)

def test_credential_removal(self):
new_url = "http://username:password@mock/status/200"
self.perform_request(new_url)
span = self.assert_span()

self.assertEqual(span.attributes[SpanAttributes.HTTP_URL], self.URL)


class TestAsyncIntegration(BaseTestCases.BaseManualTest):
response_hook = staticmethod(_async_response_hook)
Expand Down Expand Up @@ -664,6 +671,13 @@ def test_basic_multiple(self):
)
self.assert_span(num_spans=2)

def test_credential_removal(self):
new_url = "http://username:password@mock/status/200"
self.perform_request(new_url)
span = self.assert_span()

self.assertEqual(span.attributes[SpanAttributes.HTTP_URL], self.URL)


class TestSyncInstrumentationIntegration(BaseTestCases.BaseInstrumentorTest):
def create_client(
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ commands_pre =

grpc: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-grpc[test]

falcon{1,2,3},flask{213,220},django{1,2,3,4},pyramid,tornado,starlette,fastapi,aiohttp,asgi,requests,urllib,urllib3v{1,2},wsgi: pip install {toxinidir}/util/opentelemetry-util-http[test]
falcon{1,2,3},flask{213,220},django{1,2,3,4},pyramid,tornado,starlette,fastapi,aiohttp,asgi,httpx{18,21},requests,urllib,urllib3v{1,2},wsgi: pip install {toxinidir}/util/opentelemetry-util-http[test]
wsgi,falcon{1,2,3},flask{213,220},django{1,2,3,4},pyramid: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-wsgi[test]
asgi,django{3,4},starlette,fastapi: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-asgi[test]

Expand Down
Loading