Skip to content

Commit 7381e47

Browse files
authored
Merge branch 'main' into fix_vertexai
2 parents 5bc6f8d + 333fc5d commit 7381e47

File tree

30 files changed

+706
-149
lines changed

30 files changed

+706
-149
lines changed

CHANGELOG.md

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

14-
## Version 1.34.0/0.55b0 (2025-06-04)
14+
15+
### Added
16+
17+
- `opentelemetry-instrumentation-pika` Added instrumentation for All `SelectConnection` adapters
18+
([#3584](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3584))
1519

1620
### Fixed
1721

22+
- `opentelemetry-instrumentation-asgi`: fix excluded_urls in instrumentation-asgi
23+
([#3567](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3567))
1824
- `opentelemetry-resource-detector-containerid`: make it more quiet on platforms without cgroups
1925
([#3579](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3579))
2026
- `opentelemetry-instrumentation-vertexai`: migrate off the deprecated events API to use the logs API
2127
([#3625](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3626))
2228

2329
### Added
2430

25-
- `opentelemetry-instrumentation-aiokafka` Add instrumentation of `consumer.getmany` (batch)
26-
([#3257](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3257))
31+
- `opentelemetry-util-http` Added support for redacting specific url query string values and url credentials in instrumentations
32+
([#3508](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3508))
33+
- `opentelemetry-instrumentation-pymongo` `aggregate` and `getMore` capture statements support
34+
([#3601](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3601))
35+
36+
## Version 1.34.0/0.55b0 (2025-06-04)
2737

2838
### Fixed
2939

@@ -80,7 +90,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8090
([#3513](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3513))
8191
- `opentelemetry-instrumentation` Allow re-raising exception when instrumentation fails
8292
([#3545](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3545))
83-
93+
- `opentelemetry-instrumentation-aiokafka` Add instrumentation of `consumer.getmany` (batch)
94+
([#3257](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3257))
95+
8496
### Deprecated
8597

8698
- 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>

instrumentation-genai/opentelemetry-instrumentation-google-genai/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased
99

10+
## Version 0.3b0 (2025-07-08)
11+
1012
- Add automatic instrumentation to tool call functions ([#3446](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3446))
1113

1214
## Version 0.2b0 (2025-04-28)

instrumentation-genai/opentelemetry-instrumentation-google-genai/src/opentelemetry/instrumentation/google_genai/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@
1717
# This version should stay below "1.0" until the fundamentals
1818
# in "TODOS.md" have been addressed. Please revisit the TODOs
1919
# listed there before bumping to a stable version.
20-
__version__ = "0.3b0.dev"
20+
__version__ = "0.4b0.dev"

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: 31 additions & 8 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
*****************************************
@@ -254,12 +273,14 @@ def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, A
254273
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS,
255274
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST,
256275
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE,
276+
ExcludeList,
257277
SanitizeValue,
258278
_parse_url_query,
259279
get_custom_headers,
260280
normalise_request_header_name,
261281
normalise_response_header_name,
262-
remove_url_credentials,
282+
parse_excluded_urls,
283+
redact_url,
263284
sanitize_method,
264285
)
265286

@@ -356,7 +377,7 @@ def collect_request_attributes(
356377
if _report_old(sem_conv_opt_in_mode):
357378
_set_http_url(
358379
result,
359-
remove_url_credentials(http_url),
380+
redact_url(http_url),
360381
_StabilityMode.DEFAULT,
361382
)
362383
http_method = scope.get("method", "")
@@ -537,7 +558,7 @@ class OpenTelemetryMiddleware:
537558
def __init__(
538559
self,
539560
app,
540-
excluded_urls=None,
561+
excluded_urls: ExcludeList | str | None = None,
541562
default_span_details=None,
542563
server_request_hook: ServerRequestHook = None,
543564
client_request_hook: ClientRequestHook = None,
@@ -619,6 +640,8 @@ def __init__(
619640
self.active_requests_counter = create_http_server_active_requests(
620641
self.meter
621642
)
643+
if isinstance(excluded_urls, str):
644+
excluded_urls = parse_excluded_urls(excluded_urls)
622645
self.excluded_urls = excluded_urls
623646
self.default_span_details = (
624647
default_span_details or get_default_span_details

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

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,6 +1633,29 @@ async def test_no_metric_for_websockets(self):
16331633
await self.get_all_output()
16341634
self.assertIsNone(self.memory_metrics_reader.get_metrics_data())
16351635

1636+
async def test_excluded_urls(self):
1637+
self.scope["path"] = "/test_excluded_urls"
1638+
app = otel_asgi.OpenTelemetryMiddleware(
1639+
simple_asgi, excluded_urls="test_excluded_urls"
1640+
)
1641+
self.seed_app(app)
1642+
await self.send_default_request()
1643+
await self.get_all_output()
1644+
spans = self.memory_exporter.get_finished_spans()
1645+
self.assertEqual(len(spans), 0)
1646+
1647+
async def test_no_excluded_urls(self):
1648+
self.scope["path"] = "/test_excluded_urls"
1649+
app = otel_asgi.OpenTelemetryMiddleware(
1650+
simple_asgi, excluded_urls="test_excluded_urls"
1651+
)
1652+
self.seed_app(app)
1653+
self.scope["path"] = "/test_no_excluded_urls"
1654+
await self.send_default_request()
1655+
await self.get_all_output()
1656+
spans = self.memory_exporter.get_finished_spans()
1657+
self.assertGreater(len(spans), 0)
1658+
16361659

16371660
class TestAsgiAttributes(unittest.TestCase):
16381661
def setUp(self):
@@ -1809,12 +1832,14 @@ def test_response_attributes_invalid_status_code(self):
18091832
otel_asgi.set_status_code(self.span, "Invalid Status Code")
18101833
self.assertEqual(self.span.set_status.call_count, 1)
18111834

1812-
def test_credential_removal(self):
1835+
def test_remove_sensitive_params(self):
18131836
self.scope["server"] = ("username:password@mock", 80)
18141837
self.scope["path"] = "/status/200"
1838+
self.scope["query_string"] = b"X-Goog-Signature=1234567890"
18151839
attrs = otel_asgi.collect_request_attributes(self.scope)
18161840
self.assertEqual(
1817-
attrs[SpanAttributes.HTTP_URL], "http://mock/status/200"
1841+
attrs[SpanAttributes.HTTP_URL],
1842+
"http://REDACTED:REDACTED@mock/status/200?X-Goog-Signature=REDACTED",
18181843
)
18191844

18201845
def test_collect_target_attribute_missing(self):

0 commit comments

Comments
 (0)