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/histogram_storage.dart';
10 : import 'base_instrument.dart';
11 :
12 : /// Histogram is a synchronous instrument that records a distribution of values.
13 : ///
14 : /// A Histogram is used to measure a distribution of values, such as request durations,
15 : /// response sizes, or latencies.
16 : class Histogram<T extends num> implements APIHistogram<T>, SDKInstrument {
17 : /// The underlying API Histogram.
18 : final APIHistogram<T> _apiHistogram;
19 :
20 : /// The Meter that created this Histogram.
21 : final Meter _meter;
22 :
23 : /// Storage for accumulating histogram measurements.
24 : final HistogramStorage<T> _storage;
25 :
26 : /// Creates a new Histogram instance.
27 7 : Histogram({
28 : required APIHistogram<T> apiHistogram,
29 : required Meter meter,
30 : List<double>? boundaries,
31 : }) : _apiHistogram = apiHistogram,
32 : _meter = meter,
33 7 : _storage = HistogramStorage(
34 : boundaries: boundaries ?? _defaultBoundaries,
35 : recordMinMax: true,
36 14 : exemplarFilter: meter.provider.exemplarFilter,
37 : ) {
38 : // Register this instrument with the meter provider
39 35 : _meter.provider.registerInstrument(_meter.name, this);
40 : }
41 :
42 : /// Default bucket boundaries.
43 : static const List<double> _defaultBoundaries = [
44 : 0,
45 : 5,
46 : 10,
47 : 25,
48 : 50,
49 : 75,
50 : 100,
51 : 250,
52 : 500,
53 : 750,
54 : 1000,
55 : 2500,
56 : 5000,
57 : 7500,
58 : 10000,
59 : ];
60 :
61 7 : @override
62 14 : String get name => _apiHistogram.name;
63 :
64 3 : @override
65 6 : String? get unit => _apiHistogram.unit;
66 :
67 3 : @override
68 6 : String? get description => _apiHistogram.description;
69 :
70 4 : @override
71 8 : bool isEnabled() => _meter.isEnabled();
72 :
73 7 : @override
74 7 : APIMeter get meter => _meter;
75 :
76 1 : @override
77 2 : List<double>? get boundaries => _apiHistogram.boundaries;
78 :
79 1 : @override
80 : bool get isCounter => false;
81 :
82 1 : @override
83 : bool get isUpDownCounter => false;
84 :
85 1 : @override
86 : bool get isGauge => false;
87 :
88 1 : @override
89 : bool get isHistogram => true;
90 :
91 4 : @override
92 : void record(T value, [Attributes? attributes]) {
93 : // First use the API implementation (no-op by default)
94 8 : _apiHistogram.record(value, attributes);
95 :
96 : // Only record if enabled
97 4 : if (!isEnabled()) return;
98 :
99 : // Record the measurement in our storage
100 12 : _storage.record(value, attributes, Context.current);
101 : }
102 :
103 1 : @override
104 : void recordWithMap(T value, Map<String, Object> attributeMap) {
105 : // Just convert to Attributes and call record
106 : final attributes =
107 2 : attributeMap.isEmpty ? null : attributeMap.toAttributes();
108 1 : record(value, attributes);
109 : }
110 :
111 : /// Gets the current histogram value for the given attributes.
112 : /// If no attributes are provided, returns the histogram value for the null/empty attribute set.
113 2 : HistogramValue getValue([Attributes? attributes]) {
114 4 : return _storage.getValue(attributes);
115 : }
116 :
117 : /// Gets the current points for this histogram.
118 : /// This is used by the SDK to collect metrics.
119 3 : List<MetricPoint<HistogramValue>> collectPoints() {
120 6 : return _storage.collectPoints();
121 : }
122 :
123 3 : @override
124 : List<Metric> collectMetrics() {
125 4 : if (!isEnabled()) return [];
126 :
127 : // Get the points from storage
128 3 : final points = collectPoints();
129 :
130 3 : if (points.isEmpty) return [];
131 :
132 : // Create a metric with the collected points
133 3 : final metric = Metric(
134 3 : name: name,
135 3 : description: description,
136 3 : unit: unit,
137 : type: MetricType.histogram,
138 : points: points,
139 : );
140 :
141 3 : return [metric];
142 : }
143 :
144 : /// Resets the histogram. This is only used for Delta temporality.
145 1 : void reset() {
146 2 : _storage.reset();
147 : }
148 : }
|