Skip to content

Commit 0f5c00a

Browse files
Merge branch 'main' into add-metrics-attributes-labeler
2 parents aed659b + fd21563 commit 0f5c00a

File tree

29 files changed

+757
-274
lines changed

29 files changed

+757
-274
lines changed

.github/ISSUE_TEMPLATE/bug_report.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,11 @@ body:
6464
options:
6565
- "No"
6666
- "Yes"
67+
68+
- type: dropdown
69+
attributes:
70+
label: Tip
71+
description: This element is static, used to render a helpful sub-heading for end-users and community members to help prioritize issues. Please leave as is.
72+
options:
73+
- <sub>[React](https://github.blog/news-insights/product-news/add-reactions-to-pull-requests-issues-and-comments/) with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding `+1` or `me too`, to help us triage it. Learn more [here](https://opentelemetry.io/community/end-user/issue-participation/).</sub>
74+
default: 0

.github/ISSUE_TEMPLATE/feature_request.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,11 @@ body:
4848
options:
4949
- "No"
5050
- "Yes"
51+
52+
- type: dropdown
53+
attributes:
54+
label: Tip
55+
description: This element is static, used to render a helpful sub-heading for end-users and community members to help prioritize issues. Please leave as is.
56+
options:
57+
- <sub>[React](https://github.blog/news-insights/product-news/add-reactions-to-pull-requests-issues-and-comments/) with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding `+1` or `me too`, to help us triage it. Learn more [here](https://opentelemetry.io/community/end-user/issue-participation/).</sub>
58+
default: 0

CHANGELOG.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313

1414
### Fixed
1515

16+
- `opentelemetry-instrumentation-fastapi`: Fix middleware ordering to cover all exception handling use cases.
17+
([#3664](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3664))
18+
- `opentelemetry-instrumentation-asgi`: Make all user hooks failsafe and record exceptions in hooks.
19+
([#3664](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3664))
1620
- `opentelemetry-instrumentation-fastapi`: Fix memory leak in `uninstrument_app()` by properly removing apps from the tracking set
17-
([#3688](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3688)
21+
([#3688](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3688))
1822
- `opentelemetry-instrumentation-tornado` Fix server (request) duration metric calculation
1923
([#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))
2026
- `opentelemetry-instrumentation`: Avoid calls to `context.detach` with `None` token.
2127
([#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))
30+
- Fix documentation order of sections and headers for Django, Flask, MySQL, mysqlclient, psycopg, psycopg2, pymysql, sqlalchemy instrumentations.
31+
([#3719](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3719))
2232

2333
### Added
2434

@@ -28,6 +38,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2838
([#3666](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3666))
2939
- `opentelemetry-sdk-extension-aws` Add AWS X-Ray Remote Sampler with initial Rules Poller implementation
3040
([#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))
3143
- `opentelemetry-instrumentation`, `opentelemetry-instrumentation-flask`, `opentelemetry-instrumentation-wsgi`, `opentelemetry-instrumentation-django`, `opentelemetry-instrumentation-falcon`, `opentelemetry-instrumentation-asgi`: Add Labeler utility. Add FalconInstrumentor, FlaskInstrumentor, DjangoInstrumentor, WsgiInstrumentor, AsgiInstrumentor support of custom attributes merging for HTTP duration metrics.
3244
([#3689](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3689))
3345

instrumentation-genai/opentelemetry-instrumentation-openai-v2/examples/manual/main.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,22 @@
44
from openai import OpenAI
55

66
# NOTE: OpenTelemetry Python Logs and Events APIs are in beta
7-
from opentelemetry import _events, _logs, trace
7+
from opentelemetry import _events, _logs, metrics, trace
88
from opentelemetry.exporter.otlp.proto.grpc._log_exporter import (
99
OTLPLogExporter,
1010
)
11+
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import (
12+
OTLPMetricExporter,
13+
)
1114
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
1215
OTLPSpanExporter,
1316
)
1417
from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor
1518
from opentelemetry.sdk._events import EventLoggerProvider
1619
from opentelemetry.sdk._logs import LoggerProvider
1720
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
21+
from opentelemetry.sdk.metrics import MeterProvider
22+
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
1823
from opentelemetry.sdk.trace import TracerProvider
1924
from opentelemetry.sdk.trace.export import BatchSpanProcessor
2025

@@ -31,6 +36,17 @@
3136
)
3237
_events.set_event_logger_provider(EventLoggerProvider())
3338

39+
# configure metrics
40+
metrics.set_meter_provider(
41+
MeterProvider(
42+
metric_readers=[
43+
PeriodicExportingMetricReader(
44+
OTLPMetricExporter(),
45+
),
46+
]
47+
)
48+
)
49+
3450
# instrument OpenAI
3551
OpenAIInstrumentor().instrument()
3652

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
openai~=1.57.3
22

3-
opentelemetry-sdk~=1.30.0
4-
opentelemetry-exporter-otlp-proto-grpc~=1.30.0
3+
opentelemetry-sdk~=1.36.0
4+
opentelemetry-exporter-otlp-proto-grpc~=1.36.0
55
opentelemetry-instrumentation-openai-v2~=2.1b0
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
openai~=1.57.3
22

3-
opentelemetry-sdk~=1.30.0
4-
opentelemetry-exporter-otlp-proto-grpc~=1.30.0
5-
opentelemetry-distro~=0.51b0
3+
opentelemetry-sdk~=1.36.0
4+
opentelemetry-exporter-otlp-proto-grpc~=1.36.0
5+
opentelemetry-distro~=0.57b0
66
opentelemetry-instrumentation-openai-v2~=2.1b0

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-asgi/src/opentelemetry/instrumentation/asgi/__init__.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ async def user_profile(user_id):
312312
HTTP_SERVER_REQUEST_DURATION,
313313
)
314314
from opentelemetry.semconv.trace import SpanAttributes
315-
from opentelemetry.trace import set_span_in_context
315+
from opentelemetry.trace import Span, set_span_in_context
316316
from opentelemetry.util.http import (
317317
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS,
318318
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST,
@@ -690,9 +690,23 @@ def __init__(
690690
self.default_span_details = (
691691
default_span_details or get_default_span_details
692692
)
693-
self.server_request_hook = server_request_hook
694-
self.client_request_hook = client_request_hook
695-
self.client_response_hook = client_response_hook
693+
694+
def failsafe(func):
695+
if func is None:
696+
return None
697+
698+
@wraps(func)
699+
def wrapper(span: Span, *args, **kwargs):
700+
try:
701+
func(span, *args, **kwargs)
702+
except Exception as exc: # pylint: disable=broad-exception-caught
703+
span.record_exception(exc)
704+
705+
return wrapper
706+
707+
self.server_request_hook = failsafe(server_request_hook)
708+
self.client_request_hook = failsafe(client_request_hook)
709+
self.client_response_hook = failsafe(client_response_hook)
696710
self.content_length_header = None
697711
self._sem_conv_opt_in_mode = sem_conv_opt_in_mode
698712

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

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,17 @@ async def error_asgi(scope, receive, send):
337337
await send({"type": "http.response.body", "body": b"*"})
338338

339339

340+
class UnhandledException(Exception):
341+
pass
342+
343+
344+
def failing_hook(msg):
345+
def hook(*_):
346+
raise UnhandledException(msg)
347+
348+
return hook
349+
350+
340351
# pylint: disable=too-many-public-methods
341352
class TestAsgiApplication(AsyncAsgiTestBase):
342353
def setUp(self):
@@ -542,6 +553,12 @@ def validate_outputs(
542553
span.instrumentation_scope.name,
543554
"opentelemetry.instrumentation.asgi",
544555
)
556+
if "events" in expected:
557+
self.assertEqual(len(span.events), len(expected["events"]))
558+
for event, expected in zip(span.events, expected["events"]):
559+
self.assertEqual(event.name, expected["name"])
560+
for name, value in expected["attributes"].items():
561+
self.assertEqual(event.attributes[name], value)
545562

546563
async def test_basic_asgi_call(self):
547564
"""Test that spans are emitted as expected."""
@@ -1267,6 +1284,40 @@ def update_expected_hook_results(expected):
12671284
outputs, modifiers=[update_expected_hook_results]
12681285
)
12691286

1287+
async def test_hook_exceptions(self):
1288+
def exception_event(msg):
1289+
return {
1290+
"name": "exception",
1291+
"attributes": {
1292+
"exception.type": f"{__name__}.UnhandledException",
1293+
"exception.message": msg,
1294+
},
1295+
}
1296+
1297+
def update_expected_hook_results(expected):
1298+
for entry in expected:
1299+
if entry["kind"] == trace_api.SpanKind.SERVER:
1300+
entry["events"] = [exception_event("server request")]
1301+
elif entry["name"] == "GET / http receive":
1302+
entry["events"] = [exception_event("client request")]
1303+
elif entry["name"] == "GET / http send":
1304+
entry["events"] = [exception_event("client response")]
1305+
1306+
return expected
1307+
1308+
app = otel_asgi.OpenTelemetryMiddleware(
1309+
simple_asgi,
1310+
server_request_hook=failing_hook("server request"),
1311+
client_request_hook=failing_hook("client request"),
1312+
client_response_hook=failing_hook("client response"),
1313+
)
1314+
self.seed_app(app)
1315+
await self.send_default_request()
1316+
outputs = await self.get_all_output()
1317+
self.validate_outputs(
1318+
outputs, modifiers=[update_expected_hook_results]
1319+
)
1320+
12701321
async def test_asgi_metrics(self):
12711322
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
12721323
self.seed_app(app)

0 commit comments

Comments
 (0)