Skip to content

Commit bd45acc

Browse files
Merge branch 'main' into sqlcomment-dbapi-docs
2 parents 5675b82 + 6393e84 commit bd45acc

File tree

14 files changed

+154
-8
lines changed

14 files changed

+154
-8
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1919
([#3664](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3664))
2020
- `opentelemetry-instrumentation-fastapi`: Fix memory leak in `uninstrument_app()` by properly removing apps from the tracking set
2121
([#3688](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3688)
22-
- `opentelemetry-instrumentation-tornado` Fix server (request) duration metric calculation
22+
- `opentelemetry-instrumentation-tornado`: Fix server (request) duration metric calculation
2323
([#3679](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3679))
24+
- `opentelemetry-instrumentation-tornado`: Fix to properly skip all server telemetry when URL excluded.
25+
([#3680](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3680))
2426
- `opentelemetry-instrumentation`: Avoid calls to `context.detach` with `None` token.
2527
([#3673](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3673))
28+
- `opentelemetry-instrumentation-starlette`/`opentelemetry-instrumentation-fastapi`: Fixes a crash when host-based routing is used
29+
([#3507](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3507))
2630
- `opentelemetry-instrumentation-dbapi`: Adds sqlcommenter to documentation.
2731
([#3720](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3720))
2832

@@ -34,6 +38,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3438
([#3666](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3666))
3539
- `opentelemetry-sdk-extension-aws` Add AWS X-Ray Remote Sampler with initial Rules Poller implementation
3640
([#3366](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3366))
41+
- `opentelemetry-instrumentation`: add support for `OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH` to inform opentelemetry-instrument about gevent monkeypatching
42+
([#3699](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3699))
3743

3844
## Version 1.36.0/0.57b0 (2025-07-29)
3945

instrumentation-genai/opentelemetry-instrumentation-vertexai/src/opentelemetry/instrumentation/vertexai/events.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
# type: ignore[reportUnknownDeprecated]
16+
1517
"""
1618
Factories for event types described in
1719
https://github.com/open-telemetry/semantic-conventions/blob/main/docs/gen-ai/gen-ai-events.md#system-event.

instrumentation-genai/opentelemetry-instrumentation-vertexai/src/opentelemetry/instrumentation/vertexai/utils.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
# type: ignore[reportUnknownDeprecated]
16+
1517
from __future__ import annotations
1618

1719
import re

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,11 @@ def _get_route_details(scope):
516516
for starlette_route in app.routes:
517517
match, _ = starlette_route.matches(scope)
518518
if match == Match.FULL:
519-
route = starlette_route.path
519+
try:
520+
route = starlette_route.path
521+
except AttributeError:
522+
# routes added via host routing won't have a path attribute
523+
route = scope.get("path")
520524
break
521525
if match == Match.PARTIAL:
522526
route = starlette_route.path

instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ async def _():
234234
raise UnhandledException("This is an unhandled exception")
235235

236236
app.mount("/sub", app=sub_app)
237+
app.host("testserver2", sub_app)
237238

238239
return app
239240

@@ -310,6 +311,26 @@ def test_sub_app_fastapi_call(self):
310311
span.attributes[HTTP_URL],
311312
)
312313

314+
def test_host_fastapi_call(self):
315+
client = TestClient(self._app, base_url="https://testserver2")
316+
client.get("/")
317+
spans = self.memory_exporter.get_finished_spans()
318+
319+
spans_with_http_attributes = [
320+
span
321+
for span in spans
322+
if (HTTP_URL in span.attributes or HTTP_TARGET in span.attributes)
323+
]
324+
325+
self.assertEqual(1, len(spans_with_http_attributes))
326+
327+
for span in spans_with_http_attributes:
328+
self.assertEqual("/", span.attributes[HTTP_TARGET])
329+
self.assertEqual(
330+
"https://testserver2:443/",
331+
span.attributes[HTTP_URL],
332+
)
333+
313334

314335
class TestBaseAutoFastAPI(TestBaseFastAPI):
315336
@classmethod

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,11 @@ def _get_route_details(scope: dict[str, Any]) -> str | None:
354354
for starlette_route in app.routes:
355355
match, _ = starlette_route.matches(scope)
356356
if match == Match.FULL:
357-
route = starlette_route.path
357+
try:
358+
route = starlette_route.path
359+
except AttributeError:
360+
# routes added via host routing won't have a path attribute
361+
route = scope.get("path")
358362
break
359363
if match == Match.PARTIAL:
360364
route = starlette_route.path

instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
from starlette import applications
2020
from starlette.responses import PlainTextResponse
21-
from starlette.routing import Mount, Route
21+
from starlette.routing import Host, Mount, Route
2222
from starlette.testclient import TestClient
2323
from starlette.websockets import WebSocket
2424

@@ -140,6 +140,24 @@ def test_sub_app_starlette_call(self):
140140
span.attributes[HTTP_URL],
141141
)
142142

143+
def test_host_starlette_call(self):
144+
client = TestClient(self._app, base_url="http://testserver2")
145+
client.get("/home")
146+
spans = self.memory_exporter.get_finished_spans()
147+
148+
spans_with_http_attributes = [
149+
span
150+
for span in spans
151+
if (HTTP_URL in span.attributes or HTTP_TARGET in span.attributes)
152+
]
153+
154+
for span in spans_with_http_attributes:
155+
self.assertEqual("/home", span.attributes[HTTP_TARGET])
156+
self.assertEqual(
157+
"http://testserver2/home",
158+
span.attributes[HTTP_URL],
159+
)
160+
143161
def test_starlette_route_attribute_added(self):
144162
"""Ensure that starlette routes are used as the span name."""
145163
self._client.get("/user/123")
@@ -294,6 +312,7 @@ def sub_home(_):
294312
Route("/user/{username}", home),
295313
Route("/healthzz", health),
296314
Mount("/sub", app=sub_app),
315+
Host("testserver2", sub_app),
297316
],
298317
)
299318

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -403,11 +403,14 @@ def _wrap(cls, method_name, wrapper):
403403
def _prepare(
404404
tracer, server_histograms, request_hook, func, handler, args, kwargs
405405
):
406-
otel_handler_state = {_START_TIME: default_timer()}
406+
request = handler.request
407+
otel_handler_state = {
408+
_START_TIME: default_timer(),
409+
"exclude_request": _excluded_urls.url_disabled(request.uri),
410+
}
407411
setattr(handler, _HANDLER_STATE_KEY, otel_handler_state)
408412

409-
request = handler.request
410-
if _excluded_urls.url_disabled(request.uri):
413+
if otel_handler_state["exclude_request"]:
411414
return func(*args, **kwargs)
412415

413416
_record_prepare_metrics(server_histograms, handler)
@@ -625,6 +628,8 @@ def _record_prepare_metrics(server_histograms, handler):
625628

626629
def _record_on_finish_metrics(server_histograms, handler, error=None):
627630
otel_handler_state = getattr(handler, _HANDLER_STATE_KEY, None) or {}
631+
if otel_handler_state.get("exclude_request"):
632+
return
628633
start_time = otel_handler_state.get(_START_TIME, None) or default_timer()
629634
elapsed_time = round((default_timer() - start_time) * 1000)
630635

instrumentation/opentelemetry-instrumentation-tornado/tests/test_metrics_instrumentation.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,16 @@ def test_metric_uninstrument(self):
252252
for point in list(metric.data.data_points):
253253
if isinstance(point, HistogramDataPoint):
254254
self.assertEqual(point.count, 1)
255+
256+
def test_exclude_lists(self):
257+
def test_excluded(path):
258+
self.fetch(path)
259+
260+
# Verify no server metrics written (only client ones should exist)
261+
metrics = self.get_sorted_metrics()
262+
for metric in metrics:
263+
self.assertTrue("http.server" not in metric.name, metric)
264+
self.assertEqual(len(metrics), 3, metrics)
265+
266+
test_excluded("/healthz")
267+
test_excluded("/ping")

opentelemetry-instrumentation/README.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,13 @@ check `here <https://opentelemetry-python.readthedocs.io/en/stable/index.html#in
104104
* ``OTEL_PYTHON_DISABLED_INSTRUMENTATIONS``
105105

106106
If set by the user, opentelemetry-instrument will read this environment variable to disable specific instrumentations.
107-
e.g OTEL_PYTHON_DISABLED_INSTRUMENTATIONS = "requests,django"
107+
e.g OTEL_PYTHON_DISABLED_INSTRUMENTATIONS="requests,django"
108+
109+
* ``OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH``
110+
111+
If set by the user to `patch_all` , opentelemetry instrument will call the gevent monkeypatching method ``patch_all``.
112+
This is considered experimental but can be useful to instrument gevent applications.
113+
e.g OTEL_PYTHON_AUTO_INSTRUMENTATION_EXPERIMENTAL_GEVENT_PATCH=patch_all
108114

109115

110116
Examples

0 commit comments

Comments
 (0)