Skip to content

Commit 768b28c

Browse files
committed
Remove console exporter metric output if empty
Fixes #3198
1 parent 9706ed0 commit 768b28c

File tree

4 files changed

+40
-22
lines changed

4 files changed

+40
-22
lines changed

opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/__init__.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ def _set_collect_callback(
344344
@abstractmethod
345345
def _receive_metrics(
346346
self,
347-
metrics_data: "opentelemetry.sdk.metrics.export.MetricsData",
347+
metrics_data: Optional[MetricsData],
348348
timeout_millis: float = 10_000,
349349
**kwargs,
350350
) -> None:
@@ -386,9 +386,9 @@ def __init__(
386386
preferred_aggregation=preferred_aggregation,
387387
)
388388
self._lock = RLock()
389-
self._metrics_data: (
389+
self._metrics_data: Optional[
390390
"opentelemetry.sdk.metrics.export.MetricsData"
391-
) = None
391+
] = None
392392

393393
def get_metrics_data(
394394
self,
@@ -402,7 +402,7 @@ def get_metrics_data(
402402

403403
def _receive_metrics(
404404
self,
405-
metrics_data: "opentelemetry.sdk.metrics.export.MetricsData",
405+
metrics_data: Optional[MetricsData],
406406
timeout_millis: float = 10_000,
407407
**kwargs,
408408
) -> None:
@@ -511,7 +511,7 @@ def _ticker(self) -> None:
511511

512512
def _receive_metrics(
513513
self,
514-
metrics_data: MetricsData,
514+
metrics_data: Optional[MetricsData],
515515
timeout_millis: float = 10_000,
516516
**kwargs,
517517
) -> None:

opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/measurement_consumer.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from abc import ABC, abstractmethod
1818
from threading import Lock
1919
from time import time_ns
20-
from typing import Iterable, List, Mapping
20+
from typing import List, Mapping, Optional
2121

2222
# This kind of import is needed to avoid Sphinx errors.
2323
import opentelemetry.sdk.metrics
@@ -29,7 +29,7 @@
2929
from opentelemetry.sdk.metrics._internal.metric_reader_storage import (
3030
MetricReaderStorage,
3131
)
32-
from opentelemetry.sdk.metrics._internal.point import Metric
32+
from opentelemetry.sdk.metrics._internal.point import MetricsData
3333

3434

3535
class MeasurementConsumer(ABC):
@@ -51,7 +51,7 @@ def collect(
5151
self,
5252
metric_reader: "opentelemetry.sdk.metrics.MetricReader",
5353
timeout_millis: float = 10_000,
54-
) -> Iterable[Metric]:
54+
) -> Optional[MetricsData]:
5555
pass
5656

5757

@@ -94,7 +94,7 @@ def collect(
9494
self,
9595
metric_reader: "opentelemetry.sdk.metrics.MetricReader",
9696
timeout_millis: float = 10_000,
97-
) -> Iterable[Metric]:
97+
) -> Optional[MetricsData]:
9898

9999
with self._lock:
100100
metric_reader_storage = self._reader_storages[metric_reader]

opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/metric_reader_storage.py

+15-13
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from logging import getLogger
1616
from threading import RLock
1717
from time import time_ns
18-
from typing import Dict, List
18+
from typing import Dict, List, Optional
1919

2020
from opentelemetry.metrics import (
2121
Asynchronous,
@@ -119,7 +119,7 @@ def consume_measurement(self, measurement: Measurement) -> None:
119119
):
120120
view_instrument_match.consume_measurement(measurement)
121121

122-
def collect(self) -> MetricsData:
122+
def collect(self) -> Optional[MetricsData]:
123123
# Use a list instead of yielding to prevent a slow reader from holding
124124
# SDK locks
125125

@@ -231,17 +231,19 @@ def collect(self) -> MetricsData:
231231
instrument.instrumentation_scope
232232
].metrics.extend(metrics)
233233

234-
return MetricsData(
235-
resource_metrics=[
236-
ResourceMetrics(
237-
resource=self._sdk_config.resource,
238-
scope_metrics=list(
239-
instrumentation_scope_scope_metrics.values()
240-
),
241-
schema_url=self._sdk_config.resource.schema_url,
242-
)
243-
]
244-
)
234+
scope_metrics = list(instrumentation_scope_scope_metrics.values())
235+
236+
if scope_metrics:
237+
238+
return MetricsData(
239+
resource_metrics=[
240+
ResourceMetrics(
241+
resource=self._sdk_config.resource,
242+
scope_metrics=scope_metrics,
243+
schema_url=self._sdk_config.resource.schema_url,
244+
)
245+
]
246+
)
245247

246248
def _handle_view_instrument_match(
247249
self,

opentelemetry-sdk/tests/metrics/integration_test/test_console_exporter.py

+16
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,19 @@ def test_console_exporter(self):
7272

7373
self.assertEqual(metrics["attributes"], {"a": "b"})
7474
self.assertEqual(metrics["value"], 1)
75+
76+
def test_console_exporter_no_export(self):
77+
78+
output = StringIO()
79+
exporter = ConsoleMetricExporter(out=output)
80+
reader = PeriodicExportingMetricReader(
81+
exporter, export_interval_millis=100
82+
)
83+
provider = MeterProvider(metric_readers=[reader])
84+
provider.shutdown()
85+
86+
output.seek(0)
87+
actual = "".join(output.readlines())
88+
expected = ""
89+
90+
self.assertEqual(actual, expected)

0 commit comments

Comments
 (0)