Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
5c26f00
config: add resource and propagator creation from declarative config
MikeGoldsmith Mar 13, 2026
8232012
update changelog with PR number
MikeGoldsmith Mar 13, 2026
8329ae4
fix pylint, pyright and ruff errors in resource/propagator config
MikeGoldsmith Mar 13, 2026
506d816
address review feedback: use _DEFAULT_RESOURCE, fix bool_array coercion
MikeGoldsmith Mar 16, 2026
8232d48
fix linter
MikeGoldsmith Mar 16, 2026
6ed3425
Merge branch 'main' of github.com:open-telemetry/opentelemetry-python…
MikeGoldsmith Mar 16, 2026
99753f9
address review feedback: single coercion table, simplify attributes m…
MikeGoldsmith Mar 16, 2026
8ba91d8
use Callable type annotation on _array helper
MikeGoldsmith Mar 17, 2026
516aecc
Merge remote-tracking branch 'upstream/main' into mike/config-resourc…
MikeGoldsmith Mar 20, 2026
9cfdcce
add detection infrastructure foundations for resource detectors
MikeGoldsmith Mar 20, 2026
103ff08
move service.name default into base resource
MikeGoldsmith Mar 20, 2026
7f51034
remove unused logging import from _propagator.py
MikeGoldsmith Mar 20, 2026
9cd70ae
wire host resource detector in declarative config
MikeGoldsmith Mar 20, 2026
a1166ea
add changelog entry for host resource detector (#5002)
MikeGoldsmith Mar 20, 2026
7b5fbc2
merge upstream/main, fix pylint no-self-use, update HostResourceDetec…
MikeGoldsmith Mar 29, 2026
edf9d7e
fix import sort in test_resources.py (ruff)
MikeGoldsmith Mar 29, 2026
822410c
merge upstream/main
MikeGoldsmith Apr 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

- `opentelemetry-sdk`: Add `host` resource detector support to declarative file configuration via `detection_development.detectors[].host`
([#5002](https://github.com/open-telemetry/opentelemetry-python/pull/5002))
- `opentelemetry-sdk`: Add shared `_parse_headers` helper for declarative config OTLP exporters
([#5021](https://github.com/open-telemetry/opentelemetry-python/pull/5021))
- `opentelemetry-api`: Replace a broad exception in attribute cleaning tests to satisfy pylint in the `lint-opentelemetry-api` CI job
Expand Down
2 changes: 1 addition & 1 deletion opentelemetry-sdk/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ console = "opentelemetry.sdk.trace.export:ConsoleSpanExporter"
otel = "opentelemetry.sdk.resources:OTELResourceDetector"
process = "opentelemetry.sdk.resources:ProcessResourceDetector"
os = "opentelemetry.sdk.resources:OsResourceDetector"
host = "opentelemetry.sdk.resources:_HostResourceDetector"
host = "opentelemetry.sdk.resources:HostResourceDetector"

[project.urls]
Homepage = "https://github.com/open-telemetry/opentelemetry-python/tree/main/opentelemetry-sdk"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from opentelemetry.sdk.resources import (
_DEFAULT_RESOURCE,
SERVICE_NAME,
HostResourceDetector,
Resource,
)

Expand Down Expand Up @@ -149,6 +150,8 @@ def _run_detectors(
is updated in-place; later detectors overwrite earlier ones for the
same key.
"""
if detector_config.host is not None:
detected_attrs.update(HostResourceDetector().detect().attributes)


def _filter_attributes(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -490,10 +490,8 @@ def detect(self) -> "Resource":
)


class _HostResourceDetector(ResourceDetector): # type: ignore[reportUnusedClass]
"""
The HostResourceDetector detects the hostname and architecture attributes.
"""
class HostResourceDetector(ResourceDetector):
"""Detects host.name (hostname) and host.arch (CPU architecture)."""

def detect(self) -> "Resource":
return Resource(
Expand Down
77 changes: 77 additions & 0 deletions opentelemetry-sdk/tests/_configuration/test_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,22 @@
# limitations under the License.

import os
import socket
import unittest
from unittest.mock import patch

from opentelemetry.sdk._configuration._resource import create_resource
from opentelemetry.sdk._configuration.models import (
AttributeNameValue,
AttributeType,
ExperimentalResourceDetection,
ExperimentalResourceDetector,
IncludeExclude,
)
from opentelemetry.sdk._configuration.models import Resource as ResourceConfig
from opentelemetry.sdk.resources import (
HOST_ARCH,
HOST_NAME,
SERVICE_NAME,
TELEMETRY_SDK_LANGUAGE,
TELEMETRY_SDK_NAME,
Expand Down Expand Up @@ -295,3 +301,74 @@ def test_attributes_list_invalid_pair_skipped(self):
self.assertEqual(resource.attributes["foo"], "bar")
self.assertNotIn("no-equals", resource.attributes)
self.assertTrue(any("no-equals" in msg for msg in cm.output))


class TestHostResourceDetector(unittest.TestCase):
@staticmethod
def _config_with_host() -> ResourceConfig:
return ResourceConfig(
detection_development=ExperimentalResourceDetection(
detectors=[ExperimentalResourceDetector(host={})]
)
)

def test_host_detector_adds_host_attributes(self):
resource = create_resource(self._config_with_host())
self.assertIn(HOST_NAME, resource.attributes)
self.assertEqual(resource.attributes[HOST_NAME], socket.gethostname())
self.assertIn(HOST_ARCH, resource.attributes)

def test_host_detector_also_includes_sdk_defaults(self):
resource = create_resource(self._config_with_host())
self.assertEqual(resource.attributes[TELEMETRY_SDK_LANGUAGE], "python")
self.assertIn(TELEMETRY_SDK_VERSION, resource.attributes)

def test_host_detector_not_run_when_absent(self):
resource = create_resource(ResourceConfig())
self.assertNotIn(HOST_NAME, resource.attributes)
self.assertNotIn(HOST_ARCH, resource.attributes)

def test_host_detector_not_run_when_detection_development_is_none(self):
resource = create_resource(ResourceConfig(detection_development=None))
self.assertNotIn(HOST_NAME, resource.attributes)

def test_host_detector_not_run_when_detectors_list_empty(self):
config = ResourceConfig(
detection_development=ExperimentalResourceDetection(detectors=[])
)
resource = create_resource(config)
self.assertNotIn(HOST_NAME, resource.attributes)

def test_explicit_attributes_override_host_detector(self):
config = ResourceConfig(
attributes=[
AttributeNameValue(name="host.name", value="custom-host")
],
detection_development=ExperimentalResourceDetection(
detectors=[ExperimentalResourceDetector(host={})]
),
)
resource = create_resource(config)
self.assertEqual(resource.attributes[HOST_NAME], "custom-host")

def test_included_filter_limits_host_attributes(self):
config = ResourceConfig(
detection_development=ExperimentalResourceDetection(
detectors=[ExperimentalResourceDetector(host={})],
attributes=IncludeExclude(included=["host.name"]),
)
)
resource = create_resource(config)
self.assertIn(HOST_NAME, resource.attributes)
self.assertNotIn(HOST_ARCH, resource.attributes)

def test_excluded_filter_removes_host_attributes(self):
config = ResourceConfig(
detection_development=ExperimentalResourceDetection(
detectors=[ExperimentalResourceDetector(host={})],
attributes=IncludeExclude(excluded=["host.name"]),
)
)
resource = create_resource(config)
self.assertNotIn(HOST_NAME, resource.attributes)
self.assertIn(HOST_ARCH, resource.attributes)
4 changes: 2 additions & 2 deletions opentelemetry-sdk/tests/resources/test_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@
TELEMETRY_SDK_LANGUAGE,
TELEMETRY_SDK_NAME,
TELEMETRY_SDK_VERSION,
HostResourceDetector,
OsResourceDetector,
OTELResourceDetector,
ProcessResourceDetector,
Resource,
ResourceDetector,
_HostResourceDetector,
get_aggregated_resources,
)

Expand Down Expand Up @@ -813,7 +813,7 @@ class TestHostResourceDetector(unittest.TestCase):
@patch("platform.machine", lambda: "AMD64")
def test_host_resource_detector(self):
resource = get_aggregated_resources(
[_HostResourceDetector()],
[HostResourceDetector()],
Resource({}),
)
self.assertEqual(resource.attributes[HOST_NAME], "foo")
Expand Down
Loading