Repository: open-telemetry/opentelemetry-python

Issue:
The metrics exporter should provide a ForceFlush function



Discussion:

Resolving patch:
diff --git a/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py
--- a/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py
+++ b/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/metric_exporter/__init__.py
@@ -210,3 +210,6 @@ def shutdown(self, timeout_millis: float = 30_000, **kwargs) -> None:
     @property
     def _exporting(self) -> str:
         return "metrics"
+
+    def force_flush(self, timeout_millis: float = 10_000) -> bool:
+        return True
diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/__init__.py
--- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/__init__.py
+++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/export/__init__.py
@@ -91,6 +91,13 @@ def export(
             The result of the export
         """
 
+    @abstractmethod
+    def force_flush(self, timeout_millis: float = 10_000) -> bool:
+        """
+        Ensure that export of any metrics currently received by the exporter
+        are completed as soon as possible.
+        """
+
     @abstractmethod
     def shutdown(self, timeout_millis: float = 30_000, **kwargs) -> None:
         """Shuts down the exporter.
@@ -131,6 +138,9 @@ def export(
     def shutdown(self, timeout_millis: float = 30_000, **kwargs) -> None:
         pass
 
+    def force_flush(self, timeout_millis: float = 10_000) -> bool:
+        return True
+
 
 class MetricReader(ABC):
     """


Test patch:
diff --git a/opentelemetry-sdk/tests/metrics/test_backward_compat.py b/opentelemetry-sdk/tests/metrics/test_backward_compat.py
--- a/opentelemetry-sdk/tests/metrics/test_backward_compat.py
+++ b/opentelemetry-sdk/tests/metrics/test_backward_compat.py
@@ -53,6 +53,9 @@ def export(
     def shutdown(self, timeout_millis: float = 30_000, **kwargs) -> None:
         pass
 
+    def force_flush(self, timeout_millis: float = 10_000) -> bool:
+        return True
+
 
 class OrigMetricReader(MetricReader):
     def _receive_metrics(
diff --git a/opentelemetry-sdk/tests/metrics/test_metrics.py b/opentelemetry-sdk/tests/metrics/test_metrics.py
--- a/opentelemetry-sdk/tests/metrics/test_metrics.py
+++ b/opentelemetry-sdk/tests/metrics/test_metrics.py
@@ -445,6 +445,9 @@ def export(
     def shutdown(self, timeout_millis: float = 30_000, **kwargs) -> None:
         pass
 
+    def force_flush(self, timeout_millis: float = 10_000) -> bool:
+        return True
+
 
 class TestDuplicateInstrumentAggregateData(TestCase):
     def test_duplicate_instrument_aggregate_data(self):
diff --git a/opentelemetry-sdk/tests/metrics/test_periodic_exporting_metric_reader.py b/opentelemetry-sdk/tests/metrics/test_periodic_exporting_metric_reader.py
--- a/opentelemetry-sdk/tests/metrics/test_periodic_exporting_metric_reader.py
+++ b/opentelemetry-sdk/tests/metrics/test_periodic_exporting_metric_reader.py
@@ -50,6 +50,9 @@ def export(
     def shutdown(self, timeout_millis: float = 30_000, **kwargs) -> None:
         self._shutdown = True
 
+    def force_flush(self, timeout_millis: float = 10_000) -> bool:
+        return True
+
 
 metrics_list = [
     Metric(