Skip to content

Commit 27264d9

Browse files
Merge branch 'main' into main
2 parents 9d13e80 + 9e12846 commit 27264d9

File tree

9 files changed

+80
-67
lines changed

9 files changed

+80
-67
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111
1212
## Unreleased
1313

14+
### Breaking changes
15+
16+
- `opentelemetry-instrumentation-botocore` Use `cloud.region` instead of `aws.region` span attribute as per semantic conventions.
17+
([#3474](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3474))
18+
19+
1420
## Version 1.33.0/0.54b0 (2025-05-09)
1521

1622
### Added

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-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

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,10 @@ def response_hook(span, response):
106106
from opentelemetry.instrumentation.elasticsearch.version import __version__
107107
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
108108
from opentelemetry.instrumentation.utils import unwrap
109-
from opentelemetry.semconv.trace import SpanAttributes
109+
from opentelemetry.semconv._incubating.attributes.db_attributes import (
110+
DB_STATEMENT,
111+
DB_SYSTEM,
112+
)
110113
from opentelemetry.trace import SpanKind, Status, StatusCode, get_tracer
111114

112115
from .utils import sanitize_body
@@ -288,7 +291,7 @@ def normalize_kwargs(k, v):
288291

289292
if span.is_recording():
290293
attributes = {
291-
SpanAttributes.DB_SYSTEM: "elasticsearch",
294+
DB_SYSTEM: "elasticsearch",
292295
}
293296
if url:
294297
attributes["elasticsearch.url"] = url
@@ -297,9 +300,7 @@ def normalize_kwargs(k, v):
297300
if body:
298301
# Don't set db.statement for bulk requests, as it can be very large
299302
if isinstance(body, dict):
300-
attributes[SpanAttributes.DB_STATEMENT] = (
301-
sanitize_body(body)
302-
)
303+
attributes[DB_STATEMENT] = sanitize_body(body)
303304
if params:
304305
attributes["elasticsearch.params"] = str(params)
305306
if doc_id:

tests/opentelemetry-docker-tests/tests/check_availability.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@
4242
MSSQL_PORT = int(os.getenv("MSSQL_PORT", "1433"))
4343
MSSQL_USER = os.getenv("MSSQL_USER", "sa")
4444
MSSQL_PASSWORD = os.getenv("MSSQL_PASSWORD", "yourStrong(!)Password")
45-
RETRY_COUNT = 8
46-
RETRY_INTERVAL = 5 # Seconds
45+
RETRY_COUNT = 5
46+
RETRY_INITIAL_INTERVAL = 2 # Seconds
4747

4848
logger = logging.getLogger(__name__)
4949

@@ -56,14 +56,16 @@ def wrapper():
5656
func()
5757
return
5858
except Exception as ex: # pylint: disable=broad-except
59+
# Exponential backoff
60+
backoff_interval = RETRY_INITIAL_INTERVAL * (2**i)
5961
logger.error(
6062
"waiting for %s, retry %d/%d [%s]",
6163
func.__name__,
6264
i + 1,
6365
RETRY_COUNT,
6466
ex,
6567
)
66-
time.sleep(RETRY_INTERVAL)
68+
time.sleep(backoff_interval)
6769
raise Exception(f"waiting for {func.__name__} failed")
6870

6971
return wrapper

0 commit comments

Comments
 (0)