From 7c64d24a5429bd6766fd8c907e4a54da5a22ed92 Mon Sep 17 00:00:00 2001 From: Leighton Chen Date: Mon, 26 Feb 2024 15:08:32 -0800 Subject: [PATCH 1/6] ns --- .../CHANGELOG.md | 2 ++ .../opentelemetry/exporter/_constants.py | 1 + .../exporter/export/metrics/_exporter.py | 15 +++++++- .../exporter/statsbeat/_exporter.py | 3 ++ .../tests/metrics/test_metrics.py | 35 ++++++++++++++++++- 5 files changed, 54 insertions(+), 2 deletions(-) diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md b/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md index ef92eac283c5..b9d9068c4fda 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md @@ -10,6 +10,8 @@ ([#34141](https://github.com/Azure/azure-sdk-for-python/pull/34141)) - Add application.ver to part A fields ([#34401](https://github.com/Azure/azure-sdk-for-python/pull/34401)) +- Add `APPLICATIONINSIGHTS_METRIC_NAMESPACE_OPT_IN` + ([#34401](https://github.com/Azure/azure-sdk-for-python/pull/34401)) ### Breaking Changes diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_constants.py b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_constants.py index 8fffcb3e424f..e66fac012d9e 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_constants.py +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_constants.py @@ -9,6 +9,7 @@ _APPLICATIONINSIGHTS_STATSBEAT_DISABLED_ALL = "APPLICATIONINSIGHTS_STATSBEAT_DISABLED_ALL" _APPLICATIONINSIGHTS_OPENTELEMETRY_RESOURCE_METRIC_DISABLED = \ "APPLICATIONINSIGHTS_OPENTELEMETRY_RESOURCE_METRIC_DISABLED" +_APPLICATIONINSIGHTS_METRIC_NAMESPACE_OPT_IN = "APPLICATIONINSIGHTS_METRIC_NAMESPACE_OPT_IN" _WEBSITE_SITE_NAME = "WEBSITE_SITE_NAME" _WEBSITE_HOME_STAMPNAME = "WEBSITE_HOME_STAMPNAME" _WEBSITE_HOSTNAME = "WEBSITE_HOSTNAME" diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/export/metrics/_exporter.py b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/export/metrics/_exporter.py index 859b85e48357..6902f5a4830c 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/export/metrics/_exporter.py +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/export/metrics/_exporter.py @@ -1,6 +1,7 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. import logging +import os from typing import Dict, Optional, Union, Any @@ -23,8 +24,10 @@ NumberDataPoint, ) from opentelemetry.sdk.resources import Resource +from opentelemetry.sdk.util.instrumentation import InstrumentationScope from azure.monitor.opentelemetry.exporter._constants import ( + _APPLICATIONINSIGHTS_METRIC_NAMESPACE_OPT_IN, _AUTOCOLLECTED_INSTRUMENT_NAMES, _METRIC_ENVELOPE_NAME, ) @@ -94,6 +97,7 @@ def export( point, metric.name, resource_metric.resource, + scope_metric.scope, ) if envelope is not None: envelopes.append(envelope) @@ -133,8 +137,9 @@ def _point_to_envelope( point: DataPointT, name: str, resource: Optional[Resource] = None, + scope: Optional[InstrumentationScope] = None, ) -> Optional[TelemetryItem]: - envelope = _convert_point_to_envelope(point, name, resource) + envelope = _convert_point_to_envelope(point, name, resource, scope) if name in _AUTOCOLLECTED_INSTRUMENT_NAMES: envelope = _handle_std_metric_envelope(envelope, name, point.attributes) # type: ignore if envelope is not None: @@ -168,10 +173,15 @@ def _convert_point_to_envelope( point: DataPointT, name: str, resource: Optional[Resource] = None, + scope: Optional[InstrumentationScope] = None ) -> TelemetryItem: envelope = _utils._create_telemetry_item(point.time_unix_nano) envelope.name = _METRIC_ENVELOPE_NAME envelope.tags.update(_utils._populate_part_a_fields(resource)) # type: ignore + namespace = None + if scope is not None and _is_metric_namespace_opted_in(): + namespace = scope.name + namespace = str(namespace)[:256] value: Union[int, float] = 0 count = 1 min_ = None @@ -191,6 +201,7 @@ def _convert_point_to_envelope( data_point = MetricDataPoint( name=str(name)[:1024], + namespace=namespace, value=value, count=count, min=min_, @@ -266,6 +277,8 @@ def _handle_std_metric_envelope( def _is_status_code_success(status_code: Optional[str], threshold: int) -> bool: return status_code is not None and int(status_code) < threshold +def _is_metric_namespace_opted_in() -> bool: + return os.environ.get(_APPLICATIONINSIGHTS_METRIC_NAMESPACE_OPT_IN, "False").lower() == "true" def _get_metric_export_result(result: ExportResult) -> MetricExportResult: if result == ExportResult.SUCCESS: diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/statsbeat/_exporter.py b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/statsbeat/_exporter.py index bde8c807389d..e711731f9ca6 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/statsbeat/_exporter.py +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/statsbeat/_exporter.py @@ -3,6 +3,7 @@ from typing import Optional from opentelemetry.sdk.metrics.export import DataPointT from opentelemetry.sdk.resources import Resource +from opentelemetry.sdk.util.instrumentation import InstrumentationScope from azure.monitor.opentelemetry.exporter._generated.models import TelemetryItem from azure.monitor.opentelemetry.exporter import AzureMonitorMetricExporter @@ -17,6 +18,7 @@ def _point_to_envelope( point: DataPointT, name: str, resource: Optional[Resource] = None, + scope: Optional[InstrumentationScope] = None ) -> Optional[TelemetryItem]: # map statsbeat name from OpenTelemetry name name = _STATSBEAT_METRIC_NAME_MAPPINGS[name] @@ -24,4 +26,5 @@ def _point_to_envelope( point, name, resource, + None, ) diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/metrics/test_metrics.py b/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/metrics/test_metrics.py index 4869f9d300da..024c358e6b16 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/metrics/test_metrics.py +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/tests/metrics/test_metrics.py @@ -213,6 +213,7 @@ def test_point_to_envelope_partA_default(self): def test_point_to_envelope_number(self): exporter = self._exporter resource = Resource.create(attributes={"asd":"test_resource"}) + scope = InstrumentationScope("test_scope") point=NumberDataPoint( attributes={ "test": "attribute", @@ -221,7 +222,7 @@ def test_point_to_envelope_number(self): time_unix_nano=1646865018558419457, value=10, ) - envelope = exporter._point_to_envelope(point, "test name", resource) + envelope = exporter._point_to_envelope(point, "test name", resource, scope) self.assertEqual(envelope.instrumentation_key, exporter._instrumentation_key) self.assertEqual(envelope.name, 'Microsoft.ApplicationInsights.Metric') self.assertEqual(envelope.time, ns_to_iso_str(point.time_unix_nano)) @@ -230,6 +231,7 @@ def test_point_to_envelope_number(self): self.assertEqual(envelope.data.base_data.properties['test'], 'attribute') self.assertEqual(len(envelope.data.base_data.metrics), 1) self.assertEqual(envelope.data.base_data.metrics[0].name, "test name") + self.assertEqual(envelope.data.base_data.metrics[0].namespace, None) self.assertEqual(envelope.data.base_data.metrics[0].value, 10) self.assertEqual(envelope.data.base_data.metrics[0].count, 1) @@ -261,6 +263,37 @@ def test_point_to_envelope_histogram(self): self.assertEqual(envelope.data.base_data.metrics[0].value, 31) self.assertEqual(envelope.data.base_data.metrics[0].count, 7) + @mock.patch.dict( + "os.environ", + { + "APPLICATIONINSIGHTS_METRIC_NAMESPACE_OPT_IN": "True", + }, + ) + def test_point_to_envelope_metric_namespace(self): + exporter = self._exporter + resource = Resource.create(attributes={"asd":"test_resource"}) + scope = InstrumentationScope("test_scope") + point=NumberDataPoint( + attributes={ + "test": "attribute", + }, + start_time_unix_nano=1646865018558419456, + time_unix_nano=1646865018558419457, + value=10, + ) + envelope = exporter._point_to_envelope(point, "test name", resource, scope) + self.assertEqual(envelope.instrumentation_key, exporter._instrumentation_key) + self.assertEqual(envelope.name, 'Microsoft.ApplicationInsights.Metric') + self.assertEqual(envelope.time, ns_to_iso_str(point.time_unix_nano)) + self.assertEqual(envelope.data.base_type, 'MetricData') + self.assertEqual(len(envelope.data.base_data.properties), 1) + self.assertEqual(envelope.data.base_data.properties['test'], 'attribute') + self.assertEqual(len(envelope.data.base_data.metrics), 1) + self.assertEqual(envelope.data.base_data.metrics[0].name, "test name") + self.assertEqual(envelope.data.base_data.metrics[0].namespace, "test_scope") + self.assertEqual(envelope.data.base_data.metrics[0].value, 10) + self.assertEqual(envelope.data.base_data.metrics[0].count, 1) + def test_point_to_envelope_std_metric_client_duration(self): exporter = self._exporter resource = Resource( From 86ea4685d096445c0e94806dc460e19a904b7554 Mon Sep 17 00:00:00 2001 From: Leighton Chen Date: Mon, 26 Feb 2024 15:13:00 -0800 Subject: [PATCH 2/6] Update CHANGELOG.md --- sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md b/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md index b9d9068c4fda..0088906b327e 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md @@ -11,7 +11,7 @@ - Add application.ver to part A fields ([#34401](https://github.com/Azure/azure-sdk-for-python/pull/34401)) - Add `APPLICATIONINSIGHTS_METRIC_NAMESPACE_OPT_IN` - ([#34401](https://github.com/Azure/azure-sdk-for-python/pull/34401)) + ([#34463](https://github.com/Azure/azure-sdk-for-python/pull/34463)) ### Breaking Changes From b1cd487de23dff83dca5e256ae1c978995f71ab2 Mon Sep 17 00:00:00 2001 From: Leighton Chen Date: Tue, 27 Feb 2024 10:49:58 -0800 Subject: [PATCH 3/6] Update _utils.py --- .../azure/monitor/opentelemetry/exporter/_utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_utils.py b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_utils.py index a1510d736290..8d1908dfed36 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_utils.py +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_utils.py @@ -87,6 +87,7 @@ def _get_sdk_version_prefix(): return sdk_version_prefix + def _get_sdk_version(): return "{}py{}:otel{}:ext{}".format( _get_sdk_version_prefix(), platform.python_version(), opentelemetry_version, ext_version From 5fd88fb496c48d777901f283f31478fdcd2ccd64 Mon Sep 17 00:00:00 2001 From: Leighton Chen Date: Tue, 27 Feb 2024 10:50:05 -0800 Subject: [PATCH 4/6] Update _utils.py --- .../azure/monitor/opentelemetry/exporter/_utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_utils.py b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_utils.py index 8d1908dfed36..a1510d736290 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_utils.py +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/_utils.py @@ -87,7 +87,6 @@ def _get_sdk_version_prefix(): return sdk_version_prefix - def _get_sdk_version(): return "{}py{}:otel{}:ext{}".format( _get_sdk_version_prefix(), platform.python_version(), opentelemetry_version, ext_version From 0fcf31c7082f88d598dac025f7bd820d70d06ab3 Mon Sep 17 00:00:00 2001 From: Leighton Chen Date: Tue, 27 Feb 2024 11:05:16 -0800 Subject: [PATCH 5/6] readme --- sdk/monitor/azure-monitor-opentelemetry-exporter/README.md | 2 +- sdk/monitor/azure-monitor-opentelemetry/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/README.md b/sdk/monitor/azure-monitor-opentelemetry-exporter/README.md index b1a298ae01d9..32ca0fd73d35 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/README.md +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/README.md @@ -1,6 +1,6 @@ # Microsoft OpenTelemetry exporter for Azure Monitor -The exporter for Azure Monitor allows you to export data utilizing the OpenTelemetry SDK and send telemetry data to Azure Monitor for applications written in Python. +The exporter for Azure Monitor allows Python applications to export data from the OpenTelemetry SDK to Azure Monitor. The exporter is intended for users who require advanced configuration or has more complicated telemetry needs that require all of distributed tracing, logging and metrics. If you have simpler configuration requirements, we recommend using the [Azure Monitor OpenTelemetry Distro](https://learn.microsoft.com/azure/azure-monitor/app/opentelemetry-enable?tabs=python) instead for a simpler one-line setup. [Source code](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/monitor/azure-monitor-opentelemetry-exporter) | [Package (PyPi)][pypi] | [API reference documentation][api_docs] | [Product documentation][product_docs] | [Samples][exporter_samples] | [Changelog](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md) diff --git a/sdk/monitor/azure-monitor-opentelemetry/README.md b/sdk/monitor/azure-monitor-opentelemetry/README.md index f84ed52b9f86..63d311025c00 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/README.md +++ b/sdk/monitor/azure-monitor-opentelemetry/README.md @@ -1,6 +1,6 @@ # Azure Monitor Opentelemetry Distro client library for Python -The Azure Monitor Distro of [Opentelemetry Python][ot_sdk_python] provides multiple installable components available for an Opentelemetry Azure Monitor monitoring solution. It allows you to instrument your Python applications to capture and report telemetry to Azure Monitor via the Azure monitor exporters. +The Azure Monitor Distro of [Opentelemetry Python][ot_sdk_python] is a "one-stop-shop" telemetry solution, requiring only one line of code to instrument your application. The distro captures telemetry via [OpenTelemetry instrumentations][azure_monitor_opentelemetry_exporters] and reports telemetry to Azure Monitor via the [Azure Monitor exporters][azure_monitor_opentelemetry_exporters]. This distro automatically installs the following libraries: From 41dc7b26bb719700d552c9d696c387fd7933f349 Mon Sep 17 00:00:00 2001 From: Leighton Chen Date: Tue, 27 Feb 2024 11:07:17 -0800 Subject: [PATCH 6/6] review --- sdk/monitor/azure-monitor-opentelemetry-exporter/README.md | 2 +- .../monitor/opentelemetry/exporter/export/metrics/_exporter.py | 3 +-- sdk/monitor/azure-monitor-opentelemetry/README.md | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/README.md b/sdk/monitor/azure-monitor-opentelemetry-exporter/README.md index 32ca0fd73d35..b1a298ae01d9 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/README.md +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/README.md @@ -1,6 +1,6 @@ # Microsoft OpenTelemetry exporter for Azure Monitor -The exporter for Azure Monitor allows Python applications to export data from the OpenTelemetry SDK to Azure Monitor. The exporter is intended for users who require advanced configuration or has more complicated telemetry needs that require all of distributed tracing, logging and metrics. If you have simpler configuration requirements, we recommend using the [Azure Monitor OpenTelemetry Distro](https://learn.microsoft.com/azure/azure-monitor/app/opentelemetry-enable?tabs=python) instead for a simpler one-line setup. +The exporter for Azure Monitor allows you to export data utilizing the OpenTelemetry SDK and send telemetry data to Azure Monitor for applications written in Python. [Source code](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/monitor/azure-monitor-opentelemetry-exporter) | [Package (PyPi)][pypi] | [API reference documentation][api_docs] | [Product documentation][product_docs] | [Samples][exporter_samples] | [Changelog](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/monitor/azure-monitor-opentelemetry-exporter/CHANGELOG.md) diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/export/metrics/_exporter.py b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/export/metrics/_exporter.py index 6902f5a4830c..0485a20fb49a 100644 --- a/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/export/metrics/_exporter.py +++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/azure/monitor/opentelemetry/exporter/export/metrics/_exporter.py @@ -180,8 +180,7 @@ def _convert_point_to_envelope( envelope.tags.update(_utils._populate_part_a_fields(resource)) # type: ignore namespace = None if scope is not None and _is_metric_namespace_opted_in(): - namespace = scope.name - namespace = str(namespace)[:256] + namespace = str(scope.name)[:256] value: Union[int, float] = 0 count = 1 min_ = None diff --git a/sdk/monitor/azure-monitor-opentelemetry/README.md b/sdk/monitor/azure-monitor-opentelemetry/README.md index 63d311025c00..f84ed52b9f86 100644 --- a/sdk/monitor/azure-monitor-opentelemetry/README.md +++ b/sdk/monitor/azure-monitor-opentelemetry/README.md @@ -1,6 +1,6 @@ # Azure Monitor Opentelemetry Distro client library for Python -The Azure Monitor Distro of [Opentelemetry Python][ot_sdk_python] is a "one-stop-shop" telemetry solution, requiring only one line of code to instrument your application. The distro captures telemetry via [OpenTelemetry instrumentations][azure_monitor_opentelemetry_exporters] and reports telemetry to Azure Monitor via the [Azure Monitor exporters][azure_monitor_opentelemetry_exporters]. +The Azure Monitor Distro of [Opentelemetry Python][ot_sdk_python] provides multiple installable components available for an Opentelemetry Azure Monitor monitoring solution. It allows you to instrument your Python applications to capture and report telemetry to Azure Monitor via the Azure monitor exporters. This distro automatically installs the following libraries: