From f557a53aba709c36de574894451cc5f9e4212dec Mon Sep 17 00:00:00 2001 From: jerevoss Date: Wed, 8 May 2024 11:17:09 -0700 Subject: [PATCH 01/19] auto instrumentation parameter proposal --- .../sdk/_configuration/__init__.py | 54 ++++++++++++------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py index ff7b04df4a4..f2c6b03ca67 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py @@ -354,37 +354,54 @@ def _import_id_generator(id_generator_name: str) -> IdGenerator: raise RuntimeError(f"{id_generator_name} is not an IdGenerator") -def _initialize_components(auto_instrumentation_version): - trace_exporters, metric_exporters, log_exporters = _import_exporters( - _get_exporter_names("traces"), - _get_exporter_names("metrics"), - _get_exporter_names("logs"), +def _initialize_components(**kwargs): + auto_instrumentation_version = kwargs.get("auto_instrumentation_version") + # Could be trace_exporters or span_exporters + span_exporter_names = kwargs.get("span_exporter_names") + metric_exporter_names = kwargs.get("metric_exporter_names") + log_exporter_names = kwargs.get("log_exporter_names") + sampler_name = kwargs.get("sampler_name") + # Could be attribute dict or Resource object + resource_attributes = kwargs.get("resource_attributes") + logging_enabled = kwargs.get("logging_enabled") + # Could come before or after + span_exporters, metric_exporters, log_exporters = _import_exporters( + span_exporter_names + _get_exporter_names("traces"), + metric_exporter_names + _get_exporter_names("metrics"), + log_exporter_names + _get_exporter_names("logs"), ) - sampler_name = _get_sampler() + if sampler_name is None: + sampler_name = _get_sampler() sampler = _import_sampler(sampler_name) - id_generator_name = _get_id_generator() + if id_generator_name is None: + id_generator_name = _get_id_generator() id_generator = _import_id_generator(id_generator_name) # if env var OTEL_RESOURCE_ATTRIBUTES is given, it will read the service_name # from the env variable else defaults to "unknown_service" - auto_resource = {} + auto_resource_attributes = {} + if resource_attributes is not None: + auto_resource_attributes = resource_attributes # populate version if using auto-instrumentation if auto_instrumentation_version: - auto_resource[ResourceAttributes.TELEMETRY_AUTO_VERSION] = ( - auto_instrumentation_version - ) - resource = Resource.create(auto_resource) + auto_resource_attributes[ + ResourceAttributes.TELEMETRY_AUTO_VERSION + ] = auto_instrumentation_version + resource = Resource.create(auto_resource_attributes) _init_tracing( - exporters=trace_exporters, + exporters=span_exporters, id_generator=id_generator, sampler=sampler, resource=resource, ) _init_metrics(metric_exporters, resource) - logging_enabled = os.getenv( - _OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED, "false" - ) - if logging_enabled.strip().lower() == "true": + # This could also be paramaterized + if logging_enabled is None: + logging_enabled = os.getenv( + _OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED, "false" + ).strip().lower() == "true" + # Could be string or bool + if logging_enabled: _init_logging(log_exporters, resource) @@ -428,4 +445,5 @@ class _OTelSDKConfigurator(_BaseConfigurator): """ def _configure(self, **kwargs): - _initialize_components(kwargs.get("auto_instrumentation_version")) + # _initialize_components(kwargs.get("auto_instrumentation_version")) + _initialize_components(**kwargs) From bee44a9c1489a15dbef5c693a7ed0310edd41e09 Mon Sep 17 00:00:00 2001 From: jerevoss Date: Wed, 8 May 2024 14:35:16 -0700 Subject: [PATCH 02/19] Specify args at level of initialize_components --- .../sdk/_configuration/__init__.py | 47 +++++++++++++------ 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py index f2c6b03ca67..7936b483f6d 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py @@ -354,16 +354,20 @@ def _import_id_generator(id_generator_name: str) -> IdGenerator: raise RuntimeError(f"{id_generator_name} is not an IdGenerator") -def _initialize_components(**kwargs): - auto_instrumentation_version = kwargs.get("auto_instrumentation_version") - # Could be trace_exporters or span_exporters - span_exporter_names = kwargs.get("span_exporter_names") - metric_exporter_names = kwargs.get("metric_exporter_names") - log_exporter_names = kwargs.get("log_exporter_names") - sampler_name = kwargs.get("sampler_name") - # Could be attribute dict or Resource object - resource_attributes = kwargs.get("resource_attributes") - logging_enabled = kwargs.get("logging_enabled") +def _initialize_components( + auto_instrumentation_version: str = None, + # Could be trace_exporters or span_exporters + # Could be full span processors + span_exporter_names: str = None, + metric_exporter_names: str = None, + log_exporter_names: str = None, + # Could be sampler obj + sampler_name: str = None, + # Could be attribute dict or Resource object + resource_attributes: dict = None, + # resource: Resource = None, + logging_enabled: bool = None, + ): # Could come before or after span_exporters, metric_exporters, log_exporters = _import_exporters( span_exporter_names + _get_exporter_names("traces"), @@ -373,20 +377,33 @@ def _initialize_components(**kwargs): if sampler_name is None: sampler_name = _get_sampler() sampler = _import_sampler(sampler_name) + # If using sampler obj instead of name + # if sampler is None: + # sampler_name = _get_sampler() + # sampler = _import_sampler(sampler_name) if id_generator_name is None: id_generator_name = _get_id_generator() id_generator = _import_id_generator(id_generator_name) # if env var OTEL_RESOURCE_ATTRIBUTES is given, it will read the service_name # from the env variable else defaults to "unknown_service" - auto_resource_attributes = {} - if resource_attributes is not None: - auto_resource_attributes = resource_attributes + # If using attributes dict instead of resource object + if resource_attributes is None: + resource_attributes = {} # populate version if using auto-instrumentation if auto_instrumentation_version: - auto_resource_attributes[ + resource_attributes[ ResourceAttributes.TELEMETRY_AUTO_VERSION ] = auto_instrumentation_version - resource = Resource.create(auto_resource_attributes) + resource = Resource.create(resource_attributes) + # If using resource object instead of attributes dict + # if resource is None: + # resource = Resource.create() + # populate version if using auto-instrumentation + # if auto_instrumentation_version: + # resource.attributes()[ + # ResourceAttributes.TELEMETRY_AUTO_VERSION + # ] = auto_instrumentation_version + # resource = Resource.create(resource) _init_tracing( exporters=span_exporters, From e1f8a47e8f54119f24b99bd0350b4e58d61e7ce4 Mon Sep 17 00:00:00 2001 From: jerevoss Date: Wed, 8 May 2024 14:40:59 -0700 Subject: [PATCH 03/19] Optional types --- .../sdk/_configuration/__init__.py | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py index 7936b483f6d..d773eeab192 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py @@ -50,7 +50,10 @@ MetricReader, PeriodicExportingMetricReader, ) -from opentelemetry.sdk.resources import Resource +from opentelemetry.sdk.resources import ( + Attributes, + Resource +) from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor, SpanExporter from opentelemetry.sdk.trace.id_generator import IdGenerator @@ -355,18 +358,19 @@ def _import_id_generator(id_generator_name: str) -> IdGenerator: def _initialize_components( - auto_instrumentation_version: str = None, + auto_instrumentation_version: Optional[str] = None, # Could be trace_exporters or span_exporters # Could be full span processors - span_exporter_names: str = None, - metric_exporter_names: str = None, - log_exporter_names: str = None, + span_exporter_names: Optional[list[str]] = None, + metric_exporter_names: Optional[list[str]] = None, + log_exporter_names: Optional[list[str]] = None, # Could be sampler obj - sampler_name: str = None, + sampler_name: Optional[str] = None, + # sampler: Optional[Sampler] = None, # Could be attribute dict or Resource object - resource_attributes: dict = None, - # resource: Resource = None, - logging_enabled: bool = None, + resource_attributes: Optional[Attributes] = None, + # resource: Optional[Resource] = None, + logging_enabled: Optional[bool] = None, ): # Could come before or after span_exporters, metric_exporters, log_exporters = _import_exporters( @@ -398,7 +402,7 @@ def _initialize_components( # If using resource object instead of attributes dict # if resource is None: # resource = Resource.create() - # populate version if using auto-instrumentation + # # populate version if using auto-instrumentation # if auto_instrumentation_version: # resource.attributes()[ # ResourceAttributes.TELEMETRY_AUTO_VERSION From 7026675bfb229033f7b71eb316079845f27e3b1d Mon Sep 17 00:00:00 2001 From: jerevoss Date: Wed, 8 May 2024 14:42:03 -0700 Subject: [PATCH 04/19] Resource obj instead of attributes --- .../sdk/_configuration/__init__.py | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py index d773eeab192..392a8754f7f 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py @@ -368,8 +368,8 @@ def _initialize_components( sampler_name: Optional[str] = None, # sampler: Optional[Sampler] = None, # Could be attribute dict or Resource object - resource_attributes: Optional[Attributes] = None, - # resource: Optional[Resource] = None, + # resource_attributes: Optional[Attributes] = None, + resource: Optional[Resource] = None, logging_enabled: Optional[bool] = None, ): # Could come before or after @@ -391,23 +391,23 @@ def _initialize_components( # if env var OTEL_RESOURCE_ATTRIBUTES is given, it will read the service_name # from the env variable else defaults to "unknown_service" # If using attributes dict instead of resource object - if resource_attributes is None: - resource_attributes = {} - # populate version if using auto-instrumentation - if auto_instrumentation_version: - resource_attributes[ - ResourceAttributes.TELEMETRY_AUTO_VERSION - ] = auto_instrumentation_version - resource = Resource.create(resource_attributes) - # If using resource object instead of attributes dict - # if resource is None: - # resource = Resource.create() + # if resource_attributes is None: + # resource_attributes = {} # # populate version if using auto-instrumentation # if auto_instrumentation_version: - # resource.attributes()[ + # resource_attributes[ # ResourceAttributes.TELEMETRY_AUTO_VERSION # ] = auto_instrumentation_version - # resource = Resource.create(resource) + # resource = Resource.create(resource_attributes) + # If using resource object instead of attributes dict + if resource is None: + resource = Resource.create() + # populate version if using auto-instrumentation + if auto_instrumentation_version: + resource.attributes()[ + ResourceAttributes.TELEMETRY_AUTO_VERSION + ] = auto_instrumentation_version + resource = Resource.create(resource) _init_tracing( exporters=span_exporters, From 238ca3df0fac563c44b47e39683df3d33519867d Mon Sep 17 00:00:00 2001 From: jerevoss Date: Wed, 8 May 2024 14:44:24 -0700 Subject: [PATCH 05/19] Using sampler obj instead of name --- .../sdk/_configuration/__init__.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py index 392a8754f7f..fe41de57d66 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py @@ -365,8 +365,8 @@ def _initialize_components( metric_exporter_names: Optional[list[str]] = None, log_exporter_names: Optional[list[str]] = None, # Could be sampler obj - sampler_name: Optional[str] = None, - # sampler: Optional[Sampler] = None, + # sampler_name: Optional[str] = None, + sampler: Optional[Sampler] = None, # Could be attribute dict or Resource object # resource_attributes: Optional[Attributes] = None, resource: Optional[Resource] = None, @@ -378,13 +378,14 @@ def _initialize_components( metric_exporter_names + _get_exporter_names("metrics"), log_exporter_names + _get_exporter_names("logs"), ) - if sampler_name is None: - sampler_name = _get_sampler() - sampler = _import_sampler(sampler_name) - # If using sampler obj instead of name - # if sampler is None: + # If using sampler name instead of sampler obj + # if sampler_name is None: # sampler_name = _get_sampler() - # sampler = _import_sampler(sampler_name) + # sampler = _import_sampler(sampler_name) + # If using sampler obj instead of name. This means user would have to specify the rate on their own + if sampler is None: + sampler_name = _get_sampler() + sampler = _import_sampler(sampler_name) if id_generator_name is None: id_generator_name = _get_id_generator() id_generator = _import_id_generator(id_generator_name) From 0264fa0a3f9ca072dbe8539b3dd3448dd5db474b Mon Sep 17 00:00:00 2001 From: jerevoss Date: Mon, 20 May 2024 15:16:46 -0700 Subject: [PATCH 06/19] Changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a4e061bb62..a9247d92184 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - unit annotations (enclosed in curly braces like `{requests}`) are stripped away - units with slash are converted e.g. `m/s` -> `meters_per_second`. - The exporter's API is not changed +- Add parameters for Distros and configurators to configure autoinstrumentation + ([#3864] (https://github.com/open-telemetry/opentelemetry-python/pull/3864)) ## Version 1.24.0/0.45b0 (2024-03-28) From 4b996a6bf498c2f42fe75e8145de1c9ab27c312d Mon Sep 17 00:00:00 2001 From: jerevoss Date: Thu, 23 May 2024 11:33:35 -0700 Subject: [PATCH 07/19] All tests but custom configurator pass --- .../sdk/_configuration/__init__.py | 53 +++++++------------ opentelemetry-sdk/tests/test_configurator.py | 31 +++++++++-- 2 files changed, 47 insertions(+), 37 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py index fe41de57d66..f9cfb21802b 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py @@ -360,55 +360,41 @@ def _import_id_generator(id_generator_name: str) -> IdGenerator: def _initialize_components( auto_instrumentation_version: Optional[str] = None, # Could be trace_exporters or span_exporters - # Could be full span processors - span_exporter_names: Optional[list[str]] = None, - metric_exporter_names: Optional[list[str]] = None, - log_exporter_names: Optional[list[str]] = None, - # Could be sampler obj - # sampler_name: Optional[str] = None, + span_exporter_names: Optional[List[str]] = None, + metric_exporter_names: Optional[List[str]] = None, + log_exporter_names: Optional[List[str]] = None, sampler: Optional[Sampler] = None, - # Could be attribute dict or Resource object - # resource_attributes: Optional[Attributes] = None, - resource: Optional[Resource] = None, + resource_attributes: Optional[Attributes] = None, + id_generator: IdGenerator = None, logging_enabled: Optional[bool] = None, ): - # Could come before or after + if span_exporter_names is None: + span_exporter_names = list() + if metric_exporter_names is None: + metric_exporter_names = list() + if log_exporter_names is None: + log_exporter_names = list() span_exporters, metric_exporters, log_exporters = _import_exporters( span_exporter_names + _get_exporter_names("traces"), metric_exporter_names + _get_exporter_names("metrics"), log_exporter_names + _get_exporter_names("logs"), ) - # If using sampler name instead of sampler obj - # if sampler_name is None: - # sampler_name = _get_sampler() - # sampler = _import_sampler(sampler_name) - # If using sampler obj instead of name. This means user would have to specify the rate on their own if sampler is None: sampler_name = _get_sampler() sampler = _import_sampler(sampler_name) - if id_generator_name is None: + if id_generator is None: id_generator_name = _get_id_generator() - id_generator = _import_id_generator(id_generator_name) - # if env var OTEL_RESOURCE_ATTRIBUTES is given, it will read the service_name - # from the env variable else defaults to "unknown_service" - # If using attributes dict instead of resource object - # if resource_attributes is None: - # resource_attributes = {} - # # populate version if using auto-instrumentation - # if auto_instrumentation_version: - # resource_attributes[ - # ResourceAttributes.TELEMETRY_AUTO_VERSION - # ] = auto_instrumentation_version - # resource = Resource.create(resource_attributes) - # If using resource object instead of attributes dict - if resource is None: - resource = Resource.create() + id_generator = _import_id_generator(id_generator_name) + if resource_attributes is None: + resource_attributes = {} # populate version if using auto-instrumentation if auto_instrumentation_version: - resource.attributes()[ + resource_attributes[ ResourceAttributes.TELEMETRY_AUTO_VERSION ] = auto_instrumentation_version - resource = Resource.create(resource) + # if env var OTEL_RESOURCE_ATTRIBUTES is given, it will read the service_name + # from the env variable else defaults to "unknown_service" + resource = Resource.create(resource_attributes) _init_tracing( exporters=span_exporters, @@ -467,5 +453,4 @@ class _OTelSDKConfigurator(_BaseConfigurator): """ def _configure(self, **kwargs): - # _initialize_components(kwargs.get("auto_instrumentation_version")) _initialize_components(**kwargs) diff --git a/opentelemetry-sdk/tests/test_configurator.py b/opentelemetry-sdk/tests/test_configurator.py index b825ae931cb..dd2f18dd941 100644 --- a/opentelemetry-sdk/tests/test_configurator.py +++ b/opentelemetry-sdk/tests/test_configurator.py @@ -40,6 +40,7 @@ _init_metrics, _init_tracing, _initialize_components, + _OTelSDKConfigurator, ) from opentelemetry.sdk._logs import LoggingHandler from opentelemetry.sdk._logs.export import ConsoleLogExporter @@ -645,7 +646,7 @@ def test_logging_init_exporter(self): @patch("opentelemetry.sdk._configuration._init_tracing") @patch("opentelemetry.sdk._configuration._init_logging") def test_logging_init_disable_default(self, logging_mock, tracing_mock): - _initialize_components("auto-version") + _initialize_components(auto_instrumentation_version="auto-version") self.assertEqual(logging_mock.call_count, 0) self.assertEqual(tracing_mock.call_count, 1) @@ -660,7 +661,7 @@ def test_logging_init_disable_default(self, logging_mock, tracing_mock): @patch("opentelemetry.sdk._configuration._init_logging") def test_logging_init_enable_env(self, logging_mock, tracing_mock): with self.assertLogs(level=WARNING): - _initialize_components("auto-version") + _initialize_components(auto_instrumentation_version="auto-version") self.assertEqual(logging_mock.call_count, 1) self.assertEqual(tracing_mock.call_count, 1) @@ -677,7 +678,7 @@ def test_logging_init_enable_env(self, logging_mock, tracing_mock): def test_initialize_components_resource( self, metrics_mock, logging_mock, tracing_mock ): - _initialize_components("auto-version") + _initialize_components(auto_instrumentation_version="auto-version") self.assertEqual(logging_mock.call_count, 1) self.assertEqual(tracing_mock.call_count, 1) self.assertEqual(metrics_mock.call_count, 1) @@ -910,3 +911,27 @@ def test__import_config_components_missing_component( str(error.value), "Requested component 'a' not found in entry point 'name'", ) + +class CustomConfigurator(_OTelSDKConfigurator): + def _configure(self, **kwargs): + kwargs["sampler"] = "TEST_SAMPLER" + super.configure(**kwargs) + +class TestOTelSDKConfigurator(TestCase): + @patch("opentelemetry.sdk._configuration._initialize_components") + def test_configure(self, mock_init_comp): + configurator = _OTelSDKConfigurator() + configurator.configure(auto_instrumentation_version="TEST_VERSION") + mock_init_comp.assert_called_with(auto_instrumentation_version="TEST_VERSION") + + @patch("opentelemetry.sdk._configuration._initialize_components") + def test_custom_configurator(self, mock_init_comp): + configurator = CustomConfigurator() + configurator.configure(auto_instrumentation_version="TEST_VERSION") + kwargs = { + "auto_instrumentation_version": "TEST_VERSION", + "sampler": "TEST_SAMPLER", + } + mock_init_comp.assert_called_with(**kwargs) + + From 80070e3cb3b49812f290b97e790a43da58c005a5 Mon Sep 17 00:00:00 2001 From: jerevoss Date: Thu, 23 May 2024 13:23:38 -0700 Subject: [PATCH 08/19] Add custom configurator test --- opentelemetry-sdk/tests/test_configurator.py | 24 ++++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/opentelemetry-sdk/tests/test_configurator.py b/opentelemetry-sdk/tests/test_configurator.py index dd2f18dd941..558d8687fd3 100644 --- a/opentelemetry-sdk/tests/test_configurator.py +++ b/opentelemetry-sdk/tests/test_configurator.py @@ -912,26 +912,20 @@ def test__import_config_components_missing_component( "Requested component 'a' not found in entry point 'name'", ) -class CustomConfigurator(_OTelSDKConfigurator): - def _configure(self, **kwargs): - kwargs["sampler"] = "TEST_SAMPLER" - super.configure(**kwargs) - -class TestOTelSDKConfigurator(TestCase): - @patch("opentelemetry.sdk._configuration._initialize_components") - def test_configure(self, mock_init_comp): - configurator = _OTelSDKConfigurator() - configurator.configure(auto_instrumentation_version="TEST_VERSION") - mock_init_comp.assert_called_with(auto_instrumentation_version="TEST_VERSION") +class TestConfigurator(TestCase): + class CustomConfigurator(_OTelSDKConfigurator): + def _configure(self, **kwargs): + kwargs["sampler"] = "TEST_SAMPLER" + super()._configure(**kwargs) @patch("opentelemetry.sdk._configuration._initialize_components") def test_custom_configurator(self, mock_init_comp): - configurator = CustomConfigurator() - configurator.configure(auto_instrumentation_version="TEST_VERSION") + custom_configurator = TestConfigurator.CustomConfigurator() + custom_configurator._configure(auto_instrumentation_version="TEST_VERSION2") kwargs = { - "auto_instrumentation_version": "TEST_VERSION", + "auto_instrumentation_version": "TEST_VERSION2", "sampler": "TEST_SAMPLER", } - mock_init_comp.assert_called_with(**kwargs) + mock_init_comp.assert_called_once_with(**kwargs) From be73bcaf94732ce913079efc9966cad2f37e7764 Mon Sep 17 00:00:00 2001 From: jerevoss Date: Thu, 23 May 2024 14:09:10 -0700 Subject: [PATCH 09/19] Tests pass. Adding more --- .../sdk/_configuration/__init__.py | 1 - opentelemetry-sdk/tests/test_configurator.py | 83 +++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py index f9cfb21802b..af8e7f5ff2e 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py @@ -359,7 +359,6 @@ def _import_id_generator(id_generator_name: str) -> IdGenerator: def _initialize_components( auto_instrumentation_version: Optional[str] = None, - # Could be trace_exporters or span_exporters span_exporter_names: Optional[List[str]] = None, metric_exporter_names: Optional[List[str]] = None, log_exporter_names: Optional[List[str]] = None, diff --git a/opentelemetry-sdk/tests/test_configurator.py b/opentelemetry-sdk/tests/test_configurator.py index 558d8687fd3..b1867a7b7bb 100644 --- a/opentelemetry-sdk/tests/test_configurator.py +++ b/opentelemetry-sdk/tests/test_configurator.py @@ -693,6 +693,89 @@ def test_initialize_components_resource( self.assertEqual(logging_resource, metrics_resource) self.assertEqual(tracing_resource, metrics_resource) + @patch.dict( + environ, + { + "OTEL_TRACES_EXPORTER": _EXPORTER_OTLP, + "OTEL_METRICS_EXPORTER": _EXPORTER_OTLP_PROTO_GRPC, + "OTEL_LOGS_EXPORTER": _EXPORTER_OTLP_PROTO_HTTP, + }, + ) + @patch.dict( + environ, + { + "OTEL_RESOURCE_ATTRIBUTES": "service.name=otlp-service, custom.key.1=env-value", + "OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED": "False", + }, + ) + @patch("opentelemetry.sdk._configuration._import_exporters") + @patch("opentelemetry.sdk._configuration._get_exporter_names") + @patch("opentelemetry.sdk._configuration._init_tracing") + @patch("opentelemetry.sdk._configuration._init_logging") + @patch("opentelemetry.sdk._configuration._init_metrics") + def test_initialize_components_kwargs( + self, metrics_mock, logging_mock, tracing_mock, exporter_names_mock, import_exporters_mock + ): + exporter_names_mock.return_value = ["env_var_exporter_1", "env_var_exporter_2"] + import_exporters_mock.return_value = ( + "TEST_SPAN_EXPORTERS_DICT", + "TEST_METRICS_EXPORTERS_DICT", + "TEST_LOG_EXPORTERS_DICT", + ) + # custom_id_generator = CustomIdGenerator() + # sampler = Sampler() + kwargs = { + "auto_instrumentation_version": "auto-version", + "span_exporter_names": ["custom_span_exporter"], + "metric_exporter_names": ["custom_metric_exporter"], + "log_exporter_names": ["custom_log_exporter"], + "sampler": "TEST_SAMPLER", + "resource_attributes": { + "custom.key.1": "pass-in-value-1", + "custom.key.2": "pass-in-value-2", + }, + "id_generator": "TEST_GENERATOR", + "logging_enabled": True, + } + _initialize_components(**kwargs) + + import_exporters_mock.assert_called_once_with( + ["custom_span_exporter", "env_var_exporter_1", "env_var_exporter_2"], + ["custom_metric_exporter", "env_var_exporter_1", "env_var_exporter_2"], + ["custom_log_exporter", "env_var_exporter_1", "env_var_exporter_2"] + ) + # tracing_mock.assert_called_once_with( + # exporters="TEST_SPAN_EXPORTERS_DICT", + # id_generator="TEST_GENERATOR", + # sampler="TEST_SAMPLER," + # resource=resource, + # ) + # metrics_mock.assert_called_once_with( + # "TEST_METRICS_EXPORTERS_DICT", + # resource, + # ) + # logging_mock.assert_called_once_with( + # "TEST_LOG_EXPORTERS_DICT", + # resource, + # ) + + self.assertEqual(logging_mock.call_count, 1) + self.assertEqual(tracing_mock.call_count, 1) + self.assertEqual(metrics_mock.call_count, 1) + + _, args, _ = logging_mock.mock_calls[0] + logging_resource = args[1] + print(logging_resource.attributes) + _, _, kwargs = tracing_mock.mock_calls[0] + tracing_resource = kwargs["resource"] + _, args, _ = metrics_mock.mock_calls[0] + metrics_resource = args[1] + self.assertEqual(logging_resource, tracing_resource) + self.assertEqual(logging_resource, metrics_resource) + self.assertEqual(tracing_resource, metrics_resource) + self.assertEqual(tracing_resource.attributes["custom.key.1"], "pass-in-value-1") + self.assertEqual(tracing_resource.attributes["custom.key.2"], "pass-in-value-2") + class TestMetricsInit(TestCase): def setUp(self): From ecf6f377c7be3cd6a5e109abda8d474471746449 Mon Sep 17 00:00:00 2001 From: jerevoss Date: Thu, 23 May 2024 14:14:16 -0700 Subject: [PATCH 10/19] lint --- .../sdk/_configuration/__init__.py | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py index af8e7f5ff2e..8e18b97aa3e 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py @@ -50,10 +50,7 @@ MetricReader, PeriodicExportingMetricReader, ) -from opentelemetry.sdk.resources import ( - Attributes, - Resource -) +from opentelemetry.sdk.resources import Attributes, Resource from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor, SpanExporter from opentelemetry.sdk.trace.id_generator import IdGenerator @@ -358,15 +355,15 @@ def _import_id_generator(id_generator_name: str) -> IdGenerator: def _initialize_components( - auto_instrumentation_version: Optional[str] = None, - span_exporter_names: Optional[List[str]] = None, - metric_exporter_names: Optional[List[str]] = None, - log_exporter_names: Optional[List[str]] = None, - sampler: Optional[Sampler] = None, - resource_attributes: Optional[Attributes] = None, - id_generator: IdGenerator = None, - logging_enabled: Optional[bool] = None, - ): + auto_instrumentation_version: Optional[str] = None, + span_exporter_names: Optional[List[str]] = None, + metric_exporter_names: Optional[List[str]] = None, + log_exporter_names: Optional[List[str]] = None, + sampler: Optional[Sampler] = None, + resource_attributes: Optional[Attributes] = None, + id_generator: IdGenerator = None, + logging_enabled: Optional[bool] = None, +): if span_exporter_names is None: span_exporter_names = list() if metric_exporter_names is None: @@ -388,9 +385,9 @@ def _initialize_components( resource_attributes = {} # populate version if using auto-instrumentation if auto_instrumentation_version: - resource_attributes[ - ResourceAttributes.TELEMETRY_AUTO_VERSION - ] = auto_instrumentation_version + resource_attributes[ResourceAttributes.TELEMETRY_AUTO_VERSION] = ( + auto_instrumentation_version + ) # if env var OTEL_RESOURCE_ATTRIBUTES is given, it will read the service_name # from the env variable else defaults to "unknown_service" resource = Resource.create(resource_attributes) @@ -404,9 +401,14 @@ def _initialize_components( _init_metrics(metric_exporters, resource) # This could also be paramaterized if logging_enabled is None: - logging_enabled = os.getenv( - _OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED, "false" - ).strip().lower() == "true" + logging_enabled = ( + os.getenv( + _OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED, "false" + ) + .strip() + .lower() + == "true" + ) # Could be string or bool if logging_enabled: _init_logging(log_exporters, resource) From 45e0007728f5b31a7af0c76544242812271200c8 Mon Sep 17 00:00:00 2001 From: jerevoss Date: Thu, 23 May 2024 14:21:26 -0700 Subject: [PATCH 11/19] All tests pass --- opentelemetry-sdk/tests/test_configurator.py | 68 +++++++++----------- 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/opentelemetry-sdk/tests/test_configurator.py b/opentelemetry-sdk/tests/test_configurator.py index b1867a7b7bb..36929895bcd 100644 --- a/opentelemetry-sdk/tests/test_configurator.py +++ b/opentelemetry-sdk/tests/test_configurator.py @@ -18,7 +18,7 @@ from os import environ from typing import Dict, Iterable, Optional, Sequence from unittest import TestCase -from unittest.mock import Mock, patch +from unittest.mock import Mock, patch, ANY from pytest import raises @@ -708,13 +708,14 @@ def test_initialize_components_resource( "OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED": "False", }, ) + @patch("opentelemetry.sdk._configuration.Resource") @patch("opentelemetry.sdk._configuration._import_exporters") @patch("opentelemetry.sdk._configuration._get_exporter_names") @patch("opentelemetry.sdk._configuration._init_tracing") @patch("opentelemetry.sdk._configuration._init_logging") @patch("opentelemetry.sdk._configuration._init_metrics") def test_initialize_components_kwargs( - self, metrics_mock, logging_mock, tracing_mock, exporter_names_mock, import_exporters_mock + self, metrics_mock, logging_mock, tracing_mock, exporter_names_mock, import_exporters_mock, resource_mock ): exporter_names_mock.return_value = ["env_var_exporter_1", "env_var_exporter_2"] import_exporters_mock.return_value = ( @@ -722,8 +723,7 @@ def test_initialize_components_kwargs( "TEST_METRICS_EXPORTERS_DICT", "TEST_LOG_EXPORTERS_DICT", ) - # custom_id_generator = CustomIdGenerator() - # sampler = Sampler() + resource_mock.create.return_value = "TEST_RESOURCE" kwargs = { "auto_instrumentation_version": "auto-version", "span_exporter_names": ["custom_span_exporter"], @@ -744,37 +744,28 @@ def test_initialize_components_kwargs( ["custom_metric_exporter", "env_var_exporter_1", "env_var_exporter_2"], ["custom_log_exporter", "env_var_exporter_1", "env_var_exporter_2"] ) - # tracing_mock.assert_called_once_with( - # exporters="TEST_SPAN_EXPORTERS_DICT", - # id_generator="TEST_GENERATOR", - # sampler="TEST_SAMPLER," - # resource=resource, - # ) - # metrics_mock.assert_called_once_with( - # "TEST_METRICS_EXPORTERS_DICT", - # resource, - # ) - # logging_mock.assert_called_once_with( - # "TEST_LOG_EXPORTERS_DICT", - # resource, - # ) - - self.assertEqual(logging_mock.call_count, 1) - self.assertEqual(tracing_mock.call_count, 1) - self.assertEqual(metrics_mock.call_count, 1) - - _, args, _ = logging_mock.mock_calls[0] - logging_resource = args[1] - print(logging_resource.attributes) - _, _, kwargs = tracing_mock.mock_calls[0] - tracing_resource = kwargs["resource"] - _, args, _ = metrics_mock.mock_calls[0] - metrics_resource = args[1] - self.assertEqual(logging_resource, tracing_resource) - self.assertEqual(logging_resource, metrics_resource) - self.assertEqual(tracing_resource, metrics_resource) - self.assertEqual(tracing_resource.attributes["custom.key.1"], "pass-in-value-1") - self.assertEqual(tracing_resource.attributes["custom.key.2"], "pass-in-value-2") + resource_mock.create.assert_called_once_with( + { + "telemetry.auto.version": "auto-version", + "custom.key.1": "pass-in-value-1", + "custom.key.2": "pass-in-value-2", + } + ) + # Resource is checked separates + tracing_mock.assert_called_once_with( + exporters="TEST_SPAN_EXPORTERS_DICT", + id_generator="TEST_GENERATOR", + sampler="TEST_SAMPLER", + resource="TEST_RESOURCE", + ) + metrics_mock.assert_called_once_with( + "TEST_METRICS_EXPORTERS_DICT", + "TEST_RESOURCE", + ) + logging_mock.assert_called_once_with( + "TEST_LOG_EXPORTERS_DICT", + "TEST_RESOURCE", + ) class TestMetricsInit(TestCase): @@ -995,6 +986,7 @@ def test__import_config_components_missing_component( "Requested component 'a' not found in entry point 'name'", ) + class TestConfigurator(TestCase): class CustomConfigurator(_OTelSDKConfigurator): def _configure(self, **kwargs): @@ -1004,11 +996,11 @@ def _configure(self, **kwargs): @patch("opentelemetry.sdk._configuration._initialize_components") def test_custom_configurator(self, mock_init_comp): custom_configurator = TestConfigurator.CustomConfigurator() - custom_configurator._configure(auto_instrumentation_version="TEST_VERSION2") + custom_configurator._configure( + auto_instrumentation_version="TEST_VERSION2" + ) kwargs = { "auto_instrumentation_version": "TEST_VERSION2", "sampler": "TEST_SAMPLER", } mock_init_comp.assert_called_once_with(**kwargs) - - From b81f7b93996bab2b0454d0976f11c51f5ae6ad16 Mon Sep 17 00:00:00 2001 From: jerevoss Date: Thu, 23 May 2024 14:28:16 -0700 Subject: [PATCH 12/19] lint --- .../src/opentelemetry/sdk/_configuration/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py index 8e18b97aa3e..c953c5f2f2b 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py @@ -399,7 +399,6 @@ def _initialize_components( resource=resource, ) _init_metrics(metric_exporters, resource) - # This could also be paramaterized if logging_enabled is None: logging_enabled = ( os.getenv( From 5dad31d8706cf82383cc36fe2302bbe337e3ca51 Mon Sep 17 00:00:00 2001 From: jerevoss Date: Thu, 23 May 2024 14:30:45 -0700 Subject: [PATCH 13/19] lint --- .../src/opentelemetry/sdk/_configuration/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py index c953c5f2f2b..1e651371be0 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py @@ -408,7 +408,6 @@ def _initialize_components( .lower() == "true" ) - # Could be string or bool if logging_enabled: _init_logging(log_exporters, resource) From 40ea6ad07b86910e2ab66d6cff119096f1582de2 Mon Sep 17 00:00:00 2001 From: jerevoss Date: Thu, 23 May 2024 16:02:44 -0700 Subject: [PATCH 14/19] lint --- opentelemetry-sdk/tests/test_configurator.py | 31 ++++++++++++++++---- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/opentelemetry-sdk/tests/test_configurator.py b/opentelemetry-sdk/tests/test_configurator.py index 36929895bcd..28dac81c64c 100644 --- a/opentelemetry-sdk/tests/test_configurator.py +++ b/opentelemetry-sdk/tests/test_configurator.py @@ -715,9 +715,18 @@ def test_initialize_components_resource( @patch("opentelemetry.sdk._configuration._init_logging") @patch("opentelemetry.sdk._configuration._init_metrics") def test_initialize_components_kwargs( - self, metrics_mock, logging_mock, tracing_mock, exporter_names_mock, import_exporters_mock, resource_mock + self, + metrics_mock, + logging_mock, + tracing_mock, + exporter_names_mock, + import_exporters_mock, + resource_mock, ): - exporter_names_mock.return_value = ["env_var_exporter_1", "env_var_exporter_2"] + exporter_names_mock.return_value = [ + "env_var_exporter_1", + "env_var_exporter_2", + ] import_exporters_mock.return_value = ( "TEST_SPAN_EXPORTERS_DICT", "TEST_METRICS_EXPORTERS_DICT", @@ -740,9 +749,21 @@ def test_initialize_components_kwargs( _initialize_components(**kwargs) import_exporters_mock.assert_called_once_with( - ["custom_span_exporter", "env_var_exporter_1", "env_var_exporter_2"], - ["custom_metric_exporter", "env_var_exporter_1", "env_var_exporter_2"], - ["custom_log_exporter", "env_var_exporter_1", "env_var_exporter_2"] + [ + "custom_span_exporter", + "env_var_exporter_1", + "env_var_exporter_2", + ], + [ + "custom_metric_exporter", + "env_var_exporter_1", + "env_var_exporter_2", + ], + [ + "custom_log_exporter", + "env_var_exporter_1", + "env_var_exporter_2", + ], ) resource_mock.create.assert_called_once_with( { From 0e4194e0fa450e271cf7255ab127a406345b4c14 Mon Sep 17 00:00:00 2001 From: jerevoss Date: Thu, 23 May 2024 16:03:14 -0700 Subject: [PATCH 15/19] spelling --- .codespellrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.codespellrc b/.codespellrc index b81e62f640c..4da0add810b 100644 --- a/.codespellrc +++ b/.codespellrc @@ -1,4 +1,4 @@ [codespell] # skipping auto generated folders skip = ./.tox,./.mypy_cache,./docs/_build,./target,*/LICENSE,./venv,.git,./opentelemetry-semantic-conventions -ignore-words-list = ans,ue,ot,hist,ro +ignore-words-list = ans,assertIn,ue,ot,hist,ro, From d53ba6ff9511600995d70a4ce83ffe600f28730c Mon Sep 17 00:00:00 2001 From: jerevoss Date: Thu, 23 May 2024 16:13:42 -0700 Subject: [PATCH 16/19] lint --- opentelemetry-sdk/tests/test_configurator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-sdk/tests/test_configurator.py b/opentelemetry-sdk/tests/test_configurator.py index 28dac81c64c..fc743fa1af9 100644 --- a/opentelemetry-sdk/tests/test_configurator.py +++ b/opentelemetry-sdk/tests/test_configurator.py @@ -18,7 +18,7 @@ from os import environ from typing import Dict, Iterable, Optional, Sequence from unittest import TestCase -from unittest.mock import Mock, patch, ANY +from unittest.mock import Mock, patch from pytest import raises From 61d341e8dbfd3752f00d7a2c6edc43e98ad5cdae Mon Sep 17 00:00:00 2001 From: jerevoss Date: Thu, 23 May 2024 16:25:05 -0700 Subject: [PATCH 17/19] lint --- .../src/opentelemetry/sdk/_configuration/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py index 1e651371be0..86301306bc0 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py @@ -365,11 +365,11 @@ def _initialize_components( logging_enabled: Optional[bool] = None, ): if span_exporter_names is None: - span_exporter_names = list() + span_exporter_names = [] if metric_exporter_names is None: - metric_exporter_names = list() + metric_exporter_names = [] if log_exporter_names is None: - log_exporter_names = list() + log_exporter_names = [] span_exporters, metric_exporters, log_exporters = _import_exporters( span_exporter_names + _get_exporter_names("traces"), metric_exporter_names + _get_exporter_names("metrics"), From f19d261bc7d370f962a861b18ef53e1396dd1535 Mon Sep 17 00:00:00 2001 From: jerevoss Date: Tue, 28 May 2024 13:39:38 -0700 Subject: [PATCH 18/19] Feedback --- .codespellrc | 2 +- CHANGELOG.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.codespellrc b/.codespellrc index 4da0add810b..b81e62f640c 100644 --- a/.codespellrc +++ b/.codespellrc @@ -1,4 +1,4 @@ [codespell] # skipping auto generated folders skip = ./.tox,./.mypy_cache,./docs/_build,./target,*/LICENSE,./venv,.git,./opentelemetry-semantic-conventions -ignore-words-list = ans,assertIn,ue,ot,hist,ro, +ignore-words-list = ans,ue,ot,hist,ro diff --git a/CHANGELOG.md b/CHANGELOG.md index a9247d92184..20c2b8dc9e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,7 +54,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - unit annotations (enclosed in curly braces like `{requests}`) are stripped away - units with slash are converted e.g. `m/s` -> `meters_per_second`. - The exporter's API is not changed -- Add parameters for Distros and configurators to configure autoinstrumentation +- Add parameters for Distros and configurators to configure autoinstrumentation in addition to existing environment variables. ([#3864] (https://github.com/open-telemetry/opentelemetry-python/pull/3864)) ## Version 1.24.0/0.45b0 (2024-03-28) From a3f0475cf45d533b16c1558722ac5792c4df1481 Mon Sep 17 00:00:00 2001 From: jerevoss Date: Thu, 30 May 2024 14:50:00 -0700 Subject: [PATCH 19/19] Change span_exporter_names to trace_exporter_names --- .../src/opentelemetry/sdk/_configuration/__init__.py | 8 ++++---- opentelemetry-sdk/tests/test_configurator.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py index 86301306bc0..97de4fb1001 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py @@ -356,7 +356,7 @@ def _import_id_generator(id_generator_name: str) -> IdGenerator: def _initialize_components( auto_instrumentation_version: Optional[str] = None, - span_exporter_names: Optional[List[str]] = None, + trace_exporter_names: Optional[List[str]] = None, metric_exporter_names: Optional[List[str]] = None, log_exporter_names: Optional[List[str]] = None, sampler: Optional[Sampler] = None, @@ -364,14 +364,14 @@ def _initialize_components( id_generator: IdGenerator = None, logging_enabled: Optional[bool] = None, ): - if span_exporter_names is None: - span_exporter_names = [] + if trace_exporter_names is None: + trace_exporter_names = [] if metric_exporter_names is None: metric_exporter_names = [] if log_exporter_names is None: log_exporter_names = [] span_exporters, metric_exporters, log_exporters = _import_exporters( - span_exporter_names + _get_exporter_names("traces"), + trace_exporter_names + _get_exporter_names("traces"), metric_exporter_names + _get_exporter_names("metrics"), log_exporter_names + _get_exporter_names("logs"), ) diff --git a/opentelemetry-sdk/tests/test_configurator.py b/opentelemetry-sdk/tests/test_configurator.py index fc743fa1af9..403b1eff005 100644 --- a/opentelemetry-sdk/tests/test_configurator.py +++ b/opentelemetry-sdk/tests/test_configurator.py @@ -735,7 +735,7 @@ def test_initialize_components_kwargs( resource_mock.create.return_value = "TEST_RESOURCE" kwargs = { "auto_instrumentation_version": "auto-version", - "span_exporter_names": ["custom_span_exporter"], + "trace_exporter_names": ["custom_span_exporter"], "metric_exporter_names": ["custom_metric_exporter"], "log_exporter_names": ["custom_log_exporter"], "sampler": "TEST_SAMPLER",