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 = SumStorage<T>(isMonotonic: false);
26 :
27 : /// Creates a new UpDownCounter instance.
28 5 : UpDownCounter({required APIUpDownCounter<T> apiCounter, required Meter meter})
29 : : _apiCounter = apiCounter,
30 : _meter = meter {
31 : // Register this instrument with the meter provider
32 25 : _meter.provider.registerInstrument(_meter.name, this);
33 : }
34 :
35 5 : @override
36 10 : String get name => _apiCounter.name;
37 :
38 2 : @override
39 4 : String? get unit => _apiCounter.unit;
40 :
41 2 : @override
42 4 : String? get description => _apiCounter.description;
43 :
44 1 : @override
45 2 : bool get enabled => _meter.enabled;
46 :
47 5 : @override
48 5 : APIMeter get meter => _meter;
49 :
50 1 : @override
51 : bool get isCounter => false;
52 :
53 1 : @override
54 : bool get isUpDownCounter => true;
55 :
56 1 : @override
57 : bool get isGauge => false;
58 :
59 1 : @override
60 : bool get isHistogram => false;
61 :
62 3 : @override
63 : void add(T value, [Attributes? attributes]) {
64 : // First use the API implementation (no-op by default)
65 6 : _apiCounter.add(value, attributes);
66 :
67 : // In the SDK, we only check the meter's enabled state
68 6 : if (!_meter.enabled) return;
69 :
70 : // Record the measurement in our storage
71 6 : _storage.record(value, attributes);
72 : }
73 :
74 1 : @override
75 : void addWithMap(T value, Map<String, Object> attributeMap) {
76 : // Just convert to Attributes and call add
77 : final attributes =
78 2 : attributeMap.isEmpty ? null : attributeMap.toAttributes();
79 1 : add(value, attributes);
80 : }
81 :
82 : /// Gets the current value of the counter for a specific set of attributes.
83 : /// If no attributes are provided, returns the sum of all values across all attributes.
84 3 : T getValue([Attributes? attributes]) {
85 6 : return _storage.getValue(attributes);
86 : }
87 :
88 : /// Gets the current points for this counter.
89 : /// This is used by the SDK to collect metrics.
90 1 : List<MetricPoint<T>> collectPoints() {
91 2 : return _storage.collectPoints();
92 : }
93 :
94 1 : @override
95 : List<Metric> collectMetrics() {
96 2 : if (!enabled) return [];
97 :
98 : // Get the points from storage
99 1 : final points = collectPoints();
100 :
101 1 : if (points.isEmpty) return [];
102 :
103 : // Create a metric with the collected points
104 1 : final metric = Metric(
105 1 : name: name,
106 1 : description: description,
107 1 : unit: unit,
108 : type: MetricType.sum, // UpDownCounter is still a sum, just not monotonic
109 : points: points,
110 : );
111 :
112 1 : return [metric];
113 : }
114 :
115 : /// Resets the counter. This is only used for Delta temporality.
116 2 : void reset() {
117 4 : _storage.reset();
118 : }
119 : }
|