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 : /// UpDownCounter is a synchronous instrument that records additive values.
13 : ///
14 : /// An UpDownCounter is used to measure a value that increases and decreases.
15 : /// For example, the number of active requests, queue size, pool size.
16 : class UpDownCounter<T extends num>
17 : implements APIUpDownCounter<T>, SDKInstrument {
18 : /// The underlying API UpDownCounter.
19 : final APIUpDownCounter<T> _apiCounter;
20 :
21 : /// The Meter that created this UpDownCounter.
22 : final Meter _meter;
23 :
24 : /// Storage for accumulating up-down counter measurements.
25 : final SumStorage<T> _storage;
26 :
27 : /// Creates a new UpDownCounter instance.
28 6 : UpDownCounter({required APIUpDownCounter<T> apiCounter, required Meter meter})
29 : : _apiCounter = apiCounter,
30 : _meter = meter,
31 6 : _storage = SumStorage<T>(
32 : isMonotonic: false,
33 12 : exemplarFilter: meter.provider.exemplarFilter,
34 : ) {
35 : // Register this instrument with the meter provider
36 30 : _meter.provider.registerInstrument(_meter.name, this);
37 : }
38 :
39 6 : @override
40 12 : String get name => _apiCounter.name;
41 :
42 2 : @override
43 4 : String? get unit => _apiCounter.unit;
44 :
45 2 : @override
46 4 : String? get description => _apiCounter.description;
47 :
48 1 : @override
49 2 : bool isEnabled() => _meter.isEnabled();
50 :
51 6 : @override
52 6 : APIMeter get meter => _meter;
53 :
54 1 : @override
55 2 : InstrumentAdvisory? get advisory => _apiCounter.advisory;
56 :
57 1 : @override
58 : bool get isCounter => false;
59 :
60 1 : @override
61 : bool get isUpDownCounter => true;
62 :
63 1 : @override
64 : bool get isGauge => false;
65 :
66 1 : @override
67 : bool get isHistogram => false;
68 :
69 3 : @override
70 : void add(T value, [Attributes? attributes]) {
71 : // First use the API implementation (no-op by default)
72 6 : _apiCounter.add(value, attributes);
73 :
74 : // In the SDK, we only check the meter's enabled state
75 6 : if (!_meter.isEnabled()) return;
76 :
77 : // Record the measurement in our storage
78 9 : _storage.record(value, attributes, Context.current);
79 : }
80 :
81 1 : @override
82 : void addWithMap(T value, Map<String, Object> attributeMap) {
83 : // Just convert to Attributes and call add
84 : final attributes =
85 2 : attributeMap.isEmpty ? null : attributeMap.toAttributes();
86 1 : add(value, attributes);
87 : }
88 :
89 : /// Gets the current value of the counter for a specific set of attributes.
90 : /// If no attributes are provided, returns the sum of all values across all attributes.
91 3 : T getValue([Attributes? attributes]) {
92 6 : return _storage.getValue(attributes);
93 : }
94 :
95 : /// Gets the current points for this counter.
96 : /// This is used by the SDK to collect metrics.
97 1 : List<MetricPoint<T>> collectPoints() {
98 2 : return _storage.collectPoints();
99 : }
100 :
101 1 : @override
102 : List<Metric> collectMetrics() {
103 2 : if (!isEnabled()) return [];
104 :
105 : // Get the points from storage
106 1 : final points = collectPoints();
107 :
108 1 : if (points.isEmpty) return [];
109 :
110 : // Create a metric with the collected points
111 1 : final metric = Metric(
112 1 : name: name,
113 1 : description: description,
114 1 : unit: unit,
115 : type: MetricType.sum,
116 2 : isMonotonic: _storage.isMonotonic,
117 : points: points,
118 : );
119 :
120 1 : return [metric];
121 : }
122 :
123 : /// Resets the counter. This is only used for Delta temporality.
124 2 : void reset() {
125 4 : _storage.reset();
126 : }
127 : }
|