Skip to content

Commit e494677

Browse files
authored
Merge branch 'main' into fix-excluded_urls
2 parents e6c1349 + b69ebb7 commit e494677

File tree

30 files changed

+637
-226
lines changed

30 files changed

+637
-226
lines changed

CHANGELOG.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1515

1616
- `opentelemetry-instrumentation-asgi`: fix excluded_urls in instrumentation-asgi
1717
([#3567](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3567))
18-
19-
## Version 1.34.0/0.55b0 (2025-06-04)
18+
- `opentelemetry-resource-detector-containerid`: make it more quiet on platforms without cgroups
19+
([#3579](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3579))
2020

2121
### Added
2222

23-
- `opentelemetry-instrumentation-aiokafka` Add instrumentation of `consumer.getmany` (batch)
24-
([#3257](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3257))
23+
- `opentelemetry-util-http` Added support for redacting specific url query string values and url credentials in instrumentations
24+
([#3508](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3508))
25+
26+
## Version 1.34.0/0.55b0 (2025-06-04)
2527

2628
### Fixed
2729

@@ -78,7 +80,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7880
([#3513](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3513))
7981
- `opentelemetry-instrumentation` Allow re-raising exception when instrumentation fails
8082
([#3545](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3545))
81-
83+
- `opentelemetry-instrumentation-aiokafka` Add instrumentation of `consumer.getmany` (batch)
84+
([#3257](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3257))
85+
8286
### Deprecated
8387

8488
- Drop support for Python 3.8, bump baseline to Python 3.9.

README.md

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,16 @@ We meet weekly on Thursday at 9AM PT. The meeting is subject to change depending
111111

112112
Meeting notes are available as a public [Google doc](https://docs.google.com/document/d/1CIMGoIOZ-c3-igzbd6_Pnxx1SjAkjwqoYSUWxPY8XIs/edit). For edit access, get in touch on [GitHub Discussions](https://github.com/open-telemetry/opentelemetry-python/discussions).
113113

114-
Approvers ([@open-telemetry/python-approvers](https://github.com/orgs/open-telemetry/teams/python-approvers)):
114+
### Maintainers
115+
116+
- [Aaron Abbott](https://github.com/aabmass), Google
117+
- [Leighton Chen](https://github.com/lzchen), Microsoft
118+
- [Riccardo Magliocchetti](https://github.com/xrmx), Elastic
119+
- [Shalev Roda](https://github.com/shalevr), Cisco
120+
121+
For more information about the maintainer role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#maintainer).
122+
123+
### Approvers
115124

116125
- [Emídio Neto](https://github.com/emdneto), PicPay
117126
- [Jeremy Voss](https://github.com/jeremydvoss), Microsoft
@@ -121,34 +130,29 @@ Approvers ([@open-telemetry/python-approvers](https://github.com/orgs/open-telem
121130
- [Srikanth Chekuri](https://github.com/srikanthccv), signoz.io
122131
- [Tammy Baylis](https://github.com/tammy-baylis-swi), SolarWinds
123132

124-
Emeritus Approvers:
125-
126-
- [Ashutosh Goel](https://github.com/ashu658), Cisco
127-
- [Héctor Hernández](https://github.com/hectorhdzg), Microsoft
128-
- [Nikolay Sokolik](https://github.com/oxeye-nikolay), Oxeye
129-
- [Nikolay Sokolik](https://github.com/nikosokolik), Oxeye
130-
- [Nathaniel Ruiz Nowell](https://github.com/NathanielRN), AWS
131-
132-
*Find more about the approver role in [community repository](https://github.com/open-telemetry/community/blob/main/community-membership.md#approver).*
133+
For more information about the approver role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#approver).
133134

134-
Maintainers ([@open-telemetry/python-maintainers](https://github.com/orgs/open-telemetry/teams/python-maintainers)):
135-
136-
- [Aaron Abbott](https://github.com/aabmass), Google
137-
- [Leighton Chen](https://github.com/lzchen), Microsoft
138-
- [Riccardo Magliocchetti](https://github.com/xrmx), Elastic
139-
- [Shalev Roda](https://github.com/shalevr), Cisco
140-
141-
Emeritus Maintainers:
135+
### Emeritus Maintainers
142136

143137
- [Alex Boten](https://github.com/codeboten), Lightstep
144138
- [Diego Hurtado](https://github.com/ocelotl), Lightstep
145139
- [Owais Lone](https://github.com/owais), Splunk
146140
- [Yusuke Tsutsumi](https://github.com/toumorokoshi), Google
147141

148-
*Find more about the maintainer role in [community repository](https://github.com/open-telemetry/community/blob/main/community-membership.md#maintainer).*
142+
For more information about the emeritus role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#emeritus-maintainerapprovertriager).
143+
144+
### Emeritus Approvers
145+
146+
- [Ashutosh Goel](https://github.com/ashu658), Cisco
147+
- [Héctor Hernández](https://github.com/hectorhdzg), Microsoft
148+
- [Nikolay Sokolik](https://github.com/oxeye-nikolay), Oxeye
149+
- [Nikolay Sokolik](https://github.com/nikosokolik), Oxeye
150+
- [Nathaniel Ruiz Nowell](https://github.com/NathanielRN), AWS
151+
152+
For more information about the emeritus role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#emeritus-maintainerapprovertriager).
149153

150-
### Thanks to all the people who already contributed
154+
### Thanks to all of our contributors!
151155

152156
<a href="https://github.com/open-telemetry/opentelemetry-python-contrib/graphs/contributors">
153-
<img src="https://contributors-img.web.app/image?repo=open-telemetry/opentelemetry-python-contrib" />
157+
<img alt="Repo contributors" src="https://contrib.rocks/image?repo=open-telemetry/opentelemetry-python-contrib" />
154158
</a>

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@
122122
"https://opentelemetry-python.readthedocs.io/en/latest/",
123123
None,
124124
),
125-
"redis": ("https://redis-py.readthedocs.io/en/latest/", None),
125+
"redis": ("https://redis.readthedocs.io/en/latest/", None),
126126
}
127127

128128
# http://www.sphinx-doc.org/en/master/config.html#confval-nitpicky

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ def response_hook(span: Span, params: typing.Union[
135135
)
136136
from opentelemetry.trace import Span, SpanKind, TracerProvider, get_tracer
137137
from opentelemetry.trace.status import Status, StatusCode
138-
from opentelemetry.util.http import remove_url_credentials, sanitize_method
138+
from opentelemetry.util.http import redact_url, sanitize_method
139139

140140
_UrlFilterT = typing.Optional[typing.Callable[[yarl.URL], str]]
141141
_RequestHookT = typing.Optional[
@@ -311,9 +311,9 @@ async def on_request_start(
311311
method = params.method
312312
request_span_name = _get_span_name(method)
313313
request_url = (
314-
remove_url_credentials(trace_config_ctx.url_filter(params.url))
314+
redact_url(trace_config_ctx.url_filter(params.url))
315315
if callable(trace_config_ctx.url_filter)
316-
else remove_url_credentials(str(params.url))
316+
else redact_url(str(params.url))
317317
)
318318

319319
span_attributes = {}

instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/test_aiohttp_client_integration.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -762,16 +762,16 @@ async def do_request(url):
762762
)
763763
self.memory_exporter.clear()
764764

765-
def test_credential_removal(self):
765+
def test_remove_sensitive_params(self):
766766
trace_configs = [aiohttp_client.create_trace_config()]
767767

768-
app = HttpServerMock("test_credential_removal")
768+
app = HttpServerMock("test_remove_sensitive_params")
769769

770770
@app.route("/status/200")
771771
def index():
772772
return "hello"
773773

774-
url = "http://username:password@localhost:5000/status/200"
774+
url = "http://username:password@localhost:5000/status/200?Signature=secret"
775775

776776
with app.run("localhost", 5000):
777777
with self.subTest(url=url):
@@ -793,7 +793,9 @@ async def do_request(url):
793793
(StatusCode.UNSET, None),
794794
{
795795
HTTP_METHOD: "GET",
796-
HTTP_URL: ("http://localhost:5000/status/200"),
796+
HTTP_URL: (
797+
"http://REDACTED:REDACTED@localhost:5000/status/200?Signature=REDACTED"
798+
),
797799
HTTP_STATUS_CODE: int(HTTPStatus.OK),
798800
},
799801
)

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ async def hello(request):
7272
)
7373
from opentelemetry.semconv.metrics import MetricInstruments
7474
from opentelemetry.trace.status import Status, StatusCode
75-
from opentelemetry.util.http import get_excluded_urls, remove_url_credentials
75+
from opentelemetry.util.http import get_excluded_urls, redact_url
7676

7777
_duration_attrs = [
7878
HTTP_METHOD,
@@ -148,6 +148,7 @@ def collect_request_attributes(request: web.Request) -> Dict:
148148
request.url.port,
149149
str(request.url),
150150
)
151+
151152
query_string = request.query_string
152153
if query_string and http_url:
153154
if isinstance(query_string, bytes):
@@ -161,7 +162,7 @@ def collect_request_attributes(request: web.Request) -> Dict:
161162
HTTP_ROUTE: _get_view_func(request),
162163
HTTP_FLAVOR: f"{request.version.major}.{request.version.minor}",
163164
HTTP_TARGET: request.path,
164-
HTTP_URL: remove_url_credentials(http_url),
165+
HTTP_URL: redact_url(http_url),
165166
}
166167

167168
http_method = request.method

instrumentation/opentelemetry-instrumentation-aiohttp-server/tests/test_aiohttp_server_integration.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,46 @@ async def test_suppress_instrumentation(
152152
await client.get("/test-path")
153153

154154
assert len(memory_exporter.get_finished_spans()) == 0
155+
156+
157+
@pytest.mark.asyncio
158+
async def test_remove_sensitive_params(tracer, aiohttp_server):
159+
"""Test that sensitive information in URLs is properly redacted."""
160+
_, memory_exporter = tracer
161+
162+
# Set up instrumentation
163+
AioHttpServerInstrumentor().instrument()
164+
165+
# Create app with test route
166+
app = aiohttp.web.Application()
167+
168+
async def handler(request):
169+
return aiohttp.web.Response(text="hello")
170+
171+
app.router.add_get("/status/200", handler)
172+
173+
# Start the server
174+
server = await aiohttp_server(app)
175+
176+
# Make request with sensitive data in URL
177+
url = f"http://username:password@{server.host}:{server.port}/status/200?Signature=secret"
178+
async with aiohttp.ClientSession() as session:
179+
async with session.get(url) as response:
180+
assert response.status == 200
181+
assert await response.text() == "hello"
182+
183+
# Verify redaction in span attributes
184+
spans = memory_exporter.get_finished_spans()
185+
assert len(spans) == 1
186+
187+
span = spans[0]
188+
assert span.attributes[HTTP_METHOD] == "GET"
189+
assert span.attributes[HTTP_STATUS_CODE] == 200
190+
assert (
191+
span.attributes[HTTP_URL]
192+
== f"http://{server.host}:{server.port}/status/200?Signature=REDACTED"
193+
)
194+
195+
# Clean up
196+
AioHttpServerInstrumentor().uninstrument()
197+
memory_exporter.clear()

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

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14-
# pylint: disable=too-many-locals
14+
# pylint: disable=too-many-locals,too-many-lines
1515

1616
"""
1717
The opentelemetry-instrumentation-asgi package provides an ASGI middleware that can be used
@@ -81,19 +81,38 @@ async def hello():
8181
8282
.. code-block:: python
8383
84-
def server_request_hook(span: Span, scope: dict[str, Any]):
84+
from opentelemetry.trace import Span
85+
from typing import Any
86+
from asgiref.typing import Scope, ASGIReceiveEvent, ASGISendEvent
87+
from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware
88+
89+
async def application(scope: Scope, receive: ASGIReceiveEvent, send: ASGISendEvent):
90+
await send({
91+
'type': 'http.response.start',
92+
'status': 200,
93+
'headers': [
94+
[b'content-type', b'text/plain'],
95+
],
96+
})
97+
98+
await send({
99+
'type': 'http.response.body',
100+
'body': b'Hello, world!',
101+
})
102+
103+
def server_request_hook(span: Span, scope: Scope):
85104
if span and span.is_recording():
86105
span.set_attribute("custom_user_attribute_from_request_hook", "some-value")
87106
88-
def client_request_hook(span: Span, scope: dict[str, Any], message: dict[str, Any]):
107+
def client_request_hook(span: Span, scope: Scope, message: dict[str, Any]):
89108
if span and span.is_recording():
90109
span.set_attribute("custom_user_attribute_from_client_request_hook", "some-value")
91110
92-
def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, Any]):
111+
def client_response_hook(span: Span, scope: Scope, message: dict[str, Any]):
93112
if span and span.is_recording():
94113
span.set_attribute("custom_user_attribute_from_response_hook", "some-value")
95114
96-
OpenTelemetryMiddleware().(application, server_request_hook=server_request_hook, client_request_hook=client_request_hook, client_response_hook=client_response_hook)
115+
OpenTelemetryMiddleware(application, server_request_hook=server_request_hook, client_request_hook=client_request_hook, client_response_hook=client_response_hook)
97116
98117
Capture HTTP request and response headers
99118
*****************************************
@@ -261,7 +280,7 @@ def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, A
261280
normalise_request_header_name,
262281
normalise_response_header_name,
263282
parse_excluded_urls,
264-
remove_url_credentials,
283+
redact_url,
265284
sanitize_method,
266285
)
267286

@@ -358,7 +377,7 @@ def collect_request_attributes(
358377
if _report_old(sem_conv_opt_in_mode):
359378
_set_http_url(
360379
result,
361-
remove_url_credentials(http_url),
380+
redact_url(http_url),
362381
_StabilityMode.DEFAULT,
363382
)
364383
http_method = scope.get("method", "")

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1832,12 +1832,14 @@ def test_response_attributes_invalid_status_code(self):
18321832
otel_asgi.set_status_code(self.span, "Invalid Status Code")
18331833
self.assertEqual(self.span.set_status.call_count, 1)
18341834

1835-
def test_credential_removal(self):
1835+
def test_remove_sensitive_params(self):
18361836
self.scope["server"] = ("username:password@mock", 80)
18371837
self.scope["path"] = "/status/200"
1838+
self.scope["query_string"] = b"X-Goog-Signature=1234567890"
18381839
attrs = otel_asgi.collect_request_attributes(self.scope)
18391840
self.assertEqual(
1840-
attrs[SpanAttributes.HTTP_URL], "http://mock/status/200"
1841+
attrs[SpanAttributes.HTTP_URL],
1842+
"http://REDACTED:REDACTED@mock/status/200?X-Goog-Signature=REDACTED",
18411843
)
18421844

18431845
def test_collect_target_attribute_missing(self):

instrumentation/opentelemetry-instrumentation-falcon/tests/test_falcon.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,20 @@ def test_uninstrument(self):
427427
spans = self.memory_exporter.get_finished_spans()
428428
self.assertEqual(len(spans), 0)
429429

430+
def test_no_op_tracer_provider(self):
431+
FalconInstrumentor().uninstrument()
432+
433+
FalconInstrumentor().instrument(
434+
tracer_provider=trace.NoOpTracerProvider()
435+
)
436+
437+
self.memory_exporter.clear()
438+
439+
self.client().simulate_get(path="/hello")
440+
441+
spans = self.memory_exporter.get_finished_spans()
442+
self.assertEqual(len(spans), 0)
443+
430444
def test_exclude_lists(self):
431445
self.client().simulate_get(path="/ping")
432446
span_list = self.memory_exporter.get_finished_spans()

0 commit comments

Comments
 (0)