11# Copyright (c) Microsoft Corporation. All rights reserved.
22# Licensed under the MIT License.
33import logging
4- from typing import Sequence , Any
5-
6- from opentelemetry .sdk ._metrics .export import MetricExporter , MetricExportResult
7- from opentelemetry .sdk ._metrics .point import (
8- Gauge ,
9- Histogram ,
10- Metric ,
11- Sum ,
4+
5+ from typing import Optional , Any
6+
7+ from opentelemetry .sdk .metrics .export import (
8+ DataPointT ,
9+ HistogramDataPoint ,
10+ MetricExporter ,
11+ MetricExportResult ,
12+ MetricsData as OTMetricsData ,
13+ NumberDataPoint ,
1214)
15+ from opentelemetry .sdk .resources import Resource
16+ from opentelemetry .sdk .util .instrumentation import InstrumentationScope
1317
1418from azure .monitor .opentelemetry .exporter import _utils
1519from azure .monitor .opentelemetry .exporter ._generated .models import (
@@ -32,14 +36,32 @@ class AzureMonitorMetricExporter(BaseExporter, MetricExporter):
3236 """Azure Monitor Metric exporter for OpenTelemetry."""
3337
3438 def export (
35- self , metrics : Sequence [Metric ], ** kwargs : Any # pylint: disable=unused-argument
39+ self ,
40+ metrics_data : OTMetricsData ,
41+ timeout_millis : float = 10_000 , # pylint: disable=unused-argument
42+ ** kwargs : Any , # pylint: disable=unused-argument
3643 ) -> MetricExportResult :
3744 """Exports a batch of metric data
3845 :param metrics: Open Telemetry Metric(s) to export.
39- :type metrics : Sequence[~opentelemetry._metrics. point.Metric ]
40- :rtype: ~opentelemetry.sdk._metrics .export.MetricExportResult
46+ :type metrics_data : Sequence[~opentelemetry.sdk.metrics._internal. point.MetricsData ]
47+ :rtype: ~opentelemetry.sdk.metrics .export.MetricExportResult
4148 """
42- envelopes = [self ._metric_to_envelope (metric ) for metric in metrics ]
49+ envelopes = []
50+ if metrics_data is None :
51+ return MetricExportResult .SUCCESS
52+ for resource_metric in metrics_data .resource_metrics :
53+ for scope_metric in resource_metric .scope_metrics :
54+ for metric in scope_metric .metrics :
55+ for point in metric .data .data_points :
56+ if point is not None :
57+ envelopes .append (
58+ self ._point_to_envelope (
59+ point ,
60+ metric .name ,
61+ resource_metric .resource ,
62+ scope_metric .scope
63+ )
64+ )
4365 try :
4466 result = self ._transmit (envelopes )
4567 if result == ExportResult .FAILED_RETRYABLE :
@@ -53,17 +75,25 @@ def export(
5375 _logger .exception ("Exception occurred while exporting the data." )
5476 return _get_metric_export_result (ExportResult .FAILED_NOT_RETRYABLE )
5577
56- def shutdown (self ) -> None :
78+ def shutdown (
79+ self ,
80+ timeout_millis : float = 30_000 , # pylint: disable=unused-argument
81+ ** kwargs : Any , # pylint: disable=unused-argument
82+ ) -> None :
5783 """Shuts down the exporter.
5884
5985 Called when the SDK is shut down.
6086 """
6187 self .storage .close ()
6288
63- def _metric_to_envelope (self , metric : Metric ) -> TelemetryItem :
64- if not metric :
65- return None
66- envelope = _convert_metric_to_envelope (metric )
89+ def _point_to_envelope (
90+ self ,
91+ point : DataPointT ,
92+ name : str ,
93+ resource : Optional [Resource ] = None ,
94+ scope : Optional [InstrumentationScope ] = None
95+ ) -> TelemetryItem :
96+ envelope = _convert_point_to_envelope (point , name , resource , scope )
6797 envelope .instrumentation_key = self ._instrumentation_key
6898 return envelope
6999
@@ -86,33 +116,39 @@ def from_connection_string(
86116
87117
88118# pylint: disable=protected-access
89- def _convert_metric_to_envelope (metric : Metric ) -> TelemetryItem :
90- point = metric .point
119+ def _convert_point_to_envelope (
120+ point : DataPointT ,
121+ name : str ,
122+ resource : Optional [Resource ] = None ,
123+ scope : Optional [InstrumentationScope ] = None # pylint: disable=unused-argument
124+ ) -> TelemetryItem :
91125 envelope = _utils ._create_telemetry_item (point .time_unix_nano )
92126 envelope .name = "Microsoft.ApplicationInsights.Metric"
93- envelope .tags .update (_utils ._populate_part_a_fields (metric .resource ))
94- properties = metric .attributes
127+ envelope .tags .update (_utils ._populate_part_a_fields (resource ))
95128 value = 0
96- # TODO
97129 count = 1
98- # min = None
99- # max = None
130+ min_ = None
131+ max_ = None
100132 # std_dev = None
101133
102- if isinstance (point , ( Gauge , Sum ) ):
134+ if isinstance (point , NumberDataPoint ):
103135 value = point .value
104- elif isinstance (point , Histogram ):
105- value = sum (point .bucket_counts )
106- count = sum (point .bucket_counts )
136+ elif isinstance (point , HistogramDataPoint ):
137+ value = point .sum
138+ count = point .count
139+ min_ = point .min
140+ max_ = point .max
107141
108142 data_point = MetricDataPoint (
109- name = metric . name ,
143+ name = name ,
110144 value = value ,
111145 data_point_type = "Aggregation" ,
112146 count = count ,
147+ min = min_ ,
148+ max = max_ ,
113149 )
114150 data = MetricsData (
115- properties = properties ,
151+ properties = dict ( point . attributes ) ,
116152 metrics = [data_point ],
117153 )
118154
0 commit comments