Skip to content

Commit f7a3e62

Browse files
authored
Verify previous point is returned for cumulative instruments (#2773)
* Verify previous point is returned for cumulative instruments Fixes #2755 * Reject non-cumulative temporalities for Prometheus metric reader * Add test case for InMemoryMetricReader * Fix prometheus import paths * Remove parameters for Prometheus init * Add sleep for windows tests * Add temporality overriding dictionary
1 parent af09df3 commit f7a3e62

File tree

3 files changed

+84
-3
lines changed

3 files changed

+84
-3
lines changed

exporter/opentelemetry-exporter-prometheus/src/opentelemetry/exporter/prometheus/__init__.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,16 @@
7777
)
7878
from prometheus_client.core import Metric as PrometheusMetric
7979

80+
from opentelemetry.sdk.metrics import Counter
81+
from opentelemetry.sdk.metrics import Histogram as HistogramInstrument
82+
from opentelemetry.sdk.metrics import (
83+
ObservableCounter,
84+
ObservableGauge,
85+
ObservableUpDownCounter,
86+
UpDownCounter,
87+
)
8088
from opentelemetry.sdk.metrics.export import (
89+
AggregationTemporality,
8190
Gauge,
8291
Histogram,
8392
HistogramDataPoint,
@@ -113,7 +122,17 @@ class PrometheusMetricReader(MetricReader):
113122
"""
114123

115124
def __init__(self, prefix: str = "") -> None:
116-
super().__init__()
125+
126+
super().__init__(
127+
preferred_temporality={
128+
Counter: AggregationTemporality.CUMULATIVE,
129+
UpDownCounter: AggregationTemporality.CUMULATIVE,
130+
HistogramInstrument: AggregationTemporality.CUMULATIVE,
131+
ObservableCounter: AggregationTemporality.CUMULATIVE,
132+
ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
133+
ObservableGauge: AggregationTemporality.CUMULATIVE,
134+
}
135+
)
117136
self._collector = _CustomCollector(prefix)
118137
REGISTRY.register(self._collector)
119138
self._collector._callback = self.collect

exporter/opentelemetry-exporter-prometheus/tests/test_prometheus_exporter.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
PrometheusMetricReader,
2424
_CustomCollector,
2525
)
26+
from opentelemetry.sdk.metrics import MeterProvider
2627
from opentelemetry.sdk.metrics.export import (
2728
AggregationTemporality,
2829
Histogram,
@@ -51,7 +52,7 @@ def setUp(self):
5152
def test_constructor(self):
5253
"""Test the constructor."""
5354
with self._registry_register_patch:
54-
exporter = PrometheusMetricReader("testprefix")
55+
exporter = PrometheusMetricReader(prefix="testprefix")
5556
self.assertEqual(exporter._collector._prefix, "testprefix")
5657
self.assertTrue(self._mock_registry_register.called)
5758

@@ -286,3 +287,16 @@ def test_check_value(self):
286287
self.assertEqual(collector._check_value(True), "true")
287288
self.assertEqual(collector._check_value(False), "false")
288289
self.assertEqual(collector._check_value(None), "null")
290+
291+
def test_multiple_collection_calls(self):
292+
293+
metric_reader = PrometheusMetricReader(prefix="prefix")
294+
provider = MeterProvider(metric_readers=[metric_reader])
295+
meter = provider.get_meter("getting-started", "0.1.2")
296+
counter = meter.create_counter("counter")
297+
counter.add(1)
298+
result_0 = list(metric_reader._collector.collect())
299+
result_1 = list(metric_reader._collector.collect())
300+
result_2 = list(metric_reader._collector.collect())
301+
self.assertEqual(result_0, result_1)
302+
self.assertEqual(result_1, result_2)

opentelemetry-sdk/tests/metrics/test_in_memory_metric_reader.py

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
from time import sleep
1516
from unittest import TestCase
1617
from unittest.mock import Mock
1718

1819
from opentelemetry.metrics import Observation
19-
from opentelemetry.sdk.metrics import MeterProvider
20+
from opentelemetry.sdk.metrics import Counter, MeterProvider
2021
from opentelemetry.sdk.metrics.export import (
2122
AggregationTemporality,
2223
InMemoryMetricReader,
@@ -106,3 +107,50 @@ def test_integration(self):
106107
),
107108
1,
108109
)
110+
111+
def test_cumulative_multiple_collect(self):
112+
113+
reader = InMemoryMetricReader(
114+
preferred_temporality={Counter: AggregationTemporality.CUMULATIVE}
115+
)
116+
meter = MeterProvider(metric_readers=[reader]).get_meter("test_meter")
117+
counter = meter.create_counter("counter1")
118+
counter.add(1, attributes={"key": "value"})
119+
120+
reader.collect()
121+
122+
number_data_point_0 = list(
123+
reader._metrics_data.resource_metrics[0]
124+
.scope_metrics[0]
125+
.metrics[0]
126+
.data.data_points
127+
)[0]
128+
129+
# Windows tests fail without this sleep because both time_unix_nano
130+
# values are the same.
131+
sleep(0.1)
132+
reader.collect()
133+
134+
number_data_point_1 = list(
135+
reader._metrics_data.resource_metrics[0]
136+
.scope_metrics[0]
137+
.metrics[0]
138+
.data.data_points
139+
)[0]
140+
141+
self.assertEqual(
142+
number_data_point_0.attributes, number_data_point_1.attributes
143+
)
144+
self.assertEqual(
145+
number_data_point_0.start_time_unix_nano,
146+
number_data_point_1.start_time_unix_nano,
147+
)
148+
self.assertEqual(
149+
number_data_point_0.start_time_unix_nano,
150+
number_data_point_1.start_time_unix_nano,
151+
)
152+
self.assertEqual(number_data_point_0.value, number_data_point_1.value)
153+
self.assertGreater(
154+
number_data_point_1.time_unix_nano,
155+
number_data_point_0.time_unix_nano,
156+
)

0 commit comments

Comments
 (0)