Skip to content

Commit bb9e9bf

Browse files
authored
Merge branch 'main' into exclude_attribute
2 parents 5674ed3 + 634cec5 commit bb9e9bf

30 files changed

Lines changed: 1744 additions & 355 deletions

File tree

.changelog/5220.added

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
`opentelemetry-docker-tests`: Refactor Docker tests to properly validate contents of exported telemetry

.changelog/5329.changed

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
opentelemetry-sdk: revert BoundedAttributes RLock back to Lock

.changelog/5340.fixed

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
`opentelemetry-sdk`: raise `ValueError` when `ExplicitBucketHistogramAggregation` boundaries are not strictly increasing or finite

.changelog/5347.added

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
`opentelemetry-sdk`: point the declarative configuration package README at the shared [language support status matrix](https://github.com/open-telemetry/opentelemetry-configuration/blob/main/language-support-status.md#python) in the `opentelemetry-configuration` repo, so Python conformance status lives alongside the other languages instead of being duplicated per language SDK.

.changelog/5353.added

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
`opentelemetry-sdk`: document that Python-implementation extensions (`OTEL_PYTHON_*` variables) are bypassed when `OTEL_CONFIG_FILE` is set. The env-var initialisation path is skipped entirely in favour of the declarative file; honouring these alongside a config file is tracked as a follow-up.

.changelog/5363.added

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
`opentelemetry-sdk`: wire id_generator from declarative configuration to TracerProvider

CONTRIBUTING.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ You can run `tox` with the following arguments:
7373
- `tox -e tracecontext` to run integration tests for tracecontext.
7474
- `tox -e precommit` to run all `pre-commit` actions
7575

76+
The `docker-tests-otlpexporter` tests use
77+
[inline-snapshot](https://github.com/15r10nk/inline-snapshot) to assert
78+
on expected values inline in the test code. If you need to create or
79+
update a snapshot, run the tests with `--inline-snapshot=create` or
80+
`--inline-snapshot=fix` (see the
81+
[inline-snapshot docs](https://15r10nk.github.io/inline-snapshot/latest/)
82+
for all options).
83+
7684
### Changelog
7785

7886
This project uses [towncrier](https://towncrier.readthedocs.io/) to manage the changelog. Instead of editing `CHANGELOG.md` directly, each PR should include a changelog fragment file in the `.changelog/` directory.

docs/sdk/configuration.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,13 @@ Behavior notes
119119
not consulted. Environment variables can still be read indirectly by
120120
components the file enables (for example resource detectors) and via
121121
``${env:VAR}`` substitution.
122+
* Python-implementation extensions (``OTEL_PYTHON_*`` variables such as
123+
``OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED`` or
124+
``OTEL_PYTHON_TRACER_CONFIGURATOR``) are **not** applied when
125+
``OTEL_CONFIG_FILE`` is set: the env-var initialisation path is skipped
126+
entirely. If your app currently relies on one of these and you are
127+
migrating to a config file, plan to capture the equivalent behaviour in
128+
the file (or in code) instead.
122129
* Sections omitted from the file leave the corresponding global provider
123130
unset (a no-op provider), per the specification.
124131
* Setting ``disabled: true`` at the top level turns the SDK into a no-op.

opentelemetry-api/src/opentelemetry/attributes/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ def __init__(
262262
MutableMapping[str, types.AnyValue]
263263
| OrderedDict[str, types.AnyValue]
264264
) = {}
265-
self._lock = threading.RLock()
265+
self._lock = threading.Lock()
266266
if attributes:
267267
for key, value in attributes.items():
268268
self[key] = value

opentelemetry-api/tests/attributes/test_attributes.py

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
# type: ignore
55

66
import copy
7+
import logging
8+
import threading
79
import unittest
810
import unittest.mock
911
from collections.abc import MutableSequence
@@ -269,19 +271,47 @@ def test_immutable(self):
269271
with self.assertRaises(TypeError):
270272
bdict["should-not-work"] = "dict immutable"
271273

272-
def test_locking(self):
273-
"""Supporting test case for a commit titled: Fix class BoundedAttributes to have RLock rather than Lock. See #3858.
274-
The change was introduced because __iter__ of the class BoundedAttributes holds lock, and we observed some deadlock symptoms
275-
in the codebase. This test case is to verify that the fix works as expected.
274+
def test_no_deadlock_on_reentrant_logging(self):
275+
"""Regression test for #3858.
276+
277+
The deadlock scenario: a logging handler intercepts the warning
278+
emitted by _clean_attribute for an invalid value and calls __setitem__
279+
on the same BoundedAttributes instance from the same thread.
280+
With _clean_attribute called inside the lock this caused a deadlock.
281+
With _clean_attribute called before the lock is acquired, no deadlock
282+
occurs.
276283
"""
277284
bdict = BoundedAttributes(immutable=False)
278285

279-
with bdict._lock: # pylint: disable=protected-access
280-
for num in range(100):
281-
bdict[str(num)] = num
282-
283-
for num in range(100):
284-
self.assertEqual(bdict[str(num)], num)
286+
class ReentrantHandler(logging.Handler):
287+
def emit(self, _record):
288+
# Simulates Sentry intercepting the OTel warning and writing
289+
# back into the same BoundedAttributes on the same thread.
290+
bdict["reentrant.key"] = "set_by_handler"
291+
292+
otel_logger = logging.getLogger("opentelemetry.attributes")
293+
handler = ReentrantHandler()
294+
otel_logger.addHandler(handler)
295+
try:
296+
completed = threading.Event()
297+
298+
def run():
299+
# None is an invalid attribute value and triggers _logger.warning
300+
# in _clean_attribute, which fires the ReentrantHandler above.
301+
bdict["trigger.key"] = None
302+
completed.set()
303+
304+
thread = threading.Thread(target=run, daemon=True)
305+
thread.start()
306+
thread.join(timeout=2.0)
307+
308+
self.assertTrue(
309+
completed.is_set(),
310+
"Deadlock detected: __setitem__ did not complete within 2s",
311+
)
312+
self.assertEqual(bdict.get("reentrant.key"), "set_by_handler")
313+
finally:
314+
otel_logger.removeHandler(handler)
285315

286316
# pylint: disable=no-self-use
287317
def test_extended_attributes(self):

0 commit comments

Comments
 (0)