diff --git a/.changelog/5547.fixed b/.changelog/5547.fixed new file mode 100644 index 00000000000..1b9fffc302d --- /dev/null +++ b/.changelog/5547.fixed @@ -0,0 +1 @@ +`opentelemetry-sdk`: don't read `process.executable.name` resource attribute when building default `service.name` diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py index a84c9f25fe9..c68d08d105d 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py @@ -65,7 +65,6 @@ from json import dumps from os import environ from types import ModuleType -from typing import cast from urllib import parse from opentelemetry.attributes import BoundedAttributes @@ -191,12 +190,8 @@ def create( if not resource.attributes.get(SERVICE_NAME, None): default_service_name = "unknown_service" - process_executable_name = cast( - str | None, - resource.attributes.get(PROCESS_EXECUTABLE_NAME, None), - ) - if process_executable_name: - default_service_name += ":" + process_executable_name + if sys.executable: + default_service_name += f":{os.path.basename(sys.executable)}" resource = resource.merge(Resource({SERVICE_NAME: default_service_name}, schema_url)) return resource diff --git a/opentelemetry-sdk/tests/resources/test_resources.py b/opentelemetry-sdk/tests/resources/test_resources.py index 282611dd1e3..9fdb0c83027 100644 --- a/opentelemetry-sdk/tests/resources/test_resources.py +++ b/opentelemetry-sdk/tests/resources/test_resources.py @@ -91,6 +91,7 @@ def setUp(self) -> None: def tearDown(self) -> None: environ.pop(OTEL_RESOURCE_ATTRIBUTES) + @patch("sys.executable", "/usr/bin/python3") def test_create(self): attributes = { "service": "ui", @@ -108,7 +109,7 @@ def test_create(self): TELEMETRY_SDK_LANGUAGE: "python", TELEMETRY_SDK_VERSION: _OPENTELEMETRY_SDK_VERSION, SERVICE_INSTANCE_ID: self._service_instance_id, - SERVICE_NAME: "unknown_service", + SERVICE_NAME: "unknown_service:python3", } resource = Resource.create(attributes) @@ -138,7 +139,7 @@ def test_create(self): Resource( { SERVICE_INSTANCE_ID: self._service_instance_id, - SERVICE_NAME: "unknown_service", + SERVICE_NAME: "unknown_service:python3", }, "", ) @@ -209,6 +210,7 @@ def test_resource_merge_empty_string(self): Resource({"service": "not-ui", "host": "service-host"}), ) + @patch("sys.executable", "/usr/bin/python3") def test_immutability(self): attributes = { "service": "ui", @@ -222,7 +224,7 @@ def test_immutability(self): TELEMETRY_SDK_LANGUAGE: "python", TELEMETRY_SDK_VERSION: _OPENTELEMETRY_SDK_VERSION, SERVICE_INSTANCE_ID: self._service_instance_id, - SERVICE_NAME: "unknown_service", + SERVICE_NAME: "unknown_service:python3", } attributes_copy = attributes.copy() @@ -243,13 +245,6 @@ def test_immutability(self): self.assertEqual(resource.schema_url, "") - def test_service_name_using_process_name(self): - resource = Resource.create({PROCESS_EXECUTABLE_NAME: "test"}) - self.assertEqual( - resource.attributes.get(SERVICE_NAME), - "unknown_service:test", - ) - def test_invalid_resource_attribute_values(self): with self.assertLogs(level=WARNING): resource = Resource( @@ -270,6 +265,7 @@ def test_invalid_resource_attribute_values(self): ) self.assertEqual(len(resource.attributes), 1) + @patch("sys.executable", "/usr/bin/python3") def test_aggregated_resources_no_detectors(self): aggregated_resources = get_aggregated_resources([]) self.assertEqual( @@ -278,7 +274,7 @@ def test_aggregated_resources_no_detectors(self): Resource( { SERVICE_INSTANCE_ID: self._service_instance_id, - SERVICE_NAME: "unknown_service", + SERVICE_NAME: "unknown_service:python3", }, "", ) @@ -309,6 +305,7 @@ def test_aggregated_resources_with_default_destroying_static_resource( ), ) + @patch("sys.executable", "/usr/bin/python3") def test_aggregated_resources_multiple_detectors(self): resource_detector1 = Mock(spec=ResourceDetector) resource_detector1.detect.return_value = Resource({"key1": "value1"}) @@ -329,7 +326,7 @@ def test_aggregated_resources_multiple_detectors(self): Resource( { SERVICE_INSTANCE_ID: self._service_instance_id, - SERVICE_NAME: "unknown_service", + SERVICE_NAME: "unknown_service:python3", }, "", ) @@ -345,6 +342,7 @@ def test_aggregated_resources_multiple_detectors(self): ), ) + @patch("sys.executable", "/usr/bin/python3") def test_aggregated_resources_different_schema_urls(self): resource_detector1 = Mock(spec=ResourceDetector) resource_detector1.detect.return_value = Resource({"key1": "value1"}, "") @@ -374,7 +372,7 @@ def test_aggregated_resources_different_schema_urls(self): Resource( { SERVICE_INSTANCE_ID: self._service_instance_id, - SERVICE_NAME: "unknown_service", + SERVICE_NAME: "unknown_service:python3", }, "", ) @@ -392,7 +390,7 @@ def test_aggregated_resources_different_schema_urls(self): Resource( { SERVICE_INSTANCE_ID: self._service_instance_id, - SERVICE_NAME: "unknown_service", + SERVICE_NAME: "unknown_service:python3", }, "", ) @@ -414,7 +412,7 @@ def test_aggregated_resources_different_schema_urls(self): Resource( { SERVICE_INSTANCE_ID: self._service_instance_id, - SERVICE_NAME: "unknown_service", + SERVICE_NAME: "unknown_service:python3", }, "", ) @@ -433,6 +431,7 @@ def test_aggregated_resources_different_schema_urls(self): self.assertIn("url1", log_entry.output[0]) self.assertIn("url2", log_entry.output[0]) + @patch("sys.executable", "/usr/bin/python3") def test_resource_detector_ignore_error(self): resource_detector = Mock(spec=ResourceDetector) resource_detector.detect.side_effect = Exception() @@ -444,7 +443,7 @@ def test_resource_detector_ignore_error(self): Resource( { SERVICE_INSTANCE_ID: self._service_instance_id, - SERVICE_NAME: "unknown_service", + SERVICE_NAME: "unknown_service:python3", }, "", ) @@ -487,6 +486,7 @@ def test_get_process_dependent_resource_empty(self, build_resource_detectors_moc self.assertEqual(_get_process_dependent_resource(), Resource.get_empty()) + @patch("sys.executable", "/usr/bin/python3") @patch("opentelemetry.sdk.resources.logger") def test_resource_detector_timeout(self, mock_logger): resource_detector = Mock(spec=ResourceDetector) @@ -498,7 +498,7 @@ def test_resource_detector_timeout(self, mock_logger): Resource( { SERVICE_INSTANCE_ID: self._service_instance_id, - SERVICE_NAME: "unknown_service", + SERVICE_NAME: "unknown_service:python3", }, "", ) @@ -537,6 +537,11 @@ def test_service_name_env(self): resource = Resource.create({"service.name": "from-code"}) self.assertEqual(resource.attributes["service.name"], "from-code") + @patch("sys.executable", "") + def test_service_name_without_sys_executable(self): + resource = Resource.create() + self.assertEqual(resource.attributes["service.name"], "unknown_service") + # pylint: disable=too-many-public-methods def _make_detector_ep(resource): @@ -784,19 +789,20 @@ def test_process_detector_handles_missing_executable(self): "", ) + @patch("sys.executable", "/usr/bin/python3") def test_resource_detector_entry_points_default(self): resource = Resource({}).create() self.assertEqual(resource.attributes["telemetry.sdk.language"], "python") self.assertEqual(resource.attributes["telemetry.sdk.name"], "opentelemetry") - self.assertEqual(resource.attributes["service.name"], "unknown_service") + self.assertEqual(resource.attributes["service.name"], "unknown_service:python3") self.assertEqual(resource.schema_url, "") resource = Resource({}).create({"a": "b", "c": "d"}) self.assertEqual(resource.attributes["telemetry.sdk.language"], "python") self.assertEqual(resource.attributes["telemetry.sdk.name"], "opentelemetry") - self.assertEqual(resource.attributes["service.name"], "unknown_service") + self.assertEqual(resource.attributes["service.name"], "unknown_service:python3") self.assertEqual(resource.attributes["a"], "b") self.assertEqual(resource.attributes["c"], "d") self.assertEqual(resource.schema_url, "") @@ -810,11 +816,12 @@ def test_resource_detector_entry_points_default(self): ] ), ) + @patch("sys.executable", "/usr/bin/python3") def test_resource_detector_entry_points_non_default(self): resource = Resource({}).create() self.assertEqual(resource.attributes["telemetry.sdk.language"], "python") self.assertEqual(resource.attributes["telemetry.sdk.name"], "opentelemetry") - self.assertEqual(resource.attributes["service.name"], "unknown_service") + self.assertEqual(resource.attributes["service.name"], "unknown_service:python3") self.assertEqual(resource.attributes["a"], "b") self.assertEqual(resource.schema_url, "") @@ -851,6 +858,7 @@ def test_resource_detector_entry_points_all(self): "'process' resource detector not enabled", ) + @patch("sys.executable", "/usr/bin/python4") def test_resource_detector_entry_points_otel(self): """ Test that OTELResourceDetector-resource-generated attributes are @@ -860,7 +868,7 @@ def test_resource_detector_entry_points_otel(self): resource = Resource({}).create() self.assertEqual(resource.attributes["telemetry.sdk.language"], "python") self.assertEqual(resource.attributes["telemetry.sdk.name"], "opentelemetry") - self.assertEqual(resource.attributes["service.name"], "unknown_service") + self.assertEqual(resource.attributes["service.name"], "unknown_service:python4") self.assertEqual(resource.attributes["a"], "b") self.assertEqual(resource.attributes["c"], "d") self.assertEqual(resource.schema_url, "") @@ -878,7 +886,7 @@ def test_resource_detector_entry_points_otel(self): self.assertEqual(resource.attributes["telemetry.sdk.name"], "opentelemetry") self.assertEqual( resource.attributes["service.name"], - "unknown_service:" + resource.attributes["process.executable.name"], + "unknown_service:python4", ) self.assertEqual(resource.attributes["a"], "b") self.assertEqual(resource.attributes["c"], "d") diff --git a/opentelemetry-sdk/tests/trace/test_trace.py b/opentelemetry-sdk/tests/trace/test_trace.py index c139e44e4ce..ea19f54e44e 100644 --- a/opentelemetry-sdk/tests/trace/test_trace.py +++ b/opentelemetry-sdk/tests/trace/test_trace.py @@ -681,6 +681,7 @@ def test_update_resource(self): new_span = updated_tracer.start_span("new") self.assertIs(new_span.resource, tracer_provider.resource) + @patch("sys.executable", "/usr/bin/python3") def test_default_span_resource(self): tracer_provider = trace.TracerProvider() tracer = tracer_provider.get_tracer(__name__) @@ -689,7 +690,7 @@ def test_default_span_resource(self): self.assertIsInstance(span.resource, resources.Resource) self.assertEqual( span.resource.attributes.get(resources.SERVICE_NAME), - "unknown_service", + "unknown_service:python3", ) self.assertEqual( span.resource.attributes.get(resources.TELEMETRY_SDK_LANGUAGE),