diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md b/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md index d582b5831159..e5a5fc06c000 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md @@ -9,6 +9,9 @@ ### Breaking Changes +- Rename local storage configuration, change default path + ([#26891](https://github.com/Azure/azure-sdk-for-python/pull/26891)) + ### Bugs Fixed - Fixed sampleRate field in ApplicationInsightsSampler, changed attribute to `_MS.sampleRate` diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/README.md b/sdk/monitor/azure-monitor-opentelemetry-exporter/README.md index 483e08ca040b..aa8d2e16c2ae 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/README.md +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/README.md @@ -133,8 +133,8 @@ For more information about these resources, see [What is Azure Monitor?][product All configuration options can be passed through the constructors of exporters through `kwargs`. Below is a list of configurable options. `connection_string`: The connection string used for your Application Insights resource. -`enable_local_storage`: Boolean value to determine whether to store failed telemetry records for retry. Defaults to `True`. -`storage_path`: Storage path in which to store retry files. Defaults to `/opentelemetry-python-`. +`disable_offline_storage`: Boolean value to determine whether to disable storing failed telemetry records for retry. Defaults to `False`. +`storage_directory`: Storage directory in which to store retry files. Defaults to `/Microsoft/AzureMonitor/opentelemetry-python-`. ## Examples diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/export/_base.py b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/export/_base.py index d1fa6dff0d73..142c187a8c46 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/export/_base.py +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/export/_base.py @@ -39,6 +39,7 @@ logger = logging.getLogger(__name__) +_AZURE_TEMPDIR_PREFIX = "Microsoft/AzureMonitor" _TEMPDIR_PREFIX = "opentelemetry-python-" _SERVICE_API_LATEST = "2020-09-15_Preview" @@ -59,25 +60,25 @@ def __init__(self, **kwargs: Any) -> None: :keyword str api_version: The service API version used. Defaults to latest. :keyword str connection_string: The connection string used for your Application Insights resource. - :keyword bool enable_local_storage: Determines whether to store failed telemetry records for retry. Defaults to `True`. - :keyword str storage_path: Storage path in which to store retry files. Defaults to `/opentelemetry-python-`. + :keyword bool disable_offline_storage: Determines whether to disable storing failed telemetry records for retry. Defaults to `False`. + :keyword str storage_directory: Storage path in which to store retry files. Defaults to `/opentelemetry-python-`. :rtype: None """ parsed_connection_string = ConnectionStringParser(kwargs.get('connection_string')) self._api_version = kwargs.get('api_version') or _SERVICE_API_LATEST self._consecutive_redirects = 0 # To prevent circular redirects - self._enable_local_storage = kwargs.get('enable_local_storage', True) + self._disable_offline_storage = kwargs.get('disable_offline_storage', False) self._endpoint = parsed_connection_string.endpoint self._instrumentation_key = parsed_connection_string.instrumentation_key self._storage_maintenance_period = kwargs.get('storage_maintenance_period', 60) # Maintenance interval in seconds. self._storage_max_size = kwargs.get('storage_max_size', 50 * 1024 * 1024) # Maximum size in bytes (default 50MiB) self._storage_min_retry_interval = kwargs.get('storage_min_retry_interval', 60) # minimum retry interval in seconds temp_suffix = self._instrumentation_key or "" - default_storage_path = os.path.join( - tempfile.gettempdir(), _TEMPDIR_PREFIX + temp_suffix + default_storage_directory = os.path.join( + tempfile.gettempdir(), _AZURE_TEMPDIR_PREFIX, _TEMPDIR_PREFIX + temp_suffix ) - self._storage_path = kwargs.get('storage_path', default_storage_path) # Storage path in which to store retry files. + self._storage_directory = kwargs.get('storage_directory', default_storage_directory) # Storage path in which to store retry files. self._storage_retention_period = kwargs.get('storage_retention_period', 7 * 24 * 60 * 60) # Retention period in seconds self._timeout = kwargs.get('timeout', 10.0) # networking timeout in seconds @@ -101,9 +102,9 @@ def __init__(self, **kwargs: Any) -> None: self.client = AzureMonitorClient( host=self._endpoint, connection_timeout=self._timeout, policies=policies, **kwargs) self.storage = None - if self._enable_local_storage: + if not self._disable_offline_storage: self.storage = LocalFileStorage( - path=self._storage_path, + path=self._storage_directory, max_size=self._storage_max_size, maintenance_period=self._storage_maintenance_period, retention_period=self._storage_retention_period, @@ -121,7 +122,7 @@ def _transmit_from_storage(self) -> None: # give a few more seconds for blob lease operation # to reduce the chance of race (for perf consideration) if blob.lease(self._timeout + 5): - envelopes = [TelemetryItem(**x) for x in blob.get()] + envelopes = [TelemetryItem.from_dict(x) for x in blob.get()] result = self._transmit(list(envelopes)) if result == ExportResult.FAILED_RETRYABLE: blob.lease(1) diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/samples/traces/README.md b/sdk/monitor/azure-monitor-opentelemetry-exporter/samples/traces/README.md index 45d8e39bc99f..cd4a982efc17 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/samples/traces/README.md +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/samples/traces/README.md @@ -114,7 +114,8 @@ $ python sample_requests.py * Update `APPLICATIONINSIGHTS_CONNECTION_STRING` environment variable -* Ensure you have a database named `Database` with a table named `test` +* Ensure you have a database named `test` with a table named `test_table`, make sure `test_table` has a field called `test_field` +* Supply your `user` and `password` for your database if needed * Run the sample ```sh diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/samples/traces/sample_psycopg2.py b/sdk/monitor/azure-monitor-opentelemetry-exporter/samples/traces/sample_psycopg2.py index 78ceeb89f115..d10a929e81ce 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/samples/traces/sample_psycopg2.py +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/samples/traces/sample_psycopg2.py @@ -30,9 +30,9 @@ ) trace.get_tracer_provider().add_span_processor(span_processor) -cnx = psycopg2.connect(database='Database') +cnx = psycopg2.connect(database='test', user="", password="") cursor = cnx.cursor() -cursor.execute("INSERT INTO test (testField) VALUES (123)") +cursor.execute("INSERT INTO test_tables (test_field) VALUES (123)") cursor.close() cnx.close() diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/test_base_exporter.py b/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/test_base_exporter.py index 863b8295597b..e53782a0585c 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/test_base_exporter.py +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/test_base_exporter.py @@ -84,7 +84,7 @@ def test_constructor(self): storage_maintenance_period=30, storage_max_size=1000, storage_min_retry_interval=100, - storage_path="test/path", + storage_directory="test/path", storage_retention_period=2000, ) self.assertEqual( @@ -102,15 +102,17 @@ def test_constructor(self): self.assertEqual(base._timeout, 10) self.assertEqual(base._api_version, "2021-02-10_Preview") self.assertEqual(base._storage_min_retry_interval, 100) - self.assertEqual(base._storage_path, "test/path") + self.assertEqual(base._storage_directory, "test/path") - def test_transmit_from_storage_success(self): + @mock.patch.object(TelemetryItem, "from_dict") + def test_transmit_from_storage_success(self, dict_patch): exporter = BaseExporter() exporter.storage = mock.Mock() blob_mock = mock.Mock() blob_mock.lease.return_value = True envelope_mock = {"name":"test","time":"time"} blob_mock.get.return_value = [envelope_mock] + dict_patch.return_value = {"name":"test","time":"time"} exporter.storage.gets.return_value = [blob_mock] with mock.patch.object(AzureMonitorClient, 'track') as post: post.return_value = TrackResponse( @@ -123,13 +125,15 @@ def test_transmit_from_storage_success(self): blob_mock.lease.assert_called_once() blob_mock.delete.assert_called_once() - def test_transmit_from_storage_store_again(self): + @mock.patch.object(TelemetryItem, "from_dict") + def test_transmit_from_storage_store_again(self, dict_patch): exporter = BaseExporter() exporter.storage = mock.Mock() blob_mock = mock.Mock() blob_mock.lease.return_value = True envelope_mock = {"name":"test","time":"time"} blob_mock.get.return_value = [envelope_mock] + dict_patch.return_value = {"name":"test","time":"time"} exporter.storage.gets.return_value = [blob_mock] with mock.patch("azure.monitor.opentelemetry.exporter.export._base._is_retryable_code"): with mock.patch.object(AzureMonitorClient, 'track', throw(HttpResponseError)):