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 % 42 42
Test Date: 2026-08-27 23:42:02 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;
      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           15 :   Counter({required APICounter<T> apiCounter, required Meter meter})
      42              :       : _apiCounter = apiCounter,
      43              :         _meter = meter,
      44           15 :         _storage = SumStorage<T>(
      45              :           isMonotonic: true,
      46           30 :           exemplarFilter: meter.provider.exemplarFilter,
      47              :         ) {
      48           75 :     _meter.provider.registerInstrument(_meter.name, this);
      49              :   }
      50              : 
      51              :   /// Gets the name of this counter.
      52           15 :   @override
      53           30 :   String get name => _apiCounter.name;
      54              : 
      55              :   /// Gets the unit of measurement for this counter.
      56           11 :   @override
      57           22 :   String? get unit => _apiCounter.unit;
      58              : 
      59              :   /// Gets the description of this counter.
      60           11 :   @override
      61           22 :   String? get description => _apiCounter.description;
      62              : 
      63              :   /// Checks if this counter is enabled.
      64              :   ///
      65              :   /// If false, measurements will be dropped and not recorded.
      66           14 :   @override
      67           28 :   bool isEnabled() => _meter.isEnabled();
      68              : 
      69              :   /// Gets the meter that created this counter.
      70           15 :   @override
      71           15 :   APIMeter get meter => _meter;
      72              : 
      73              :   /// Always true for Counter instruments.
      74            1 :   @override
      75              :   bool get isCounter => true;
      76              : 
      77              :   /// Always false for Counter instruments.
      78            1 :   @override
      79              :   bool get isUpDownCounter => false;
      80              : 
      81              :   /// Always false for Counter instruments.
      82            1 :   @override
      83              :   bool get isGauge => false;
      84              : 
      85              :   /// Always false for Counter instruments.
      86            1 :   @override
      87              :   bool get isHistogram => false;
      88              : 
      89              :   /// Records a measurement with this counter.
      90              :   ///
      91              :   /// This method increments the counter by the given value. The value must be
      92              :   /// non-negative, or an ArgumentError will be thrown.
      93              :   ///
      94              :   /// @param value The amount to increment the counter by (must be non-negative)
      95              :   /// @param attributes Optional attributes to associate with this measurement
      96              :   /// @throws ArgumentError if value is negative
      97           14 :   @override
      98              :   void add(T value, [Attributes? attributes]) {
      99              :     // First use the API implementation (no-op by default)
     100           28 :     _apiCounter.add(value, attributes);
     101              : 
     102              :     // Check for negative values
     103           14 :     if (value < 0) {
     104            1 :       throw ArgumentError('Counter value must be non-negative');
     105              :     }
     106              : 
     107              :     // Only record if enabled
     108           14 :     if (!isEnabled()) return;
     109              : 
     110              :     // Record the measurement in our storage
     111           42 :     _storage.record(value, attributes, Context.current);
     112              :   }
     113              : 
     114              :   /// Records a measurement with attributes specified as a map.
     115              :   ///
     116              :   /// This is a convenience method that converts the map to Attributes
     117              :   /// and calls add().
     118              :   ///
     119              :   /// @param value The amount to increment the counter by (must be non-negative)
     120              :   /// @param attributeMap Map of attribute names to values
     121            1 :   @override
     122              :   void addWithMap(T value, Map<String, Object> attributeMap) {
     123              :     // Just convert to Attributes and call add
     124              :     final attributes =
     125            2 :         attributeMap.isEmpty ? null : attributeMap.toAttributes();
     126            1 :     add(value, attributes);
     127              :   }
     128              : 
     129              :   /// Gets the current value of the counter for a specific set of attributes.
     130              :   ///
     131              :   /// If no attributes are provided, returns the sum of all values across all attributes.
     132              :   ///
     133              :   /// @param attributes Optional attributes to filter by
     134              :   /// @return The current value of the counter
     135            4 :   T getValue([Attributes? attributes]) {
     136            8 :     return _storage.getValue(attributes);
     137              :   }
     138              : 
     139              :   /// Gets the current points for this counter.
     140              :   ///
     141              :   /// This is used by the SDK to collect metrics for export.
     142              :   ///
     143              :   /// @return A list of metric points containing the current counter values
     144           10 :   List<MetricPoint<T>> collectPoints() {
     145           20 :     return _storage.collectPoints();
     146              :   }
     147              : 
     148              :   /// Collects metrics for this counter.
     149              :   ///
     150              :   /// This method is called by the SDK to collect metrics for export.
     151              :   ///
     152              :   /// @return A list of metrics containing the current counter values
     153           10 :   @override
     154              :   List<Metric> collectMetrics() {
     155           11 :     if (!isEnabled()) return [];
     156              : 
     157              :     // Get the points from storage
     158           10 :     final points = collectPoints();
     159              : 
     160           10 :     if (points.isEmpty) return [];
     161              : 
     162           10 :     final metric = Metric(
     163           10 :       name: name,
     164           10 :       description: description,
     165           10 :       unit: unit,
     166              :       type: MetricType.sum,
     167              :       points: points,
     168              :     );
     169              : 
     170           10 :     return [metric];
     171              :   }
     172              : 
     173              :   /// Resets the counter.
     174              :   ///
     175              :   /// This is only used for Delta temporality and should not be called
     176              :   /// by application code.
     177            2 :   void reset() {
     178            4 :     _storage.reset();
     179              :   }
     180              : }
        

Generated by: LCOV version 2.0-1