LCOV - code coverage report
Current view: top level - lib/src/metrics/instruments - counter.dart (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 40 40
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              : 
       6              : import '../data/metric.dart';
       7              : import '../data/metric_point.dart';
       8              : import '../meter.dart';
       9              : import '../storage/sum_storage.dart';
      10              : import 'base_instrument.dart';
      11              : 
      12              : /// A synchronous instrument that records monotonically increasing values.
      13              : ///
      14              : /// A Counter is used to measure a non-negative, monotonically increasing value.
      15              : /// Counters only allow positive increments and are appropriate for values that
      16              : /// never decrease, such as:
      17              : /// - Request count
      18              : /// - Completed operations
      19              : /// - Error count
      20              : /// - CPU time used
      21              : /// - Bytes sent/received
      22              : ///
      23              : /// If the value can decrease, use an UpDownCounter instead.
      24              : ///
      25              : /// More information:
      26              : /// https://opentelemetry.io/docs/specs/otel/metrics/api/#counter
      27              : class Counter<T extends num> implements APICounter<T>, SDKInstrument {
      28              :   /// The underlying API Counter.
      29              :   final APICounter<T> _apiCounter;
      30              : 
      31              :   /// The Meter that created this Counter.
      32              :   final Meter _meter;
      33              : 
      34              :   /// Storage for accumulating counter measurements.
      35              :   final SumStorage<T> _storage = SumStorage<T>(isMonotonic: true);
      36              : 
      37              :   /// Creates a new Counter instance.
      38              :   ///
      39              :   /// @param apiCounter The API Counter to delegate API calls to
      40              :   /// @param meter The Meter that created this Counter
      41           12 :   Counter({required APICounter<T> apiCounter, required Meter meter})
      42              :       : _apiCounter = apiCounter,
      43              :         _meter = meter {
      44           60 :     _meter.provider.registerInstrument(_meter.name, this);
      45              :   }
      46              : 
      47              :   /// Gets the name of this counter.
      48           12 :   @override
      49           24 :   String get name => _apiCounter.name;
      50              : 
      51              :   /// Gets the unit of measurement for this counter.
      52            8 :   @override
      53           16 :   String? get unit => _apiCounter.unit;
      54              : 
      55              :   /// Gets the description of this counter.
      56            8 :   @override
      57           16 :   String? get description => _apiCounter.description;
      58              : 
      59              :   /// Checks if this counter is enabled.
      60              :   ///
      61              :   /// If false, measurements will be dropped and not recorded.
      62           11 :   @override
      63           22 :   bool get enabled => _meter.enabled;
      64              : 
      65              :   /// Gets the meter that created this counter.
      66           12 :   @override
      67           12 :   APIMeter get meter => _meter;
      68              : 
      69              :   /// Always true for Counter instruments.
      70            1 :   @override
      71              :   bool get isCounter => true;
      72              : 
      73              :   /// Always false for Counter instruments.
      74            1 :   @override
      75              :   bool get isUpDownCounter => false;
      76              : 
      77              :   /// Always false for Counter instruments.
      78            1 :   @override
      79              :   bool get isGauge => false;
      80              : 
      81              :   /// Always false for Counter instruments.
      82            1 :   @override
      83              :   bool get isHistogram => false;
      84              : 
      85              :   /// Records a measurement with this counter.
      86              :   ///
      87              :   /// This method increments the counter by the given value. The value must be
      88              :   /// non-negative, or an ArgumentError will be thrown.
      89              :   ///
      90              :   /// @param value The amount to increment the counter by (must be non-negative)
      91              :   /// @param attributes Optional attributes to associate with this measurement
      92              :   /// @throws ArgumentError if value is negative
      93           11 :   @override
      94              :   void add(T value, [Attributes? attributes]) {
      95              :     // First use the API implementation (no-op by default)
      96           22 :     _apiCounter.add(value, attributes);
      97              : 
      98              :     // Check for negative values
      99           11 :     if (value < 0) {
     100            1 :       throw ArgumentError('Counter value must be non-negative');
     101              :     }
     102              : 
     103              :     // Only record if enabled
     104           11 :     if (!enabled) return;
     105              : 
     106              :     // Record the measurement in our storage
     107           22 :     _storage.record(value, attributes);
     108              :   }
     109              : 
     110              :   /// Records a measurement with attributes specified as a map.
     111              :   ///
     112              :   /// This is a convenience method that converts the map to Attributes
     113              :   /// and calls add().
     114              :   ///
     115              :   /// @param value The amount to increment the counter by (must be non-negative)
     116              :   /// @param attributeMap Map of attribute names to values
     117            1 :   @override
     118              :   void addWithMap(T value, Map<String, Object> attributeMap) {
     119              :     // Just convert to Attributes and call add
     120              :     final attributes =
     121            2 :         attributeMap.isEmpty ? null : attributeMap.toAttributes();
     122            1 :     add(value, attributes);
     123              :   }
     124              : 
     125              :   /// Gets the current value of the counter for a specific set of attributes.
     126              :   ///
     127              :   /// If no attributes are provided, returns the sum of all values across all attributes.
     128              :   ///
     129              :   /// @param attributes Optional attributes to filter by
     130              :   /// @return The current value of the counter
     131            4 :   T getValue([Attributes? attributes]) {
     132            8 :     return _storage.getValue(attributes);
     133              :   }
     134              : 
     135              :   /// Gets the current points for this counter.
     136              :   ///
     137              :   /// This is used by the SDK to collect metrics for export.
     138              :   ///
     139              :   /// @return A list of metric points containing the current counter values
     140            7 :   List<MetricPoint<T>> collectPoints() {
     141           14 :     return _storage.collectPoints();
     142              :   }
     143              : 
     144              :   /// Collects metrics for this counter.
     145              :   ///
     146              :   /// This method is called by the SDK to collect metrics for export.
     147              :   ///
     148              :   /// @return A list of metrics containing the current counter values
     149            7 :   @override
     150              :   List<Metric> collectMetrics() {
     151            8 :     if (!enabled) return [];
     152              : 
     153              :     // Get the points from storage
     154            7 :     final points = collectPoints();
     155              : 
     156            7 :     if (points.isEmpty) return [];
     157              : 
     158            7 :     final metric = Metric(
     159            7 :       name: name,
     160            7 :       description: description,
     161            7 :       unit: unit,
     162              :       type: MetricType.sum,
     163              :       points: points,
     164              :     );
     165              : 
     166            7 :     return [metric];
     167              :   }
     168              : 
     169              :   /// Resets the counter.
     170              :   ///
     171              :   /// This is only used for Delta temporality and should not be called
     172              :   /// by application code.
     173            2 :   void reset() {
     174            4 :     _storage.reset();
     175              :   }
     176              : }
        

Generated by: LCOV version 2.0-1