Line data Source code
1 : // Licensed under the Apache License, Version 2.0
2 : // Copyright 2025, Michael Bushe, All rights reserved.
3 :
4 : import 'package:dartastic_opentelemetry_api/dartastic_opentelemetry_api.dart';
5 :
6 : import 'exemplar.dart';
7 :
8 : /// Represents a metric data point, which consists of a value or set of values,
9 : /// a set of attributes, and possibly exemplars.
10 : ///
11 : /// The type of value depends on the instrument type:
12 : class MetricPoint<T> {
13 : /// The set of attributes associated with this metric point.
14 : final Attributes attributes;
15 :
16 : /// The start timestamp for this data point.
17 : final DateTime startTime;
18 :
19 : /// The end timestamp for this data point.
20 : final DateTime endTime;
21 :
22 : /// The value of the metric point. The type depends on the instrument type:
23 : /// - For counters: A single sum value as a [num]
24 : /// - For histograms: A [HistogramValue] object
25 : final T value;
26 :
27 : /// Optional exemplars for this data point.
28 : final List<Exemplar>? exemplars;
29 :
30 : /// Creates a new MetricPoint.
31 19 : MetricPoint({
32 : required this.attributes,
33 : required this.startTime,
34 : required this.endTime,
35 : required this.value,
36 : this.exemplars,
37 : });
38 :
39 : /// Creates a sum data point.
40 11 : factory MetricPoint.sum({
41 : required Attributes attributes,
42 : required DateTime startTime,
43 : required DateTime time,
44 : required T value,
45 : bool isMonotonic = true,
46 : List<Exemplar>? exemplars,
47 : }) {
48 11 : return MetricPoint(
49 : attributes: attributes,
50 : startTime: startTime,
51 : endTime: time,
52 : value: value,
53 : exemplars: exemplars,
54 : );
55 : }
56 :
57 : /// Creates a gauge data point.
58 7 : factory MetricPoint.gauge({
59 : required Attributes attributes,
60 : required DateTime startTime,
61 : required DateTime time,
62 : required T value,
63 : List<Exemplar>? exemplars,
64 : }) {
65 7 : return MetricPoint(
66 : attributes: attributes,
67 : startTime: startTime,
68 : endTime: time,
69 : value: value,
70 : exemplars: exemplars,
71 : );
72 : }
73 :
74 : /// Creates a histogram data point.
75 0 : factory MetricPoint.histogram({
76 : required Attributes attributes,
77 : required DateTime startTime,
78 : required DateTime time,
79 : required int count,
80 : required T sum,
81 : required List<int> counts,
82 : required List<double> boundaries,
83 : T? min,
84 : T? max,
85 : List<Exemplar>? exemplars,
86 : }) {
87 0 : return MetricPoint(
88 : attributes: attributes,
89 : startTime: startTime,
90 : endTime: time,
91 0 : value: HistogramValue(
92 0 : sum: (sum is num) ? sum : num.tryParse(sum.toString()) ?? 0.0,
93 : count: count,
94 : boundaries: boundaries,
95 : bucketCounts: counts,
96 0 : min: min is num
97 : ? min
98 : : min != null
99 0 : ? num.tryParse(min.toString())
100 : : null,
101 0 : max: max is num
102 : ? max
103 : : max != null
104 0 : ? num.tryParse(max.toString())
105 : : null,
106 : ) as T,
107 : exemplars: exemplars,
108 : );
109 : }
110 :
111 : /// Checks if this point has exemplars.
112 6 : bool get hasExemplars => exemplars != null && exemplars!.isNotEmpty;
113 :
114 : /// Creates a string representation of the value.
115 1 : String get valueAsString {
116 2 : if (value is HistogramValue) {
117 1 : final histValue = value as HistogramValue;
118 3 : return 'Histogram(sum: ${histValue.sum}, count: ${histValue.count})';
119 : } else {
120 2 : return value.toString();
121 : }
122 : }
123 :
124 : /// Gets this point as a histogram value. Will throw if this is not a histogram point.
125 4 : HistogramValue histogram() {
126 8 : if (value is! HistogramValue) {
127 0 : throw StateError('This is not a histogram point');
128 : }
129 4 : return value as HistogramValue;
130 : }
131 : }
132 :
133 : /// Represents the value of a histogram metric point.
134 : class HistogramValue {
135 : /// The sum of all recorded values.
136 : final num sum;
137 :
138 : /// The count of all recorded values.
139 : final int count;
140 :
141 : /// The bucket boundaries.
142 : final List<double> boundaries;
143 :
144 : /// The counts in each bucket.
145 : final List<int> bucketCounts;
146 :
147 : /// The minimum recorded value (optional).
148 : final num? min;
149 :
150 : /// The maximum recorded value (optional).
151 : final num? max;
152 :
153 : /// Creates a new HistogramValue.
154 7 : HistogramValue({
155 : required this.sum,
156 : required this.count,
157 : required this.boundaries,
158 : required this.bucketCounts,
159 : this.min,
160 : this.max,
161 : });
162 : }
|