LCOV - code coverage report
Current view: top level - lib/src/metrics/export - composite_metric_exporter.dart (source / functions) Coverage Total Hit
Test: lcov.info Lines: 95.0 % 20 19
Test Date: 2026-07-11 13:35:19 Functions: - 0 0

            Line data    Source code
       1              : // Copyright The OpenTelemetry Authors
       2              : // SPDX-License-Identifier: Apache-2.0
       3              : 
       4              : import 'package:dartastic_opentelemetry_api/dartastic_opentelemetry_api.dart'
       5              :     show OTelLog;
       6              : 
       7              : import '../data/metric_data.dart';
       8              : import '../metric_exporter.dart';
       9              : 
      10              : /// A composite metric exporter that delegates to multiple exporters.
      11              : ///
      12              : /// This exporter implements the fan-out pattern, where metrics are exported
      13              : /// to multiple backends simultaneously. It forwards all export, flush, and
      14              : /// shutdown operations to each of its delegate exporters.
      15              : ///
      16              : /// This is useful for scenarios where you want to send metrics to multiple
      17              : /// destinations, such as a local console and a remote collector.
      18              : ///
      19              : /// More information:
      20              : /// https://opentelemetry.io/docs/specs/otel/metrics/sdk/#metricexporter
      21              : class CompositeMetricExporter implements MetricExporter {
      22              :   /// The list of delegate exporters.
      23              :   final List<MetricExporter> _exporters;
      24              : 
      25              :   /// Whether this exporter has been shut down.
      26              :   bool _shutdown = false;
      27              : 
      28              :   /// Creates a new CompositeMetricExporter with the given list of exporters.
      29              :   ///
      30              :   /// @param exporters The list of exporters to which operations will be delegated
      31            2 :   CompositeMetricExporter(this._exporters);
      32              : 
      33              :   /// The delegate exporters this composite forwards to.
      34            0 :   List<MetricExporter> get exporters => List.unmodifiable(_exporters);
      35              : 
      36              :   /// Exports metrics to all delegate exporters.
      37              :   ///
      38              :   /// This method forwards the export operation to each delegate exporter.
      39              :   /// If any exporter fails, the composite exporter will still try to export
      40              :   /// to the remaining exporters, but will return false to indicate failure.
      41              :   ///
      42              :   /// @param data The metric data to export
      43              :   /// @return true if all exporters succeeded, false if any exporter failed
      44            2 :   @override
      45              :   Future<bool> export(MetricData data) async {
      46            2 :     if (_shutdown) {
      47            1 :       if (OTelLog.isLogExport()) {
      48            1 :         OTelLog.logExport(
      49              :           'CompositeMetricExporter: Cannot export after shutdown',
      50              :         );
      51              :       }
      52              :       return false;
      53              :     }
      54              : 
      55              :     var success = true;
      56            4 :     for (final exporter in _exporters) {
      57              :       try {
      58            2 :         final result = await exporter.export(data);
      59              :         success = success && result;
      60              :       } catch (e) {
      61            1 :         if (OTelLog.isLogExport()) {
      62            1 :           OTelLog.logExport(
      63            1 :             'CompositeMetricExporter: Export failed for $exporter: $e',
      64              :           );
      65              :         }
      66              :         success = false;
      67              :       }
      68              :     }
      69              : 
      70              :     return success;
      71              :   }
      72              : 
      73              :   /// Forces a flush of all delegate exporters.
      74              :   ///
      75              :   /// This method forwards the flush operation to each delegate exporter.
      76              :   /// If any exporter fails to flush, the composite exporter will still try
      77              :   /// to flush the remaining exporters, but will return false to indicate failure.
      78              :   ///
      79              :   /// @return true if all exporters were flushed successfully, false otherwise
      80            2 :   @override
      81              :   Future<bool> forceFlush() async {
      82            2 :     if (_shutdown) {
      83              :       return false;
      84              :     }
      85              : 
      86              :     var success = true;
      87            4 :     for (final exporter in _exporters) {
      88              :       try {
      89            2 :         final result = await exporter.forceFlush();
      90              :         success = success && result;
      91              :       } catch (e) {
      92              :         success = false;
      93              :       }
      94              :     }
      95              : 
      96              :     return success;
      97              :   }
      98              : 
      99              :   /// Shuts down all delegate exporters.
     100              :   ///
     101              :   /// This method forwards the shutdown operation to each delegate exporter.
     102              :   /// Once shut down, this exporter will no longer accept export requests.
     103              :   ///
     104              :   /// @return true if all exporters were shut down successfully, false otherwise
     105            2 :   @override
     106              :   Future<bool> shutdown() async {
     107            2 :     if (_shutdown) {
     108              :       return true;
     109              :     }
     110              : 
     111            2 :     _shutdown = true;
     112              :     var success = true;
     113            4 :     for (final exporter in _exporters) {
     114              :       try {
     115            2 :         final result = await exporter.shutdown();
     116              :         success = success && result;
     117              :       } catch (e) {
     118              :         success = false;
     119              :       }
     120              :     }
     121              : 
     122              :     return success;
     123              :   }
     124              : }
        

Generated by: LCOV version 2.0-1