Skip to content

Commit 131c9ab

Browse files
authored
Merge branch 'main' into refactor/missing_lambda_handler_in_aws_lambda_raises_exception
2 parents 9819673 + 1c8d8ef commit 131c9ab

File tree

10 files changed

+465
-255
lines changed

10 files changed

+465
-255
lines changed

CHANGELOG.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
- `opentelemetry-instrumentation-aws-lambda` Avoid exception when a handler is not present.
1313
([#2750](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2750))
14+
- `opentelemetry-instrumentation-django` Fix regression - `http.target` re-added back to old semconv duration metrics
15+
([#2746](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2746))
16+
- `opentelemetry-instrumentation-grpc` Fixes the issue with the gRPC instrumentation not working with the 1.63.0 and higher version of gRPC
17+
([#2483](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2484))
1418

1519
## Version 1.26.0/0.47b0 (2024-07-23)
1620

@@ -104,7 +108,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
104108
- `opentelemetry-instrumentation-asgi` Bugfix: Middleware did not set status code attribute on duration metrics for non-recording spans.
105109
([#2627](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2627))
106110

107-
108111
## Version 1.25.0/0.46b0 (2024-05-31)
109112

110113
### Breaking changes

instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware/otel_middleware.py

+5
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ def process_exception(self, request, exception):
333333

334334
# pylint: disable=too-many-branches
335335
# pylint: disable=too-many-locals
336+
# pylint: disable=too-many-statements
336337
def process_response(self, request, response):
337338
if self._excluded_urls.url_disabled(request.build_absolute_uri("?")):
338339
return response
@@ -426,6 +427,10 @@ def process_response(self, request, response):
426427
duration_attrs_old = _parse_duration_attrs(
427428
duration_attrs, _HTTPStabilityMode.DEFAULT
428429
)
430+
# http.target to be included in old semantic conventions
431+
target = duration_attrs.get(SpanAttributes.HTTP_TARGET)
432+
if target:
433+
duration_attrs_old[SpanAttributes.HTTP_TARGET] = target
429434
self._duration_histogram_old.record(
430435
max(round(duration_s * 1000), 0), duration_attrs_old
431436
)

instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py

+157-144
Large diffs are not rendered by default.

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

+1
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ def _start_response(status, response_headers, *args, **kwargs):
395395
)
396396

397397
if request_route:
398+
# http.target to be included in old semantic conventions
398399
duration_attrs_old[SpanAttributes.HTTP_TARGET] = str(
399400
request_route
400401
)

instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/grpcext/_interceptor.py

+64-16
Original file line numberDiff line numberDiff line change
@@ -272,47 +272,95 @@ def unsubscribe(self, *args, **kwargs):
272272
self._channel.unsubscribe(*args, **kwargs)
273273

274274
def unary_unary(
275-
self, method, request_serializer=None, response_deserializer=None
275+
self,
276+
method,
277+
request_serializer=None,
278+
response_deserializer=None,
279+
_registered_method=False,
276280
):
277-
base_callable = self._channel.unary_unary(
278-
method, request_serializer, response_deserializer
279-
)
281+
if _registered_method:
282+
base_callable = self._channel.unary_unary(
283+
method,
284+
request_serializer,
285+
response_deserializer,
286+
_registered_method,
287+
)
288+
else:
289+
base_callable = self._channel.unary_unary(
290+
method, request_serializer, response_deserializer
291+
)
280292
if isinstance(self._interceptor, grpcext.UnaryClientInterceptor):
281293
return _InterceptorUnaryUnaryMultiCallable(
282294
method, base_callable, self._interceptor
283295
)
284296
return base_callable
285297

286298
def unary_stream(
287-
self, method, request_serializer=None, response_deserializer=None
299+
self,
300+
method,
301+
request_serializer=None,
302+
response_deserializer=None,
303+
_registered_method=False,
288304
):
289-
base_callable = self._channel.unary_stream(
290-
method, request_serializer, response_deserializer
291-
)
305+
if _registered_method:
306+
base_callable = self._channel.unary_stream(
307+
method,
308+
request_serializer,
309+
response_deserializer,
310+
_registered_method,
311+
)
312+
else:
313+
base_callable = self._channel.unary_stream(
314+
method, request_serializer, response_deserializer
315+
)
292316
if isinstance(self._interceptor, grpcext.StreamClientInterceptor):
293317
return _InterceptorUnaryStreamMultiCallable(
294318
method, base_callable, self._interceptor
295319
)
296320
return base_callable
297321

298322
def stream_unary(
299-
self, method, request_serializer=None, response_deserializer=None
323+
self,
324+
method,
325+
request_serializer=None,
326+
response_deserializer=None,
327+
_registered_method=False,
300328
):
301-
base_callable = self._channel.stream_unary(
302-
method, request_serializer, response_deserializer
303-
)
329+
if _registered_method:
330+
base_callable = self._channel.stream_unary(
331+
method,
332+
request_serializer,
333+
response_deserializer,
334+
_registered_method,
335+
)
336+
else:
337+
base_callable = self._channel.stream_unary(
338+
method, request_serializer, response_deserializer
339+
)
304340
if isinstance(self._interceptor, grpcext.StreamClientInterceptor):
305341
return _InterceptorStreamUnaryMultiCallable(
306342
method, base_callable, self._interceptor
307343
)
308344
return base_callable
309345

310346
def stream_stream(
311-
self, method, request_serializer=None, response_deserializer=None
347+
self,
348+
method,
349+
request_serializer=None,
350+
response_deserializer=None,
351+
_registered_method=False,
312352
):
313-
base_callable = self._channel.stream_stream(
314-
method, request_serializer, response_deserializer
315-
)
353+
if _registered_method:
354+
base_callable = self._channel.stream_stream(
355+
method,
356+
request_serializer,
357+
response_deserializer,
358+
_registered_method,
359+
)
360+
else:
361+
base_callable = self._channel.stream_stream(
362+
method, request_serializer, response_deserializer
363+
)
316364
if isinstance(self._interceptor, grpcext.StreamClientInterceptor):
317365
return _InterceptorStreamStreamMultiCallable(
318366
method, base_callable, self._interceptor
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
asgiref==3.7.2
2+
attrs==23.2.0
3+
Deprecated==1.2.14
4+
grpcio==1.63.0
5+
importlib-metadata==6.11.0
6+
iniconfig==2.0.0
7+
packaging==23.2
8+
pluggy==1.4.0
9+
protobuf==3.20.3
10+
py==1.11.0
11+
py-cpuinfo==9.0.0
12+
pytest==7.1.3
13+
pytest-asyncio==0.23.5
14+
pytest-benchmark==4.0.0
15+
tomli==2.0.1
16+
typing_extensions==4.9.0
17+
wrapt==1.16.0
18+
zipp==3.17.0
19+
-e opentelemetry-instrumentation
20+
-e instrumentation/opentelemetry-instrumentation-grpc

instrumentation/opentelemetry-instrumentation-urllib3/tests/test_urllib3_integration.py

+46-55
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,6 @@
3636
suppress_instrumentation,
3737
)
3838
from opentelemetry.propagate import get_global_textmap, set_global_textmap
39-
from opentelemetry.semconv.attributes.http_attributes import (
40-
HTTP_REQUEST_METHOD,
41-
HTTP_REQUEST_METHOD_ORIGINAL,
42-
HTTP_RESPONSE_STATUS_CODE,
43-
)
44-
from opentelemetry.semconv.attributes.url_attributes import URL_FULL
45-
from opentelemetry.semconv.trace import SpanAttributes
4639
from opentelemetry.test.mock_textmap import MockTextMapPropagator
4740
from opentelemetry.test.test_base import TestBase
4841
from opentelemetry.trace import Span
@@ -123,24 +116,29 @@ def assert_success_span(
123116
self.assertEqual(
124117
span.status.status_code, trace.status.StatusCode.UNSET
125118
)
126-
attr_old = {
127-
SpanAttributes.HTTP_METHOD: "GET",
128-
SpanAttributes.HTTP_URL: url,
129-
SpanAttributes.HTTP_STATUS_CODE: 200,
119+
expected_attr_old = {
120+
"http.method": "GET",
121+
"http.url": url,
122+
"http.status_code": 200,
130123
}
131124

132-
attr_new = {
133-
HTTP_REQUEST_METHOD: "GET",
134-
URL_FULL: url,
135-
HTTP_RESPONSE_STATUS_CODE: 200,
125+
expected_attr_new = {
126+
"http.request.method": "GET",
127+
"url.full": url,
128+
"http.response.status_code": 200,
136129
}
137130

138131
attributes = {
139-
_HTTPStabilityMode.DEFAULT: attr_old,
140-
_HTTPStabilityMode.HTTP: attr_new,
141-
_HTTPStabilityMode.HTTP_DUP: {**attr_new, **attr_old},
132+
_HTTPStabilityMode.DEFAULT: expected_attr_old,
133+
_HTTPStabilityMode.HTTP: expected_attr_new,
134+
_HTTPStabilityMode.HTTP_DUP: {
135+
**expected_attr_new,
136+
**expected_attr_old,
137+
},
142138
}
143-
self.assertEqual(span.attributes, attributes.get(sem_conv_opt_in_mode))
139+
self.assertDictEqual(
140+
dict(span.attributes), attributes.get(sem_conv_opt_in_mode)
141+
)
144142

145143
def assert_exception_span(
146144
self,
@@ -149,24 +147,29 @@ def assert_exception_span(
149147
):
150148
span = self.assert_span()
151149

152-
attr_old = {
153-
SpanAttributes.HTTP_METHOD: "GET",
154-
SpanAttributes.HTTP_URL: url,
150+
expected_attr_old = {
151+
"http.method": "GET",
152+
"http.url": url,
155153
}
156154

157-
attr_new = {
158-
HTTP_REQUEST_METHOD: "GET",
159-
URL_FULL: url,
155+
expected_attr_new = {
156+
"http.request.method": "GET",
157+
"url.full": url,
160158
# TODO: Add `error.type` attribute when supported
161159
}
162160

163161
attributes = {
164-
_HTTPStabilityMode.DEFAULT: attr_old,
165-
_HTTPStabilityMode.HTTP: attr_new,
166-
_HTTPStabilityMode.HTTP_DUP: {**attr_new, **attr_old},
162+
_HTTPStabilityMode.DEFAULT: expected_attr_old,
163+
_HTTPStabilityMode.HTTP: expected_attr_new,
164+
_HTTPStabilityMode.HTTP_DUP: {
165+
**expected_attr_new,
166+
**expected_attr_old,
167+
},
167168
}
168169

169-
self.assertEqual(span.attributes, attributes.get(sem_conv_opt_in_mode))
170+
self.assertDictEqual(
171+
dict(span.attributes), attributes.get(sem_conv_opt_in_mode)
172+
)
170173
self.assertEqual(
171174
trace.status.StatusCode.ERROR, span.status.status_code
172175
)
@@ -265,9 +268,7 @@ def test_basic_not_found(self):
265268
self.assertEqual(404, response.status)
266269

267270
span = self.assert_span()
268-
self.assertEqual(
269-
404, span.attributes.get(SpanAttributes.HTTP_STATUS_CODE)
270-
)
271+
self.assertEqual(404, span.attributes.get("http.status_code"))
271272
self.assertIs(trace.status.StatusCode.ERROR, span.status.status_code)
272273

273274
def test_basic_not_found_new_semconv(self):
@@ -278,7 +279,7 @@ def test_basic_not_found_new_semconv(self):
278279
self.assertEqual(404, response.status)
279280

280281
span = self.assert_span()
281-
self.assertEqual(404, span.attributes.get(HTTP_RESPONSE_STATUS_CODE))
282+
self.assertEqual(404, span.attributes.get("http.response.status_code"))
282283
self.assertIs(trace.status.StatusCode.ERROR, span.status.status_code)
283284

284285
def test_basic_not_found_both_semconv(self):
@@ -289,10 +290,8 @@ def test_basic_not_found_both_semconv(self):
289290
self.assertEqual(404, response.status)
290291

291292
span = self.assert_span()
292-
self.assertEqual(404, span.attributes.get(HTTP_RESPONSE_STATUS_CODE))
293-
self.assertEqual(
294-
404, span.attributes.get(SpanAttributes.HTTP_STATUS_CODE)
295-
)
293+
self.assertEqual(404, span.attributes.get("http.response.status_code"))
294+
self.assertEqual(404, span.attributes.get("http.status_code"))
296295
self.assertIs(trace.status.StatusCode.ERROR, span.status.status_code)
297296

298297
@mock.patch("httpretty.http.HttpBaseClass.METHODS", ("NONSTANDARD",))
@@ -303,12 +302,8 @@ def test_nonstandard_http_method(self):
303302
self.perform_request(self.HTTP_URL, method="NONSTANDARD")
304303
span = self.assert_span()
305304
self.assertEqual("HTTP", span.name)
306-
self.assertEqual(
307-
span.attributes.get(SpanAttributes.HTTP_METHOD), "_OTHER"
308-
)
309-
self.assertEqual(
310-
span.attributes.get(SpanAttributes.HTTP_STATUS_CODE), 405
311-
)
305+
self.assertEqual(span.attributes.get("http.method"), "_OTHER")
306+
self.assertEqual(span.attributes.get("http.status_code"), 405)
312307

313308
@mock.patch("httpretty.http.HttpBaseClass.METHODS", ("NONSTANDARD",))
314309
def test_nonstandard_http_method_new_semconv(self):
@@ -318,11 +313,11 @@ def test_nonstandard_http_method_new_semconv(self):
318313
self.perform_request(self.HTTP_URL, method="NONSTANDARD")
319314
span = self.assert_span()
320315
self.assertEqual("HTTP", span.name)
321-
self.assertEqual(span.attributes.get(HTTP_REQUEST_METHOD), "_OTHER")
316+
self.assertEqual(span.attributes.get("http.request.method"), "_OTHER")
322317
self.assertEqual(
323-
span.attributes.get(HTTP_REQUEST_METHOD_ORIGINAL), "NONSTANDARD"
318+
span.attributes.get("http.request.method_original"), "NONSTANDARD"
324319
)
325-
self.assertEqual(span.attributes.get(HTTP_RESPONSE_STATUS_CODE), 405)
320+
self.assertEqual(span.attributes.get("http.response.status_code"), 405)
326321

327322
@mock.patch("httpretty.http.HttpBaseClass.METHODS", ("NONSTANDARD",))
328323
def test_nonstandard_http_method_both_semconv(self):
@@ -332,17 +327,13 @@ def test_nonstandard_http_method_both_semconv(self):
332327
self.perform_request(self.HTTP_URL, method="NONSTANDARD")
333328
span = self.assert_span()
334329
self.assertEqual("HTTP", span.name)
330+
self.assertEqual(span.attributes.get("http.method"), "_OTHER")
331+
self.assertEqual(span.attributes.get("http.status_code"), 405)
332+
self.assertEqual(span.attributes.get("http.request.method"), "_OTHER")
335333
self.assertEqual(
336-
span.attributes.get(SpanAttributes.HTTP_METHOD), "_OTHER"
337-
)
338-
self.assertEqual(
339-
span.attributes.get(SpanAttributes.HTTP_STATUS_CODE), 405
340-
)
341-
self.assertEqual(span.attributes.get(HTTP_REQUEST_METHOD), "_OTHER")
342-
self.assertEqual(
343-
span.attributes.get(HTTP_REQUEST_METHOD_ORIGINAL), "NONSTANDARD"
334+
span.attributes.get("http.request.method_original"), "NONSTANDARD"
344335
)
345-
self.assertEqual(span.attributes.get(HTTP_RESPONSE_STATUS_CODE), 405)
336+
self.assertEqual(span.attributes.get("http.response.status_code"), 405)
346337

347338
def test_basic_http_non_default_port(self):
348339
url = "http://mock:666/status/200"

0 commit comments

Comments
 (0)