diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/export/trace/_sampling.py b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/export/trace/_sampling.py index 130ede8e4125..e3378780b578 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/export/trace/_sampling.py +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/export/trace/_sampling.py @@ -95,5 +95,5 @@ def azure_monitor_opentelemetry_sampler_factory(sampler_argument): # pylint: di try: rate = float(sampler_argument) return ApplicationInsightsSampler(rate) - except ValueError: + except (ValueError, TypeError): return ApplicationInsightsSampler() diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/trace/test_sampling.py b/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/trace/test_sampling.py index 195cd9a438c2..d443c38f381c 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/trace/test_sampling.py +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/trace/test_sampling.py @@ -5,12 +5,18 @@ from azure.monitor.opentelemetry.exporter.export.trace._sampling import ( ApplicationInsightsSampler, + azure_monitor_opentelemetry_sampler_factory, ) # pylint: disable=protected-access class TestApplicationInsightsSampler(unittest.TestCase): def test_constructor(self): + sampler = ApplicationInsightsSampler() + self.assertEqual(sampler._ratio, 1.0) + self.assertEqual(sampler._sample_rate, 100) + + def test_constructor_ratio(self): sampler = ApplicationInsightsSampler(0.75) self.assertEqual(sampler._ratio, 0.75) self.assertEqual(sampler._sample_rate, 75) @@ -38,3 +44,15 @@ def test_should_sample_not_sampled(self, score_mock): result = sampler.should_sample(None, 0, "test") self.assertEqual(result.attributes["_MS.sampleRate"], 50) self.assertFalse(result.decision.is_sampled()) + + def test_sampler_factory(self): + sampler = azure_monitor_opentelemetry_sampler_factory("1.0") + self.assertEqual(sampler._ratio, 1.0) + + def test_sampler_factory_none(self): + sampler = azure_monitor_opentelemetry_sampler_factory(None) + self.assertEqual(sampler._ratio, 1.0) + + def test_sampler_factory_empty(self): + sampler = azure_monitor_opentelemetry_sampler_factory("") + self.assertEqual(sampler._ratio, 1.0) diff --git a/sdk/monitor/azure-monitor-opentelemetry/CHANGELOG.md b/sdk/monitor/azure-monitor-opentelemetry/CHANGELOG.md index 1643d6aaa7b6..7418f4e1b29f 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/CHANGELOG.md +++ b/sdk/monitor/azure-monitor-opentelemetry/CHANGELOG.md @@ -4,6 +4,9 @@ ### Features Added +- Enable sampling for attach + ([#35218](https://github.com/Azure/azure-sdk-for-python/pull/35218)) + ### Breaking Changes ### Bugs Fixed diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_autoinstrumentation/distro.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_autoinstrumentation/distro.py index 364c80df0cf8..23935eb87653 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_autoinstrumentation/distro.py +++ b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_autoinstrumentation/distro.py @@ -17,6 +17,7 @@ from opentelemetry.sdk.environment_variables import ( _OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED, OTEL_EXPERIMENTAL_RESOURCE_DETECTORS, + OTEL_TRACES_SAMPLER, ) from azure.core.settings import settings @@ -70,6 +71,9 @@ def _configure_auto_instrumentation() -> None: environ.setdefault( OTEL_LOGS_EXPORTER, "azure_monitor_opentelemetry_exporter" ) + environ.setdefault( + OTEL_TRACES_SAMPLER, "azure_monitor_opentelemetry_sampler" + ) environ.setdefault( _OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED, "true" ) diff --git a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_configure.py b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_configure.py index 4bd2b00c6766..d4745c3e8220 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_configure.py +++ b/sdk/monitor/azure-monitor-opentelemetry/azure/monitor/opentelemetry/_configure.py @@ -168,7 +168,7 @@ def _setup_instrumentations(configurations: Dict[str, ConfigurationValue]): continue try: # Check if dependent libraries/version are installed - conflict = get_dist_dependency_conflicts(entry_point.dist) + conflict = get_dist_dependency_conflicts(entry_point.dist) # type: ignore if conflict: _logger.debug( "Skipping instrumentation %s: %s", diff --git a/sdk/monitor/azure-monitor-opentelemetry/tests/autoinstrumentation/test_distro.py b/sdk/monitor/azure-monitor-opentelemetry/tests/autoinstrumentation/test_distro.py index 1c45d518a30a..c4a59d293109 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/tests/autoinstrumentation/test_distro.py +++ b/sdk/monitor/azure-monitor-opentelemetry/tests/autoinstrumentation/test_distro.py @@ -1,3 +1,4 @@ +from os import environ import warnings from unittest import TestCase from unittest.mock import patch @@ -13,6 +14,7 @@ class TestDistro(TestCase): + @patch.dict("os.environ", {}, clear=True) @patch("azure.monitor.opentelemetry._autoinstrumentation.distro._is_attach_enabled", return_value=True) @patch("azure.monitor.opentelemetry._autoinstrumentation.distro.settings") @patch( @@ -30,8 +32,56 @@ def test_configure(self, mock_diagnostics, azure_core_mock, attach_mock): self.assertEqual( azure_core_mock.tracing_implementation, OpenTelemetrySpan ) + self.assertEqual( + environ, + { + "OTEL_METRICS_EXPORTER": "azure_monitor_opentelemetry_exporter", + "OTEL_TRACES_EXPORTER": "azure_monitor_opentelemetry_exporter", + "OTEL_LOGS_EXPORTER": "azure_monitor_opentelemetry_exporter", + "OTEL_TRACES_SAMPLER": "azure_monitor_opentelemetry_sampler", + "OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED": "true", + "OTEL_EXPERIMENTAL_RESOURCE_DETECTORS": "azure_app_service", + } + ) + + @patch.dict("os.environ", { + "OTEL_METRICS_EXPORTER": "custom_metrics_exporter", + "OTEL_TRACES_EXPORTER": "custom_traces_exporter", + "OTEL_LOGS_EXPORTER": "custom_logs_exporter", + "OTEL_TRACES_SAMPLER": "custom_traces_sampler", + "OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED": "false", + "OTEL_EXPERIMENTAL_RESOURCE_DETECTORS": "custom_resource_detector", + }, clear=True) + @patch("azure.monitor.opentelemetry._autoinstrumentation.distro._is_attach_enabled", return_value=True) + @patch("azure.monitor.opentelemetry._autoinstrumentation.distro.settings") + @patch( + "azure.monitor.opentelemetry._autoinstrumentation.distro.AzureDiagnosticLogging" + ) + def test_configure_env_vars_set(self, mock_diagnostics, azure_core_mock, attach_mock): + distro = AzureMonitorDistro() + with warnings.catch_warnings(): + warnings.simplefilter("error") + distro.configure() + mock_diagnostics.info.assert_called_once_with( + "Azure Monitor OpenTelemetry Distro configured successfully.", + _ATTACH_SUCCESS_DISTRO + ) + self.assertEqual( + azure_core_mock.tracing_implementation, OpenTelemetrySpan + ) + self.assertEqual( + environ, + { + "OTEL_METRICS_EXPORTER": "custom_metrics_exporter", + "OTEL_TRACES_EXPORTER": "custom_traces_exporter", + "OTEL_LOGS_EXPORTER": "custom_logs_exporter", + "OTEL_TRACES_SAMPLER": "custom_traces_sampler", + "OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED": "false", + "OTEL_EXPERIMENTAL_RESOURCE_DETECTORS": "custom_resource_detector", + } + ) - @patch.dict("os.environ", {"OTEL_PYTHON_DISABLED_INSTRUMENTATIONS": " flask,azure_sdk , urllib3"}) + @patch.dict("os.environ", {"OTEL_PYTHON_DISABLED_INSTRUMENTATIONS": " flask,azure_sdk , urllib3"}, clear=True) @patch("azure.monitor.opentelemetry._autoinstrumentation.distro._is_attach_enabled", return_value=True) @patch("azure.monitor.opentelemetry._autoinstrumentation.distro.settings") @patch(