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 'instruments/counter.dart';
7 : import 'instruments/gauge.dart';
8 : import 'instruments/histogram.dart';
9 : import 'instruments/observable_counter.dart';
10 : import 'instruments/observable_gauge.dart';
11 : import 'instruments/observable_up_down_counter.dart';
12 : import 'instruments/up_down_counter.dart';
13 : import 'meter_provider.dart';
14 :
15 : part 'meter_create.dart';
16 :
17 : /// SDK implementation of the APIMeter interface.
18 : ///
19 : /// A Meter is the entry point for creating instruments that collect measurements for a specific
20 : /// instrumentation scope. Meters are obtained from a MeterProvider, and each Meter is associated
21 : /// with a specific instrumentation library, version, and optional schema URL.
22 : ///
23 : /// The Meter follows the OpenTelemetry metrics data model which consists of instruments that
24 : /// record measurements, which are then aggregated into metrics. This implementation delegates
25 : /// to the API implementation while adding SDK-specific behaviors.
26 : ///
27 : /// More information:
28 : /// https://opentelemetry.io/docs/specs/otel/metrics/api/
29 : /// https://opentelemetry.io/docs/specs/otel/metrics/sdk/
30 : class Meter implements APIMeter {
31 : /// The underlying API Meter implementation.
32 : final APIMeter _delegate;
33 :
34 : /// The MeterProvider that created this Meter.
35 : final MeterProvider _provider;
36 :
37 : /// Private constructor for creating Meter instances.
38 : ///
39 : /// @param delegate The API Meter implementation to delegate to
40 : /// @param provider The MeterProvider that created this Meter
41 20 : Meter._({
42 : required APIMeter delegate,
43 : required MeterProvider provider,
44 : }) : _delegate = delegate,
45 : _provider = provider;
46 :
47 : /// Gets the name of the instrumentation scope.
48 : ///
49 : /// This name uniquely identifies the instrumentation library, such as
50 : /// the package, module, or class name.
51 19 : @override
52 38 : String get name => _delegate.name;
53 :
54 : /// Gets the version of the instrumentation scope.
55 : ///
56 : /// This represents the version of the instrumentation library.
57 0 : @override
58 0 : String? get version => _delegate.version;
59 :
60 : /// Gets the schema URL of the instrumentation scope.
61 : ///
62 : /// This URL identifies the schema that defines the instrumentation scope.
63 0 : @override
64 0 : String? get schemaUrl => _delegate.schemaUrl;
65 :
66 : /// Gets the attributes associated with this meter.
67 : ///
68 : /// These attributes provide additional context about the instrumentation scope.
69 0 : @override
70 0 : Attributes? get attributes => _delegate.attributes;
71 :
72 : /// Indicates whether this meter is enabled.
73 : ///
74 : /// If false, instruments created by this meter will not record measurements.
75 : /// This is controlled by the associated MeterProvider.
76 16 : @override
77 32 : bool get enabled => _provider.enabled;
78 :
79 : /// Gets the MeterProvider that created this Meter.
80 : ///
81 : /// @return The MeterProvider instance
82 34 : MeterProvider get provider => _provider;
83 :
84 : /// Creates a Counter instrument for recording cumulative, monotonically increasing values.
85 : ///
86 : /// Counters are used to measure a non-negative, monotonically increasing value. They only
87 : /// allow positive increments and are appropriate for values that never decrease, such as
88 : /// request counts, completed operations, or error counts.
89 : ///
90 : /// @param name The name of the instrument, which should be unique within the meter
91 : /// @param unit Optional unit of measurement (e.g., "ms", "bytes", "requests")
92 : /// @param description Optional description of what the instrument measures
93 : /// @return A Counter instrument of the specified numeric type
94 : ///
95 : /// More information:
96 : /// https://opentelemetry.io/docs/specs/otel/metrics/api/#counter
97 8 : @override
98 : APICounter<T> createCounter<T extends num>(
99 : {required String name, String? unit, String? description}) {
100 : // First call the API implementation to get the API object
101 16 : final apiCounter = _delegate.createCounter<T>(
102 : name: name, unit: unit, description: description);
103 :
104 : // Now wrap it with our SDK implementation
105 8 : return Counter<T>(
106 : apiCounter: apiCounter,
107 : meter: this,
108 : );
109 : }
110 :
111 : /// Creates an UpDownCounter instrument for recording cumulative values that can increase or decrease.
112 : ///
113 : /// UpDownCounters are used to measure values that can go up or down over time. They are appropriate
114 : /// for values that represent a current state, such as active requests, queue size, or resource usage.
115 : ///
116 : /// @param name The name of the instrument, which should be unique within the meter
117 : /// @param unit Optional unit of measurement (e.g., "ms", "bytes", "requests")
118 : /// @param description Optional description of what the instrument measures
119 : /// @return An UpDownCounter instrument of the specified numeric type
120 : ///
121 : /// More information:
122 : /// https://opentelemetry.io/docs/specs/otel/metrics/api/#updowncounter
123 4 : @override
124 : APIUpDownCounter<T> createUpDownCounter<T extends num>(
125 : {required String name, String? unit, String? description}) {
126 : // First call the API implementation to get the API object
127 8 : final apiCounter = _delegate.createUpDownCounter<T>(
128 : name: name, unit: unit, description: description);
129 :
130 : // Now wrap it with our SDK implementation
131 4 : return UpDownCounter<T>(
132 : apiCounter: apiCounter,
133 : meter: this,
134 : );
135 : }
136 :
137 : /// Creates a Histogram instrument for recording a distribution of values.
138 : ///
139 : /// Histograms are used to measure the distribution of values, such as request durations or
140 : /// response sizes. They provide statistics about the distribution, including count, sum,
141 : /// min, max, and quantiles.
142 : ///
143 : /// @param name The name of the instrument, which should be unique within the meter
144 : /// @param unit Optional unit of measurement (e.g., "ms", "bytes")
145 : /// @param description Optional description of what the instrument measures
146 : /// @param boundaries Optional explicit histogram bucket boundaries in increasing order
147 : /// @return A Histogram instrument of the specified numeric type
148 : ///
149 : /// More information:
150 : /// https://opentelemetry.io/docs/specs/otel/metrics/api/#histogram
151 4 : @override
152 : APIHistogram<T> createHistogram<T extends num>(
153 : {required String name,
154 : String? unit,
155 : String? description,
156 : List<double>? boundaries}) {
157 : // First call the API implementation to get the API object
158 8 : final apiHistogram = _delegate.createHistogram<T>(
159 : name: name,
160 : unit: unit,
161 : description: description,
162 : boundaries: boundaries);
163 :
164 : // Now wrap it with our SDK implementation
165 4 : return Histogram<T>(
166 : apiHistogram: apiHistogram,
167 : meter: this,
168 : boundaries: boundaries,
169 : );
170 : }
171 :
172 : /// Creates a Gauge instrument for recording the current value at the time of measurement.
173 : ///
174 : /// Gauges are used to measure the instantaneous value of something, such as the current
175 : /// CPU usage, memory usage, or temperature. They report the most recently observed value.
176 : ///
177 : /// @param name The name of the instrument, which should be unique within the meter
178 : /// @param unit Optional unit of measurement (e.g., "ms", "bytes", "percent")
179 : /// @param description Optional description of what the instrument measures
180 : /// @return A Gauge instrument of the specified numeric type
181 : ///
182 : /// More information:
183 : /// https://opentelemetry.io/docs/specs/otel/metrics/api/#gauge
184 4 : @override
185 : APIGauge<T> createGauge<T extends num>(
186 : {required String name, String? unit, String? description}) {
187 : // First call the API implementation to get the API object
188 8 : final apiGauge = _delegate.createGauge<T>(
189 : name: name, unit: unit, description: description);
190 :
191 : // Now wrap it with our SDK implementation
192 4 : return Gauge<T>(
193 : apiGauge: apiGauge,
194 : meter: this,
195 : );
196 : }
197 :
198 : /// Creates an ObservableCounter instrument for asynchronously recording cumulative, monotonically increasing values.
199 : ///
200 : /// ObservableCounters are used when measurements are expensive to compute and should be
201 : /// collected only when needed, or when they come from an external source. They are appropriate
202 : /// for the same use cases as Counters, but with asynchronous collection.
203 : ///
204 : /// @param name The name of the instrument, which should be unique within the meter
205 : /// @param unit Optional unit of measurement (e.g., "ms", "bytes", "requests")
206 : /// @param description Optional description of what the instrument measures
207 : /// @param callback Optional callback function that will be called when measurements are collected
208 : /// @return An ObservableCounter instrument of the specified numeric type
209 : ///
210 : /// More information:
211 : /// https://opentelemetry.io/docs/specs/otel/metrics/api/#asynchronous-counter
212 5 : @override
213 : APIObservableCounter<T> createObservableCounter<T extends num>(
214 : {required String name,
215 : String? unit,
216 : String? description,
217 : ObservableCallback<T>? callback}) {
218 : // First call the API implementation to get the API object
219 10 : final apiCounter = _delegate.createObservableCounter<T>(
220 : name: name,
221 : unit: unit,
222 : description: description,
223 : callback: callback,
224 : );
225 :
226 : // Now wrap it with our SDK implementation
227 5 : final counter = ObservableCounter<T>(
228 : apiCounter: apiCounter,
229 : meter: this,
230 : );
231 :
232 : // Register the instrument with the meter provider
233 10 : _provider.registerInstrument(name, counter);
234 :
235 : return counter;
236 : }
237 :
238 : /// Creates an ObservableUpDownCounter instrument for asynchronously recording cumulative values that can increase or decrease.
239 : ///
240 : /// ObservableUpDownCounters are used when measurements are expensive to compute and should be
241 : /// collected only when needed, or when they come from an external source. They are appropriate
242 : /// for the same use cases as UpDownCounters, but with asynchronous collection.
243 : ///
244 : /// @param name The name of the instrument, which should be unique within the meter
245 : /// @param unit Optional unit of measurement (e.g., "ms", "bytes", "requests")
246 : /// @param description Optional description of what the instrument measures
247 : /// @param callback Optional callback function that will be called when measurements are collected
248 : /// @return An ObservableUpDownCounter instrument of the specified numeric type
249 : ///
250 : /// More information:
251 : /// https://opentelemetry.io/docs/specs/otel/metrics/api/#asynchronous-updowncounter
252 3 : @override
253 : APIObservableUpDownCounter<T> createObservableUpDownCounter<T extends num>(
254 : {required String name,
255 : String? unit,
256 : String? description,
257 : ObservableCallback<T>? callback}) {
258 : // First call the API implementation to get the API object
259 6 : final apiCounter = _delegate.createObservableUpDownCounter<T>(
260 : name: name,
261 : unit: unit,
262 : description: description,
263 : callback: callback,
264 : );
265 :
266 : // Now wrap it with our SDK implementation
267 3 : final counter = ObservableUpDownCounter<T>(
268 : apiCounter: apiCounter,
269 : meter: this,
270 : );
271 :
272 : // Register the instrument with the meter provider
273 6 : _provider.registerInstrument(name, counter);
274 :
275 : return counter;
276 : }
277 :
278 : /// Creates an ObservableGauge instrument for asynchronously recording the current value at collection time.
279 : ///
280 : /// ObservableGauges are used when measurements are expensive to compute and should be
281 : /// collected only when needed, or when they come from an external source. They are appropriate
282 : /// for the same use cases as Gauges, but with asynchronous collection.
283 : ///
284 : /// @param name The name of the instrument, which should be unique within the meter
285 : /// @param unit Optional unit of measurement (e.g., "ms", "bytes", "percent")
286 : /// @param description Optional description of what the instrument measures
287 : /// @param callback Optional callback function that will be called when measurements are collected
288 : /// @return An ObservableGauge instrument of the specified numeric type
289 : ///
290 : /// More information:
291 : /// https://opentelemetry.io/docs/specs/otel/metrics/api/#asynchronous-gauge
292 3 : @override
293 : APIObservableGauge<T> createObservableGauge<T extends num>(
294 : {required String name,
295 : String? unit,
296 : String? description,
297 : ObservableCallback<T>? callback}) {
298 : // First call the API implementation to get the API object
299 6 : final apiGauge = _delegate.createObservableGauge<T>(
300 : name: name,
301 : unit: unit,
302 : description: description,
303 : callback: callback,
304 : );
305 :
306 : // Now wrap it with our SDK implementation
307 3 : final gauge = ObservableGauge<T>(
308 : apiGauge: apiGauge,
309 : meter: this,
310 : );
311 :
312 : // Register the instrument with the meter provider
313 6 : _provider.registerInstrument(name, gauge);
314 :
315 : return gauge;
316 : }
317 : }
318 :
319 : /// A no-op implementation of Meter that doesn't record any metrics.
320 : ///
321 : /// This implementation is used when the MeterProvider has been shut down
322 : /// or if metrics collection is disabled. It provides the same interface as
323 : /// a regular Meter but does nothing when measurements are recorded.
324 : ///
325 : /// More information:
326 : /// https://opentelemetry.io/docs/specs/otel/metrics/api/#no-op-implementations
327 : class NoopMeter implements APIMeter {
328 : @override
329 : final String name;
330 :
331 : @override
332 : final String? version;
333 :
334 : @override
335 : final String? schemaUrl;
336 :
337 : @override
338 : final Attributes? attributes = null;
339 :
340 : @override
341 : final bool enabled = false;
342 :
343 : /// Creates a new NoopMeter with the specified name and optional version and schema URL.
344 : ///
345 : /// @param name The name of the instrumentation scope
346 : /// @param version Optional version of the instrumentation scope
347 : /// @param schemaUrl Optional URL of the schema defining the instrumentation scope
348 2 : NoopMeter({
349 : required this.name,
350 : this.version,
351 : this.schemaUrl,
352 : });
353 :
354 1 : @override
355 : APICounter<T> createCounter<T extends num>(
356 : {required String name, String? unit, String? description}) {
357 1 : return NoopCounter<T>(name: name, unit: unit, description: description);
358 : }
359 :
360 1 : @override
361 : APIUpDownCounter<T> createUpDownCounter<T extends num>(
362 : {required String name, String? unit, String? description}) {
363 1 : return NoopUpDownCounter<T>(
364 : name: name, unit: unit, description: description);
365 : }
366 :
367 1 : @override
368 : APIHistogram<T> createHistogram<T extends num>(
369 : {required String name,
370 : String? unit,
371 : String? description,
372 : List<double>? boundaries}) {
373 1 : return NoopHistogram<T>(
374 : name: name,
375 : unit: unit,
376 : description: description,
377 : boundaries: boundaries);
378 : }
379 :
380 1 : @override
381 : APIGauge<T> createGauge<T extends num>(
382 : {required String name, String? unit, String? description}) {
383 1 : return NoopGauge<T>(name: name, unit: unit, description: description);
384 : }
385 :
386 1 : @override
387 : APIObservableCounter<T> createObservableCounter<T extends num>(
388 : {required String name,
389 : String? unit,
390 : String? description,
391 : ObservableCallback<T>? callback}) {
392 1 : return NoopObservableCounter<T>(
393 : name: name, unit: unit, description: description, callback: callback);
394 : }
395 :
396 1 : @override
397 : APIObservableUpDownCounter<T> createObservableUpDownCounter<T extends num>(
398 : {required String name,
399 : String? unit,
400 : String? description,
401 : ObservableCallback<T>? callback}) {
402 1 : return NoopObservableUpDownCounter<T>(
403 : name: name, unit: unit, description: description, callback: callback);
404 : }
405 :
406 1 : @override
407 : APIObservableGauge<T> createObservableGauge<T extends num>(
408 : {required String name,
409 : String? unit,
410 : String? description,
411 : ObservableCallback<T>? callback}) {
412 1 : return NoopObservableGauge<T>(
413 : name: name, unit: unit, description: description, callback: callback);
414 : }
415 : }
416 :
417 : /// No-op implementation of Counter instrument.
418 : ///
419 : /// This implementation conforms to the OpenTelemetry specification for no-op implementations,
420 : /// maintaining the same interface as a functional Counter but performing no operations.
421 : class NoopCounter<T extends num> implements APICounter<T> {
422 : @override
423 : final String name;
424 :
425 : @override
426 : final String? description;
427 :
428 : @override
429 : final String? unit;
430 :
431 : @override
432 : final bool enabled = false;
433 :
434 : @override
435 : final APIMeter meter;
436 :
437 : /// Creates a new NoopCounter with the specified name, unit, and description.
438 : ///
439 : /// @param name The name of the instrument
440 : /// @param unit Optional unit of measurement
441 : /// @param description Optional description of what the instrument measures
442 1 : NoopCounter({required this.name, this.unit, this.description})
443 1 : : meter = NoopMeter(name: 'noop-meter');
444 :
445 : /// Records a measurement (no-op implementation).
446 : ///
447 : /// @param value The measurement value (ignored)
448 : /// @param attributes Optional attributes to associate with the measurement (ignored)
449 1 : @override
450 : void add(T value, [Attributes? attributes]) {
451 : // No-op
452 : }
453 :
454 : /// Records a measurement with attributes as a map (no-op implementation).
455 : ///
456 : /// @param value The measurement value (ignored)
457 : /// @param attributeMap Map of attribute names to values (ignored)
458 1 : @override
459 : void addWithMap(T value, Map<String, Object> attributeMap) {
460 : // No-op
461 : }
462 :
463 1 : @override
464 : bool get isCounter => true;
465 :
466 1 : @override
467 : bool get isGauge => false;
468 :
469 1 : @override
470 : bool get isHistogram => false;
471 :
472 1 : @override
473 : bool get isUpDownCounter => false;
474 : }
475 :
476 : /// No-op implementation of UpDownCounter instrument.
477 : ///
478 : /// This implementation conforms to the OpenTelemetry specification for no-op implementations,
479 : /// maintaining the same interface as a functional UpDownCounter but performing no operations.
480 : class NoopUpDownCounter<T extends num> implements APIUpDownCounter<T> {
481 : @override
482 : final String name;
483 :
484 : @override
485 : final String? description;
486 :
487 : @override
488 : final String? unit;
489 :
490 : @override
491 : final bool enabled = false;
492 :
493 : @override
494 : final APIMeter meter;
495 :
496 : /// Creates a new NoopUpDownCounter with the specified name, unit, and description.
497 : ///
498 : /// @param name The name of the instrument
499 : /// @param unit Optional unit of measurement
500 : /// @param description Optional description of what the instrument measures
501 1 : NoopUpDownCounter({required this.name, this.unit, this.description})
502 1 : : meter = NoopMeter(name: 'noop-meter');
503 :
504 : /// Records a measurement (no-op implementation).
505 : ///
506 : /// @param value The measurement value (ignored)
507 : /// @param attributes Optional attributes to associate with the measurement (ignored)
508 1 : @override
509 : void add(T value, [Attributes? attributes]) {
510 : // No-op
511 : }
512 :
513 : /// Records a measurement with attributes as a map (no-op implementation).
514 : ///
515 : /// @param value The measurement value (ignored)
516 : /// @param attributeMap Map of attribute names to values (ignored)
517 1 : @override
518 : void addWithMap(T value, Map<String, Object> attributeMap) {
519 : // No-op
520 : }
521 :
522 1 : @override
523 : bool get isCounter => false;
524 :
525 1 : @override
526 : bool get isGauge => false;
527 :
528 1 : @override
529 : bool get isHistogram => false;
530 :
531 1 : @override
532 : bool get isUpDownCounter => true;
533 : }
534 :
535 : /// No-op implementation of Histogram instrument.
536 : ///
537 : /// This implementation conforms to the OpenTelemetry specification for no-op implementations,
538 : /// maintaining the same interface as a functional Histogram but performing no operations.
539 : class NoopHistogram<T extends num> implements APIHistogram<T> {
540 : @override
541 : final String name;
542 :
543 : @override
544 : final String? description;
545 :
546 : @override
547 : final String? unit;
548 :
549 : @override
550 : final List<double>? boundaries;
551 :
552 : @override
553 : final bool enabled = false;
554 :
555 : @override
556 : final APIMeter meter;
557 :
558 : /// Creates a new NoopHistogram with the specified name, unit, description, and boundaries.
559 : ///
560 : /// @param name The name of the instrument
561 : /// @param unit Optional unit of measurement
562 : /// @param description Optional description of what the instrument measures
563 : /// @param boundaries Optional explicit histogram bucket boundaries
564 1 : NoopHistogram(
565 : {required this.name, this.unit, this.description, this.boundaries})
566 1 : : meter = NoopMeter(name: 'noop-meter');
567 :
568 : /// Records a measurement (no-op implementation).
569 : ///
570 : /// @param value The measurement value (ignored)
571 : /// @param attributes Optional attributes to associate with the measurement (ignored)
572 1 : @override
573 : void record(T value, [Attributes? attributes]) {
574 : // No-op
575 : }
576 :
577 : /// Records a measurement with attributes as a map (no-op implementation).
578 : ///
579 : /// @param value The measurement value (ignored)
580 : /// @param attributeMap Map of attribute names to values (ignored)
581 1 : @override
582 : void recordWithMap(T value, Map<String, Object> attributeMap) {
583 : // No-op
584 : }
585 :
586 1 : @override
587 : bool get isCounter => false;
588 :
589 1 : @override
590 : bool get isGauge => false;
591 :
592 1 : @override
593 : bool get isHistogram => true;
594 :
595 1 : @override
596 : bool get isUpDownCounter => false;
597 : }
598 :
599 : /// No-op implementation of Gauge instrument.
600 : ///
601 : /// This implementation conforms to the OpenTelemetry specification for no-op implementations,
602 : /// maintaining the same interface as a functional Gauge but performing no operations.
603 : class NoopGauge<T extends num> implements APIGauge<T> {
604 : @override
605 : final String name;
606 :
607 : @override
608 : final String? description;
609 :
610 : @override
611 : final String? unit;
612 :
613 : @override
614 : final bool enabled = false;
615 :
616 : @override
617 : final APIMeter meter;
618 :
619 : /// Creates a new NoopGauge with the specified name, unit, and description.
620 : ///
621 : /// @param name The name of the instrument
622 : /// @param unit Optional unit of measurement
623 : /// @param description Optional description of what the instrument measures
624 1 : NoopGauge({required this.name, this.unit, this.description})
625 1 : : meter = NoopMeter(name: 'noop-meter');
626 :
627 : /// Records a measurement (no-op implementation).
628 : ///
629 : /// @param value The measurement value (ignored)
630 : /// @param attributes Optional attributes to associate with the measurement (ignored)
631 1 : @override
632 : void record(T value, [Attributes? attributes]) {
633 : // No-op
634 : }
635 :
636 : /// Records a measurement with attributes as a map (no-op implementation).
637 : ///
638 : /// @param value The measurement value (ignored)
639 : /// @param attributeMap Map of attribute names to values (ignored)
640 1 : @override
641 : void recordWithMap(T value, Map<String, Object> attributeMap) {
642 : // No-op
643 : }
644 :
645 1 : @override
646 : bool get isCounter => false;
647 :
648 1 : @override
649 : bool get isGauge => true;
650 :
651 1 : @override
652 : bool get isHistogram => false;
653 :
654 1 : @override
655 : bool get isUpDownCounter => false;
656 : }
657 :
658 : /// No-op implementation of ObservableCounter instrument.
659 : ///
660 : /// This implementation conforms to the OpenTelemetry specification for no-op implementations,
661 : /// maintaining the same interface as a functional ObservableCounter but performing no operations.
662 : class NoopObservableCounter<T extends num> implements APIObservableCounter<T> {
663 : @override
664 : final String name;
665 :
666 : @override
667 : final String? description;
668 :
669 : @override
670 : final String? unit;
671 :
672 : @override
673 : final bool enabled = false;
674 :
675 : @override
676 : final APIMeter meter;
677 :
678 : final List<ObservableCallback<T>> _callbacks = [];
679 :
680 : /// Creates a new NoopObservableCounter with the specified name, unit, description, and callback.
681 : ///
682 : /// @param name The name of the instrument
683 : /// @param unit Optional unit of measurement
684 : /// @param description Optional description of what the instrument measures
685 : /// @param callback Optional callback function that will be called when measurements are collected
686 1 : NoopObservableCounter(
687 : {required this.name,
688 : this.unit,
689 : this.description,
690 : ObservableCallback<T>? callback})
691 1 : : meter = NoopMeter(name: 'noop-meter') {
692 : if (callback != null) {
693 0 : addCallback(callback);
694 : }
695 : }
696 :
697 : /// Gets all registered callbacks.
698 : ///
699 : /// @return An unmodifiable list of registered callbacks
700 1 : @override
701 2 : List<ObservableCallback<T>> get callbacks => List.unmodifiable(_callbacks);
702 :
703 : /// Registers a callback function for collecting measurements.
704 : ///
705 : /// @param callback The callback function to register
706 : /// @return A registration object that can be used to unregister the callback
707 1 : @override
708 : APICallbackRegistration<T> addCallback(ObservableCallback<T> callback) {
709 2 : _callbacks.add(callback);
710 1 : return _NoopCallbackRegistration<T>(this, callback);
711 : }
712 :
713 : /// Unregisters a previously registered callback function.
714 : ///
715 : /// @param callback The callback function to unregister
716 1 : @override
717 : void removeCallback(ObservableCallback<T> callback) {
718 2 : _callbacks.remove(callback);
719 : }
720 :
721 : /// Collects measurements from all registered callbacks (no-op implementation).
722 : ///
723 : /// @return An empty list of measurements
724 1 : @override
725 : List<Measurement> collect() {
726 1 : return <Measurement>[];
727 : }
728 : }
729 :
730 : /// No-op implementation of ObservableUpDownCounter instrument.
731 : ///
732 : /// This implementation conforms to the OpenTelemetry specification for no-op implementations,
733 : /// maintaining the same interface as a functional ObservableUpDownCounter but performing no operations.
734 : class NoopObservableUpDownCounter<T extends num>
735 : implements APIObservableUpDownCounter<T> {
736 : @override
737 : final String name;
738 :
739 : @override
740 : final String? description;
741 :
742 : @override
743 : final String? unit;
744 :
745 : @override
746 : final bool enabled = false;
747 :
748 : @override
749 : final APIMeter meter;
750 :
751 : final List<ObservableCallback<T>> _callbacks = [];
752 :
753 : /// Creates a new NoopObservableUpDownCounter with the specified name, unit, description, and callback.
754 : ///
755 : /// @param name The name of the instrument
756 : /// @param unit Optional unit of measurement
757 : /// @param description Optional description of what the instrument measures
758 : /// @param callback Optional callback function that will be called when measurements are collected
759 1 : NoopObservableUpDownCounter(
760 : {required this.name,
761 : this.unit,
762 : this.description,
763 : ObservableCallback<T>? callback})
764 1 : : meter = NoopMeter(name: 'noop-meter') {
765 : if (callback != null) {
766 0 : addCallback(callback);
767 : }
768 : }
769 :
770 : /// Gets all registered callbacks.
771 : ///
772 : /// @return An unmodifiable list of registered callbacks
773 1 : @override
774 2 : List<ObservableCallback<T>> get callbacks => List.unmodifiable(_callbacks);
775 :
776 : /// Registers a callback function for collecting measurements.
777 : ///
778 : /// @param callback The callback function to register
779 : /// @return A registration object that can be used to unregister the callback
780 1 : @override
781 : APICallbackRegistration<T> addCallback(ObservableCallback<T> callback) {
782 2 : _callbacks.add(callback);
783 1 : return _NoopCallbackRegistration<T>(this, callback);
784 : }
785 :
786 : /// Unregisters a previously registered callback function.
787 : ///
788 : /// @param callback The callback function to unregister
789 1 : @override
790 : void removeCallback(ObservableCallback<T> callback) {
791 2 : _callbacks.remove(callback);
792 : }
793 :
794 : /// Collects measurements from all registered callbacks (no-op implementation).
795 : ///
796 : /// @return An empty list of measurements
797 1 : @override
798 : List<Measurement> collect() {
799 1 : return <Measurement>[];
800 : }
801 : }
802 :
803 : /// No-op implementation of ObservableGauge instrument.
804 : ///
805 : /// This implementation conforms to the OpenTelemetry specification for no-op implementations,
806 : /// maintaining the same interface as a functional ObservableGauge but performing no operations.
807 : class NoopObservableGauge<T extends num> implements APIObservableGauge<T> {
808 : @override
809 : final String name;
810 :
811 : @override
812 : final String? description;
813 :
814 : @override
815 : final String? unit;
816 :
817 : @override
818 : final bool enabled = false;
819 :
820 : @override
821 : final APIMeter meter;
822 :
823 : final List<ObservableCallback<T>> _callbacks = [];
824 :
825 : /// Creates a new NoopObservableGauge with the specified name, unit, description, and callback.
826 : ///
827 : /// @param name The name of the instrument
828 : /// @param unit Optional unit of measurement
829 : /// @param description Optional description of what the instrument measures
830 : /// @param callback Optional callback function that will be called when measurements are collected
831 1 : NoopObservableGauge(
832 : {required this.name,
833 : this.unit,
834 : this.description,
835 : ObservableCallback<T>? callback})
836 1 : : meter = NoopMeter(name: 'noop-meter') {
837 : if (callback != null) {
838 0 : addCallback(callback);
839 : }
840 : }
841 :
842 : /// Gets all registered callbacks.
843 : ///
844 : /// @return An unmodifiable list of registered callbacks
845 1 : @override
846 2 : List<ObservableCallback<T>> get callbacks => List.unmodifiable(_callbacks);
847 :
848 : /// Registers a callback function for collecting measurements.
849 : ///
850 : /// @param callback The callback function to register
851 : /// @return A registration object that can be used to unregister the callback
852 1 : @override
853 : APICallbackRegistration<T> addCallback(ObservableCallback<T> callback) {
854 2 : _callbacks.add(callback);
855 1 : return _NoopCallbackRegistration<T>(this, callback);
856 : }
857 :
858 : /// Unregisters a previously registered callback function.
859 : ///
860 : /// @param callback The callback function to unregister
861 1 : @override
862 : void removeCallback(ObservableCallback<T> callback) {
863 2 : _callbacks.remove(callback);
864 : }
865 :
866 : /// Collects measurements from all registered callbacks (no-op implementation).
867 : ///
868 : /// @return An empty list of measurements
869 1 : @override
870 : List<Measurement> collect() {
871 1 : return <Measurement>[];
872 : }
873 : }
874 :
875 : /// No-op implementation of callback registration for observable instruments.
876 : ///
877 : /// This implementation allows unregistering callbacks from no-op instruments.
878 : class _NoopCallbackRegistration<T extends num>
879 : implements APICallbackRegistration<T> {
880 : final dynamic _instrument;
881 : final ObservableCallback<T> _callback;
882 :
883 : /// Creates a new NoopCallbackRegistration.
884 : ///
885 : /// @param instrument The instrument that owns the callback
886 : /// @param callback The callback function to be unregistered
887 1 : _NoopCallbackRegistration(this._instrument, this._callback);
888 :
889 : /// Unregisters the callback from the instrument.
890 1 : @override
891 : void unregister() {
892 2 : if (_instrument is APIObservableCounter<T>) {
893 3 : (_instrument as APIObservableCounter<T>).removeCallback(_callback);
894 2 : } else if (_instrument is APIObservableUpDownCounter<T>) {
895 3 : (_instrument as APIObservableUpDownCounter<T>).removeCallback(_callback);
896 2 : } else if (_instrument is APIObservableGauge<T>) {
897 3 : (_instrument as APIObservableGauge<T>).removeCallback(_callback);
898 : }
899 : }
900 : }
|