Skip to content

Commit d6b953a

Browse files
authored
Merge branch 'main' into feature
2 parents 5add449 + a3a0b24 commit d6b953a

File tree

33 files changed

+224
-137
lines changed

33 files changed

+224
-137
lines changed

CHANGELOG.md

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

88
## Unreleased
99

10+
### Added
11+
12+
- Make Flask request span attributes available for `start_span`.
13+
([#1784](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1784))
14+
- Fix falcon instrumentation's usage of Span Status to only set the description if the status code is ERROR.
15+
([#1840](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1840))
1016
- Instrument all httpx versions >= 0.18. ([#1748](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1748))
1117
- Fix `Invalid type NoneType for attribute X (opentelemetry-instrumentation-aws-lambda)` error when some attributes do not exist
1218
([#1780](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1780))
@@ -25,9 +31,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2531
([#1778](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1778))
2632
- Add `excluded_urls` functionality to `urllib` and `urllib3` instrumentations
2733
([#1733](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1733))
28-
- Make Django request span attributes available for `start_span`.
34+
- Make Django request span attributes available for `start_span`.
2935
([#1730](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1730))
30-
- Make ASGI request span attributes available for `start_span`.
36+
- Make ASGI request span attributes available for `start_span`.
3137
([#1762](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1762))
3238
- `opentelemetry-instrumentation-celery` Add support for anonymous tasks.
3339
([#1407](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1407))
@@ -53,6 +59,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5359
- Fix Flask instrumentation to only close the span if it was created by the same request context.
5460
([#1692](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1692))
5561

62+
### Changed
63+
- Update HTTP server/client instrumentation span names to comply with spec
64+
([#1759](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1759)
65+
5666
## Version 1.17.0/0.38b0 (2023-03-22)
5767

5868
### Added

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ async def on_request_start(
179179
return
180180

181181
http_method = params.method.upper()
182-
request_span_name = f"HTTP {http_method}"
182+
request_span_name = f"{http_method}"
183183
request_url = (
184184
remove_url_credentials(trace_config_ctx.url_filter(params.url))
185185
if callable(trace_config_ctx.url_filter)

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

+7-6
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ def test_status_codes(self):
119119
self.assert_spans(
120120
[
121121
(
122-
"HTTP GET",
122+
"GET",
123123
(span_status, None),
124124
{
125125
SpanAttributes.HTTP_METHOD: "GET",
@@ -213,7 +213,7 @@ def strip_query_params(url: yarl.URL) -> str:
213213
self.assert_spans(
214214
[
215215
(
216-
"HTTP GET",
216+
"GET",
217217
(StatusCode.UNSET, None),
218218
{
219219
SpanAttributes.HTTP_METHOD: "GET",
@@ -247,7 +247,7 @@ async def do_request(url):
247247
self.assert_spans(
248248
[
249249
(
250-
"HTTP GET",
250+
"GET",
251251
(expected_status, None),
252252
{
253253
SpanAttributes.HTTP_METHOD: "GET",
@@ -274,7 +274,7 @@ async def request_handler(request):
274274
self.assert_spans(
275275
[
276276
(
277-
"HTTP GET",
277+
"GET",
278278
(StatusCode.ERROR, None),
279279
{
280280
SpanAttributes.HTTP_METHOD: "GET",
@@ -301,7 +301,7 @@ async def request_handler(request):
301301
self.assert_spans(
302302
[
303303
(
304-
"HTTP GET",
304+
"GET",
305305
(StatusCode.ERROR, None),
306306
{
307307
SpanAttributes.HTTP_METHOD: "GET",
@@ -338,7 +338,7 @@ async def do_request(url):
338338
self.assert_spans(
339339
[
340340
(
341-
"HTTP GET",
341+
"GET",
342342
(StatusCode.UNSET, None),
343343
{
344344
SpanAttributes.HTTP_METHOD: "GET",
@@ -391,6 +391,7 @@ def test_instrument(self):
391391
self.get_default_request(), self.URL, self.default_handler
392392
)
393393
span = self.assert_spans(1)
394+
self.assertEqual("GET", span.name)
394395
self.assertEqual("GET", span.attributes[SpanAttributes.HTTP_METHOD])
395396
self.assertEqual(
396397
f"http://{host}:{port}/test-path",

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

+12-7
Original file line numberDiff line numberDiff line change
@@ -415,18 +415,23 @@ def set_status_code(span, status_code):
415415

416416

417417
def get_default_span_details(scope: dict) -> Tuple[str, dict]:
418-
"""Default implementation for get_default_span_details
418+
"""
419+
Default span name is the HTTP method and URL path, or just the method.
420+
https://github.com/open-telemetry/opentelemetry-specification/pull/3165
421+
https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/http/#name
422+
419423
Args:
420424
scope: the ASGI scope dictionary
421425
Returns:
422426
a tuple of the span name, and any attributes to attach to the span.
423427
"""
424-
span_name = (
425-
scope.get("path", "").strip()
426-
or f"HTTP {scope.get('method', '').strip()}"
427-
)
428-
429-
return span_name, {}
428+
path = scope.get("path", "").strip()
429+
method = scope.get("method", "").strip()
430+
if method and path: # http
431+
return f"{method} {path}", {}
432+
if path: # websocket
433+
return path, {}
434+
return method, {} # http with no path
430435

431436

432437
def _collect_target_attribute(

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

+7-7
Original file line numberDiff line numberDiff line change
@@ -142,25 +142,25 @@ def validate_outputs(self, outputs, error=None, modifiers=None):
142142
self.assertEqual(len(span_list), 4)
143143
expected = [
144144
{
145-
"name": "/ http receive",
145+
"name": "GET / http receive",
146146
"kind": trace_api.SpanKind.INTERNAL,
147147
"attributes": {"type": "http.request"},
148148
},
149149
{
150-
"name": "/ http send",
150+
"name": "GET / http send",
151151
"kind": trace_api.SpanKind.INTERNAL,
152152
"attributes": {
153153
SpanAttributes.HTTP_STATUS_CODE: 200,
154154
"type": "http.response.start",
155155
},
156156
},
157157
{
158-
"name": "/ http send",
158+
"name": "GET / http send",
159159
"kind": trace_api.SpanKind.INTERNAL,
160160
"attributes": {"type": "http.response.body"},
161161
},
162162
{
163-
"name": "/",
163+
"name": "GET /",
164164
"kind": trace_api.SpanKind.SERVER,
165165
"attributes": {
166166
SpanAttributes.HTTP_METHOD: "GET",
@@ -231,7 +231,7 @@ def update_expected_span_name(expected):
231231
entry["name"] = span_name
232232
else:
233233
entry["name"] = " ".join(
234-
[span_name] + entry["name"].split(" ")[1:]
234+
[span_name] + entry["name"].split(" ")[2:]
235235
)
236236
return expected
237237

@@ -493,9 +493,9 @@ def update_expected_hook_results(expected):
493493
for entry in expected:
494494
if entry["kind"] == trace_api.SpanKind.SERVER:
495495
entry["name"] = "name from server hook"
496-
elif entry["name"] == "/ http receive":
496+
elif entry["name"] == "GET / http receive":
497497
entry["name"] = "name from client request hook"
498-
elif entry["name"] == "/ http send":
498+
elif entry["name"] == "GET / http send":
499499
entry["attributes"].update({"attr-from-hook": "value"})
500500
return expected
501501

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

+3-9
Original file line numberDiff line numberDiff line change
@@ -173,18 +173,12 @@ def _get_span_name(request):
173173
match = resolve(request.path)
174174

175175
if hasattr(match, "route"):
176-
return match.route
176+
return f"{request.method} {match.route}"
177177

178-
# Instead of using `view_name`, better to use `_func_name` as some applications can use similar
179-
# view names in different modules
180-
if hasattr(match, "_func_name"):
181-
return match._func_name # pylint: disable=protected-access
182-
183-
# Fallback for safety as `_func_name` private field
184-
return match.view_name
178+
return request.method
185179

186180
except Resolver404:
187-
return f"HTTP {request.method}"
181+
return request.method
188182

189183
# pylint: disable=too-many-locals
190184
def process_request(self, request):

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

+8-18
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,9 @@ def test_templated_route_get(self):
150150

151151
self.assertEqual(
152152
span.name,
153-
"^route/(?P<year>[0-9]{4})/template/$"
153+
"GET ^route/(?P<year>[0-9]{4})/template/$"
154154
if DJANGO_2_2
155-
else "tests.views.traced_template",
155+
else "GET",
156156
)
157157
self.assertEqual(span.kind, SpanKind.SERVER)
158158
self.assertEqual(span.status.status_code, StatusCode.UNSET)
@@ -177,9 +177,7 @@ def test_traced_get(self):
177177

178178
span = spans[0]
179179

180-
self.assertEqual(
181-
span.name, "^traced/" if DJANGO_2_2 else "tests.views.traced"
182-
)
180+
self.assertEqual(span.name, "GET ^traced/" if DJANGO_2_2 else "GET")
183181
self.assertEqual(span.kind, SpanKind.SERVER)
184182
self.assertEqual(span.status.status_code, StatusCode.UNSET)
185183
self.assertEqual(span.attributes[SpanAttributes.HTTP_METHOD], "GET")
@@ -215,9 +213,7 @@ def test_traced_post(self):
215213

216214
span = spans[0]
217215

218-
self.assertEqual(
219-
span.name, "^traced/" if DJANGO_2_2 else "tests.views.traced"
220-
)
216+
self.assertEqual(span.name, "POST ^traced/" if DJANGO_2_2 else "POST")
221217
self.assertEqual(span.kind, SpanKind.SERVER)
222218
self.assertEqual(span.status.status_code, StatusCode.UNSET)
223219
self.assertEqual(span.attributes[SpanAttributes.HTTP_METHOD], "POST")
@@ -241,9 +237,7 @@ def test_error(self):
241237

242238
span = spans[0]
243239

244-
self.assertEqual(
245-
span.name, "^error/" if DJANGO_2_2 else "tests.views.error"
246-
)
240+
self.assertEqual(span.name, "GET ^error/" if DJANGO_2_2 else "GET")
247241
self.assertEqual(span.kind, SpanKind.SERVER)
248242
self.assertEqual(span.status.status_code, StatusCode.ERROR)
249243
self.assertEqual(span.attributes[SpanAttributes.HTTP_METHOD], "GET")
@@ -307,9 +301,7 @@ def test_span_name(self):
307301
span = span_list[0]
308302
self.assertEqual(
309303
span.name,
310-
"^span_name/([0-9]{4})/$"
311-
if DJANGO_2_2
312-
else "tests.views.route_span_name",
304+
"GET ^span_name/([0-9]{4})/$" if DJANGO_2_2 else "GET",
313305
)
314306

315307
def test_span_name_for_query_string(self):
@@ -323,9 +315,7 @@ def test_span_name_for_query_string(self):
323315
span = span_list[0]
324316
self.assertEqual(
325317
span.name,
326-
"^span_name/([0-9]{4})/$"
327-
if DJANGO_2_2
328-
else "tests.views.route_span_name",
318+
"GET ^span_name/([0-9]{4})/$" if DJANGO_2_2 else "GET",
329319
)
330320

331321
def test_span_name_404(self):
@@ -334,7 +324,7 @@ def test_span_name_404(self):
334324
self.assertEqual(len(span_list), 1)
335325

336326
span = span_list[0]
337-
self.assertEqual(span.name, "HTTP GET")
327+
self.assertEqual(span.name, "GET")
338328

339329
def test_traced_request_attrs(self):
340330
Client().get("/span_name/1234/", CONTENT_TYPE="test/ct")

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

+7-7
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ async def test_templated_route_get(self):
137137

138138
span = spans[0]
139139

140-
self.assertEqual(span.name, "^route/(?P<year>[0-9]{4})/template/$")
140+
self.assertEqual(span.name, "GET ^route/(?P<year>[0-9]{4})/template/$")
141141
self.assertEqual(span.kind, SpanKind.SERVER)
142142
self.assertEqual(span.status.status_code, StatusCode.UNSET)
143143
self.assertEqual(span.attributes[SpanAttributes.HTTP_METHOD], "GET")
@@ -160,7 +160,7 @@ async def test_traced_get(self):
160160

161161
span = spans[0]
162162

163-
self.assertEqual(span.name, "^traced/")
163+
self.assertEqual(span.name, "GET ^traced/")
164164
self.assertEqual(span.kind, SpanKind.SERVER)
165165
self.assertEqual(span.status.status_code, StatusCode.UNSET)
166166
self.assertEqual(span.attributes[SpanAttributes.HTTP_METHOD], "GET")
@@ -195,7 +195,7 @@ async def test_traced_post(self):
195195

196196
span = spans[0]
197197

198-
self.assertEqual(span.name, "^traced/")
198+
self.assertEqual(span.name, "POST ^traced/")
199199
self.assertEqual(span.kind, SpanKind.SERVER)
200200
self.assertEqual(span.status.status_code, StatusCode.UNSET)
201201
self.assertEqual(span.attributes[SpanAttributes.HTTP_METHOD], "POST")
@@ -218,7 +218,7 @@ async def test_error(self):
218218

219219
span = spans[0]
220220

221-
self.assertEqual(span.name, "^error/")
221+
self.assertEqual(span.name, "GET ^error/")
222222
self.assertEqual(span.kind, SpanKind.SERVER)
223223
self.assertEqual(span.status.status_code, StatusCode.ERROR)
224224
self.assertEqual(span.attributes[SpanAttributes.HTTP_METHOD], "GET")
@@ -264,7 +264,7 @@ async def test_span_name(self):
264264
self.assertEqual(len(span_list), 1)
265265

266266
span = span_list[0]
267-
self.assertEqual(span.name, "^span_name/([0-9]{4})/$")
267+
self.assertEqual(span.name, "GET ^span_name/([0-9]{4})/$")
268268

269269
async def test_span_name_for_query_string(self):
270270
"""
@@ -275,15 +275,15 @@ async def test_span_name_for_query_string(self):
275275
self.assertEqual(len(span_list), 1)
276276

277277
span = span_list[0]
278-
self.assertEqual(span.name, "^span_name/([0-9]{4})/$")
278+
self.assertEqual(span.name, "GET ^span_name/([0-9]{4})/$")
279279

280280
async def test_span_name_404(self):
281281
await self.async_client.get("/span_name/1234567890/")
282282
span_list = self.memory_exporter.get_finished_spans()
283283
self.assertEqual(len(span_list), 1)
284284

285285
span = span_list[0]
286-
self.assertEqual(span.name, "HTTP GET")
286+
self.assertEqual(span.name, "GET")
287287

288288
async def test_traced_request_attrs(self):
289289
await self.async_client.get("/span_name/1234/", CONTENT_TYPE="test/ct")

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

+10-4
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ def response_hook(span, req, resp):
208208
from opentelemetry.metrics import get_meter
209209
from opentelemetry.semconv.metrics import MetricInstruments
210210
from opentelemetry.semconv.trace import SpanAttributes
211-
from opentelemetry.trace.status import Status
211+
from opentelemetry.trace.status import Status, StatusCode
212212
from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs
213213

214214
_logger = getLogger(__name__)
@@ -461,11 +461,17 @@ def process_response(
461461
try:
462462
status_code = int(status)
463463
span.set_attribute(SpanAttributes.HTTP_STATUS_CODE, status_code)
464+
otel_status_code = http_status_to_status_code(
465+
status_code, server_span=True
466+
)
467+
468+
# set the description only when the status code is ERROR
469+
if otel_status_code is not StatusCode.ERROR:
470+
reason = None
471+
464472
span.set_status(
465473
Status(
466-
status_code=http_status_to_status_code(
467-
status_code, server_span=True
468-
),
474+
status_code=otel_status_code,
469475
description=reason,
470476
)
471477
)

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ def test_404(self):
145145
spans = self.memory_exporter.get_finished_spans()
146146
self.assertEqual(len(spans), 1)
147147
span = spans[0]
148-
self.assertEqual(span.name, "HTTP GET")
148+
self.assertEqual(span.name, "GET /does-not-exist")
149149
self.assertEqual(span.status.status_code, StatusCode.UNSET)
150150
self.assertSpanHasAttributes(
151151
span,

0 commit comments

Comments
 (0)