Skip to content

Commit 161ce21

Browse files
committed
Merge branch 'main' into feature/dbapi-instrument-respect-suppress-instrumentation
2 parents 2b00ca9 + ccdf522 commit 161ce21

File tree

10 files changed

+97
-84
lines changed

10 files changed

+97
-84
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
### Fixed
1515
- `opentelemetry-instrumentation-dbapi` Respect suppress_instrumentation functionality ([#3460](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3460))
1616

17+
### Breaking changes
18+
19+
- `opentelemetry-instrumentation-botocore` Use `cloud.region` instead of `aws.region` span attribute as per semantic conventions.
20+
([#3474](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3474))
1721

1822
## Version 1.33.0/0.54b0 (2025-05-09)
1923

RELEASING.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
(otherwise the workflow will pick up the version from `main` and just remove the `.dev` suffix).
1010
* Review the two pull requests that it creates.
1111
(one is targeted to the release branch and one is targeted to `main`).
12-
* The builds will fail for both the `main` and release pr because of validation rules. Follow the [release workflow](https://github.com/open-telemetry/opentelemetry-python/blob/main/RELEASING.md) for the core repo up until this same point. Change the SHAs of each PR to point at each other to get the `main` and release builds to pass.
12+
* The builds will fail for the release PR because of validation rules. Follow the [release workflow](https://github.com/open-telemetry/opentelemetry-python/blob/main/RELEASING.md) for the core repo up until this same point.
13+
* Close and reopen the PR so that the workflow will take into account the label automation we have in place
1314
* Merge the release PR.
1415
* Merge the PR to main (this can be done separately from [making the release](#making-the-release))
1516

exporter/opentelemetry-exporter-richconsole/src/opentelemetry/exporter/richconsole/__init__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@
6464
import opentelemetry.trace
6565
from opentelemetry.sdk.trace import ReadableSpan
6666
from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
67-
from opentelemetry.semconv.trace import SpanAttributes
67+
from opentelemetry.semconv._incubating.attributes.db_attributes import (
68+
DB_STATEMENT,
69+
)
6870

6971

7072
def _ns_to_time(nanoseconds):
@@ -120,7 +122,7 @@ def _child_add_optional_attributes(child: Tree, span: ReadableSpan):
120122
label=Text.from_markup("[bold cyan]Attributes :[/bold cyan] ")
121123
)
122124
for attribute in span.attributes:
123-
if attribute == SpanAttributes.DB_STATEMENT:
125+
if attribute == DB_STATEMENT:
124126
attributes.add(
125127
Text.from_markup(f"[bold cyan]{attribute} :[/bold cyan] ")
126128
)

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

Lines changed: 40 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,18 @@
3636
AioHttpClientInstrumentor,
3737
)
3838
from opentelemetry.instrumentation.utils import suppress_instrumentation
39+
from opentelemetry.semconv._incubating.attributes.http_attributes import (
40+
HTTP_METHOD,
41+
HTTP_STATUS_CODE,
42+
HTTP_URL,
43+
)
3944
from opentelemetry.semconv.attributes.error_attributes import ERROR_TYPE
4045
from opentelemetry.semconv.attributes.http_attributes import (
4146
HTTP_REQUEST_METHOD,
4247
HTTP_REQUEST_METHOD_ORIGINAL,
4348
HTTP_RESPONSE_STATUS_CODE,
4449
)
4550
from opentelemetry.semconv.attributes.url_attributes import URL_FULL
46-
from opentelemetry.semconv.trace import SpanAttributes
4751
from opentelemetry.test.test_base import TestBase
4852
from opentelemetry.trace import Span, StatusCode
4953
from opentelemetry.util._importlib_metadata import entry_points
@@ -136,9 +140,9 @@ def test_status_codes(self):
136140
)
137141
url = f"http://{host}:{port}/{path}"
138142
attributes = {
139-
SpanAttributes.HTTP_METHOD: "GET",
140-
SpanAttributes.HTTP_URL: url,
141-
SpanAttributes.HTTP_STATUS_CODE: status_code,
143+
HTTP_METHOD: "GET",
144+
HTTP_URL: url,
145+
HTTP_STATUS_CODE: status_code,
142146
}
143147
spans = [("GET", (span_status, None), attributes)]
144148
self.assert_spans(spans)
@@ -181,11 +185,11 @@ def test_status_codes_both_semconv(self):
181185
url = f"http://{host}:{port}/{path}"
182186
attributes = {
183187
HTTP_REQUEST_METHOD: "GET",
184-
SpanAttributes.HTTP_METHOD: "GET",
188+
HTTP_METHOD: "GET",
185189
URL_FULL: url,
186-
SpanAttributes.HTTP_URL: url,
190+
HTTP_URL: url,
187191
HTTP_RESPONSE_STATUS_CODE: status_code,
188-
SpanAttributes.HTTP_STATUS_CODE: status_code,
192+
HTTP_STATUS_CODE: status_code,
189193
}
190194
if status_code >= 400:
191195
attributes[ERROR_TYPE] = str(status_code.value)
@@ -292,16 +296,12 @@ def response_hook(
292296
(span.status.status_code, span.status.description),
293297
(StatusCode.UNSET, None),
294298
)
299+
self.assertEqual(span.attributes[HTTP_METHOD], method)
295300
self.assertEqual(
296-
span.attributes[SpanAttributes.HTTP_METHOD], method
297-
)
298-
self.assertEqual(
299-
span.attributes[SpanAttributes.HTTP_URL],
301+
span.attributes[HTTP_URL],
300302
f"http://{host}:{port}{path}",
301303
)
302-
self.assertEqual(
303-
span.attributes[SpanAttributes.HTTP_STATUS_CODE], HTTPStatus.OK
304-
)
304+
self.assertEqual(span.attributes[HTTP_STATUS_CODE], HTTPStatus.OK)
305305
self.assertIn("response_hook_attr", span.attributes)
306306
self.assertEqual(span.attributes["response_hook_attr"], "value")
307307
self.memory_exporter.clear()
@@ -325,9 +325,9 @@ def strip_query_params(url: yarl.URL) -> str:
325325
"GET",
326326
(StatusCode.UNSET, None),
327327
{
328-
SpanAttributes.HTTP_METHOD: "GET",
329-
SpanAttributes.HTTP_URL: f"http://{host}:{port}/some/path",
330-
SpanAttributes.HTTP_STATUS_CODE: int(HTTPStatus.OK),
328+
HTTP_METHOD: "GET",
329+
HTTP_URL: f"http://{host}:{port}/some/path",
330+
HTTP_STATUS_CODE: int(HTTPStatus.OK),
331331
},
332332
)
333333
]
@@ -359,8 +359,8 @@ async def do_request(url):
359359
"GET",
360360
(expected_status, "ClientConnectorError"),
361361
{
362-
SpanAttributes.HTTP_METHOD: "GET",
363-
SpanAttributes.HTTP_URL: url,
362+
HTTP_METHOD: "GET",
363+
HTTP_URL: url,
364364
},
365365
)
366366
]
@@ -385,8 +385,8 @@ async def request_handler(request):
385385
"GET",
386386
(StatusCode.ERROR, "ServerDisconnectedError"),
387387
{
388-
SpanAttributes.HTTP_METHOD: "GET",
389-
SpanAttributes.HTTP_URL: f"http://{host}:{port}/test",
388+
HTTP_METHOD: "GET",
389+
HTTP_URL: f"http://{host}:{port}/test",
390390
},
391391
)
392392
]
@@ -443,8 +443,8 @@ async def request_handler(request):
443443
HTTP_REQUEST_METHOD: "GET",
444444
URL_FULL: f"http://{host}:{port}/test",
445445
ERROR_TYPE: "ServerDisconnectedError",
446-
SpanAttributes.HTTP_METHOD: "GET",
447-
SpanAttributes.HTTP_URL: f"http://{host}:{port}/test",
446+
HTTP_METHOD: "GET",
447+
HTTP_URL: f"http://{host}:{port}/test",
448448
},
449449
)
450450
]
@@ -469,8 +469,8 @@ async def request_handler(request):
469469
"GET",
470470
(StatusCode.ERROR, "SocketTimeoutError"),
471471
{
472-
SpanAttributes.HTTP_METHOD: "GET",
473-
SpanAttributes.HTTP_URL: f"http://{host}:{port}/test_timeout",
472+
HTTP_METHOD: "GET",
473+
HTTP_URL: f"http://{host}:{port}/test_timeout",
474474
},
475475
)
476476
]
@@ -496,8 +496,8 @@ async def request_handler(request):
496496
"GET",
497497
(StatusCode.ERROR, "TooManyRedirects"),
498498
{
499-
SpanAttributes.HTTP_METHOD: "GET",
500-
SpanAttributes.HTTP_URL: f"http://{host}:{port}/test_too_many_redirects",
499+
HTTP_METHOD: "GET",
500+
HTTP_URL: f"http://{host}:{port}/test_too_many_redirects",
501501
},
502502
)
503503
]
@@ -532,11 +532,9 @@ async def do_request(url):
532532
"HTTP",
533533
(StatusCode.ERROR, None),
534534
{
535-
SpanAttributes.HTTP_METHOD: "_OTHER",
536-
SpanAttributes.HTTP_URL: url,
537-
SpanAttributes.HTTP_STATUS_CODE: int(
538-
HTTPStatus.METHOD_NOT_ALLOWED
539-
),
535+
HTTP_METHOD: "_OTHER",
536+
HTTP_URL: url,
537+
HTTP_STATUS_CODE: int(HTTPStatus.METHOD_NOT_ALLOWED),
540538
},
541539
)
542540
]
@@ -619,11 +617,9 @@ async def do_request(url):
619617
"GET",
620618
(StatusCode.UNSET, None),
621619
{
622-
SpanAttributes.HTTP_METHOD: "GET",
623-
SpanAttributes.HTTP_URL: (
624-
"http://localhost:5000/status/200"
625-
),
626-
SpanAttributes.HTTP_STATUS_CODE: int(HTTPStatus.OK),
620+
HTTP_METHOD: "GET",
621+
HTTP_URL: ("http://localhost:5000/status/200"),
622+
HTTP_STATUS_CODE: int(HTTPStatus.OK),
627623
},
628624
)
629625
]
@@ -671,12 +667,12 @@ def test_instrument(self):
671667
)
672668
span = self.assert_spans(1)
673669
self.assertEqual("GET", span.name)
674-
self.assertEqual("GET", span.attributes[SpanAttributes.HTTP_METHOD])
670+
self.assertEqual("GET", span.attributes[HTTP_METHOD])
675671
self.assertEqual(
676672
f"http://{host}:{port}/test-path",
677-
span.attributes[SpanAttributes.HTTP_URL],
673+
span.attributes[HTTP_URL],
678674
)
679-
self.assertEqual(200, span.attributes[SpanAttributes.HTTP_STATUS_CODE])
675+
self.assertEqual(200, span.attributes[HTTP_STATUS_CODE])
680676

681677
def test_instrument_new_semconv(self):
682678
AioHttpClientInstrumentor().uninstrument()
@@ -708,11 +704,11 @@ def test_instrument_both_semconv(self):
708704
url = f"http://{host}:{port}/test-path"
709705
attributes = {
710706
HTTP_REQUEST_METHOD: "GET",
711-
SpanAttributes.HTTP_METHOD: "GET",
707+
HTTP_METHOD: "GET",
712708
URL_FULL: url,
713-
SpanAttributes.HTTP_URL: url,
709+
HTTP_URL: url,
714710
HTTP_RESPONSE_STATUS_CODE: 200,
715-
SpanAttributes.HTTP_STATUS_CODE: 200,
711+
HTTP_STATUS_CODE: 200,
716712
}
717713
span = self.assert_spans(1)
718714
self.assertEqual("GET", span.name)
@@ -852,7 +848,7 @@ def strip_query_params(url: yarl.URL) -> str:
852848
span = self.assert_spans(1)
853849
self.assertEqual(
854850
f"http://{host}:{port}/test-path",
855-
span.attributes[SpanAttributes.HTTP_URL],
851+
span.attributes[HTTP_URL],
856852
)
857853

858854
def test_hooks(self):

instrumentation/opentelemetry-instrumentation-aiohttp-server/tests/test_aiohttp_server_integration.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@
2424
AioHttpServerInstrumentor,
2525
)
2626
from opentelemetry.instrumentation.utils import suppress_http_instrumentation
27-
from opentelemetry.semconv.trace import SpanAttributes
27+
from opentelemetry.semconv._incubating.attributes.http_attributes import (
28+
HTTP_METHOD,
29+
HTTP_STATUS_CODE,
30+
HTTP_URL,
31+
)
2832
from opentelemetry.test.globals_test import reset_trace_globals
2933
from opentelemetry.test.test_base import TestBase
3034
from opentelemetry.util._importlib_metadata import entry_points
@@ -127,15 +131,11 @@ async def test_status_code_instrumentation(
127131

128132
[span] = memory_exporter.get_finished_spans()
129133

130-
assert expected_method.value == span.attributes[SpanAttributes.HTTP_METHOD]
131-
assert (
132-
expected_status_code
133-
== span.attributes[SpanAttributes.HTTP_STATUS_CODE]
134-
)
134+
assert expected_method.value == span.attributes[HTTP_METHOD]
135+
assert expected_status_code == span.attributes[HTTP_STATUS_CODE]
135136

136137
assert (
137-
f"http://{server.host}:{server.port}{url}"
138-
== span.attributes[SpanAttributes.HTTP_URL]
138+
f"http://{server.host}:{server.port}{url}" == span.attributes[HTTP_URL]
139139
)
140140

141141

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

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -60,49 +60,51 @@ async def main():
6060
from opentelemetry.instrumentation.asyncpg.version import __version__
6161
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
6262
from opentelemetry.instrumentation.utils import unwrap
63-
from opentelemetry.semconv.trace import (
63+
from opentelemetry.semconv._incubating.attributes.db_attributes import (
64+
DB_NAME,
65+
DB_STATEMENT,
66+
DB_SYSTEM,
67+
DB_USER,
6468
DbSystemValues,
69+
)
70+
from opentelemetry.semconv._incubating.attributes.net_attributes import (
71+
NET_PEER_NAME,
72+
NET_PEER_PORT,
73+
NET_TRANSPORT,
6574
NetTransportValues,
66-
SpanAttributes,
6775
)
6876
from opentelemetry.trace import SpanKind
6977
from opentelemetry.trace.status import Status, StatusCode
7078

7179

7280
def _hydrate_span_from_args(connection, query, parameters) -> dict:
7381
"""Get network and database attributes from connection."""
74-
span_attributes = {
75-
SpanAttributes.DB_SYSTEM: DbSystemValues.POSTGRESQL.value
76-
}
82+
span_attributes = {DB_SYSTEM: DbSystemValues.POSTGRESQL.value}
7783

7884
# connection contains _params attribute which is a namedtuple ConnectionParameters.
7985
# https://github.com/MagicStack/asyncpg/blob/master/asyncpg/connection.py#L68
8086

8187
params = getattr(connection, "_params", None)
8288
dbname = getattr(params, "database", None)
8389
if dbname:
84-
span_attributes[SpanAttributes.DB_NAME] = dbname
90+
span_attributes[DB_NAME] = dbname
8591
user = getattr(params, "user", None)
8692
if user:
87-
span_attributes[SpanAttributes.DB_USER] = user
93+
span_attributes[DB_USER] = user
8894

8995
# connection contains _addr attribute which is either a host/port tuple, or unix socket string
9096
# https://magicstack.github.io/asyncpg/current/_modules/asyncpg/connection.html
9197
addr = getattr(connection, "_addr", None)
9298
if isinstance(addr, tuple):
93-
span_attributes[SpanAttributes.NET_PEER_NAME] = addr[0]
94-
span_attributes[SpanAttributes.NET_PEER_PORT] = addr[1]
95-
span_attributes[SpanAttributes.NET_TRANSPORT] = (
96-
NetTransportValues.IP_TCP.value
97-
)
99+
span_attributes[NET_PEER_NAME] = addr[0]
100+
span_attributes[NET_PEER_PORT] = addr[1]
101+
span_attributes[NET_TRANSPORT] = NetTransportValues.IP_TCP.value
98102
elif isinstance(addr, str):
99-
span_attributes[SpanAttributes.NET_PEER_NAME] = addr
100-
span_attributes[SpanAttributes.NET_TRANSPORT] = (
101-
NetTransportValues.OTHER.value
102-
)
103+
span_attributes[NET_PEER_NAME] = addr
104+
span_attributes[NET_TRANSPORT] = NetTransportValues.OTHER.value
103105

104106
if query is not None:
105-
span_attributes[SpanAttributes.DB_STATEMENT] = query
107+
span_attributes[DB_STATEMENT] = query
106108

107109
if parameters is not None and len(parameters) > 0:
108110
span_attributes["db.statement.parameters"] = str(parameters)

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ def response_hook(span, service_name, operation_name, result):
109109
)
110110
from opentelemetry.metrics import Instrument, Meter, get_meter
111111
from opentelemetry.propagators.aws.aws_xray_propagator import AwsXRayPropagator
112+
from opentelemetry.semconv._incubating.attributes.cloud_attributes import (
113+
CLOUD_REGION,
114+
)
112115
from opentelemetry.semconv.trace import SpanAttributes
113116
from opentelemetry.trace import get_tracer
114117
from opentelemetry.trace.span import Span
@@ -276,8 +279,7 @@ def _patched_api_call(self, original_func, instance, args, kwargs):
276279
SpanAttributes.RPC_SYSTEM: "aws-api",
277280
SpanAttributes.RPC_SERVICE: call_context.service_id,
278281
SpanAttributes.RPC_METHOD: call_context.operation,
279-
# TODO: update when semantic conventions exist
280-
"aws.region": call_context.region,
282+
CLOUD_REGION: call_context.region,
281283
**get_server_attributes(call_context.endpoint_url),
282284
}
283285

instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_instrumentation.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
)
2828
from opentelemetry.propagate import get_global_textmap, set_global_textmap
2929
from opentelemetry.propagators.aws.aws_xray_propagator import TRACE_HEADER_KEY
30+
from opentelemetry.semconv._incubating.attributes.cloud_attributes import (
31+
CLOUD_REGION,
32+
)
3033
from opentelemetry.semconv.trace import SpanAttributes
3134
from opentelemetry.test.mock_textmap import MockTextMapPropagator
3235
from opentelemetry.test.test_base import TestBase
@@ -61,7 +64,7 @@ def _default_span_attributes(self, service: str, operation: str):
6164
SpanAttributes.RPC_SYSTEM: "aws-api",
6265
SpanAttributes.RPC_SERVICE: service,
6366
SpanAttributes.RPC_METHOD: operation,
64-
"aws.region": self.region,
67+
CLOUD_REGION: self.region,
6568
"retry_attempts": 0,
6669
SpanAttributes.HTTP_STATUS_CODE: 200,
6770
# Some services like IAM or STS have a global endpoint and exclude specified region.
@@ -527,7 +530,7 @@ def test_server_attributes(self):
527530
attributes={
528531
SpanAttributes.SERVER_ADDRESS: "iam.amazonaws.com",
529532
SpanAttributes.SERVER_PORT: 443,
530-
"aws.region": "aws-global",
533+
CLOUD_REGION: "aws-global",
531534
},
532535
)
533536

0 commit comments

Comments
 (0)