Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 11 additions & 0 deletions src/sap_cloud_sdk/core/telemetry/config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"""Configuration for OpenTelemetry telemetry."""

import logging
import os
from dataclasses import dataclass
from importlib.metadata import entry_points as _entry_points
from typing import Optional
from opentelemetry.sdk.resources import SERVICE_NAME
from sap_cloud_sdk.core._version import get_version
Expand All @@ -22,6 +24,8 @@
SDK_NAME,
)

logger = logging.getLogger(__name__)

# Default attribute values
DEFAULT_UNKNOWN = "unknown"

Expand Down Expand Up @@ -172,6 +176,13 @@ def create_resource_attributes_from_env() -> dict:
if service_display_name is not None:
attributes[ATTR_SAP_SERVICE_DISPLAY_NAME] = service_display_name

for _ep in _entry_points(group="sap_cloud_sdk.resource_providers"):
try:
_provider = _ep.load()
attributes.update(_provider())
except Exception:
logger.debug("Failed to load resource provider %s", _ep.name, exc_info=True)

return attributes


Expand Down
46 changes: 46 additions & 0 deletions tests/core/unit/telemetry/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,3 +299,49 @@ def test_service_display_name_independent_of_other_attributes(self):

assert attrs[ATTR_SAP_SERVICE_DISPLAY_NAME] == "My Service"
assert attrs[ATTR_SAP_ORD_ID] == "my-ord-id"


def _make_ep(name: str, attrs: dict, raises: Exception | None = None):
"""Build a mock entry point that returns *attrs* (or raises *raises*)."""
from unittest.mock import MagicMock
ep = MagicMock()
ep.name = name
if raises is not None:
ep.load.return_value = MagicMock(side_effect=raises)
else:
ep.load.return_value = lambda: attrs
return ep


class TestSdkResourceProviderEntryPoints:
"""Tests for companion-SDK resource attribute discovery via entry points."""

def test_provider_attributes_appear_in_resource(self):
mock_ep = _make_ep("test_sdk", {"sap.test_sdk.version": "1.0.0"})
with patch("sap_cloud_sdk.core.telemetry.config._entry_points", return_value=[mock_ep]):
attrs = create_resource_attributes_from_env()
assert attrs["sap.test_sdk.version"] == "1.0.0"

def test_multiple_providers_are_merged(self):
eps = [
_make_ep("sdk_a", {"sap.sdk_a.version": "1.0"}),
_make_ep("sdk_b", {"sap.sdk_b.version": "2.0"}),
]
with patch("sap_cloud_sdk.core.telemetry.config._entry_points", return_value=eps):
attrs = create_resource_attributes_from_env()
assert attrs["sap.sdk_a.version"] == "1.0"
assert attrs["sap.sdk_b.version"] == "2.0"

def test_failing_provider_is_skipped_silently(self):
bad_ep = _make_ep("broken", {}, raises=RuntimeError("boom"))
good_ep = _make_ep("good", {"sap.good.version": "3.0"})
with patch("sap_cloud_sdk.core.telemetry.config._entry_points", return_value=[bad_ep, good_ep]):
attrs = create_resource_attributes_from_env()
assert attrs["sap.good.version"] == "3.0"
assert "sap.broken.version" not in attrs

def test_no_providers_does_not_affect_cloud_sdk_keys(self):
with patch("sap_cloud_sdk.core.telemetry.config._entry_points", return_value=[]):
attrs = create_resource_attributes_from_env()
from sap_cloud_sdk.core.telemetry.constants import ATTR_SAP_SDK_VERSION
assert ATTR_SAP_SDK_VERSION in attrs
Loading