LCOV - code coverage report
Current view: top level - lib/src/metrics - meter.dart (source / functions) Coverage Total Hit
Test: lcov.info Lines: 97.1 % 174 169
Test Date: 2026-10-11 16:35:14 Functions: - 0 0

            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              : import 'package:meta/meta.dart';
       6              : 
       7              : import 'instruments/base_instrument.dart';
       8              : import 'instruments/counter.dart';
       9              : import 'instruments/gauge.dart';
      10              : import 'instruments/histogram.dart';
      11              : import 'instruments/observable_counter.dart';
      12              : import 'instruments/observable_gauge.dart';
      13              : import 'instruments/observable_up_down_counter.dart';
      14              : import 'instruments/up_down_counter.dart';
      15              : import 'meter_provider.dart';
      16              : 
      17              : part 'meter_create.dart';
      18              : 
      19              : /// SDK implementation of the APIMeter interface.
      20              : ///
      21              : /// A Meter is the entry point for creating instruments that collect measurements for a specific
      22              : /// instrumentation scope. Meters are obtained from a MeterProvider, and each Meter is associated
      23              : /// with a specific instrumentation library, version, and optional schema URL.
      24              : ///
      25              : /// The Meter follows the OpenTelemetry metrics data model which consists of instruments that
      26              : /// record measurements, which are then aggregated into metrics. This implementation delegates
      27              : /// to the API implementation while adding SDK-specific behaviors.
      28              : ///
      29              : /// More information:
      30              : /// https://opentelemetry.io/docs/specs/otel/metrics/api/
      31              : /// https://opentelemetry.io/docs/specs/otel/metrics/sdk/
      32              : class Meter implements APIMeter {
      33              :   /// The underlying API Meter implementation.
      34              :   final APIMeter _delegate;
      35              : 
      36              :   /// The MeterProvider that created this Meter.
      37              :   final MeterProvider _provider;
      38              : 
      39              :   /// Private constructor for creating Meter instances.
      40              :   ///
      41              :   /// @param delegate The API Meter implementation to delegate to
      42              :   /// @param provider The MeterProvider that created this Meter
      43           33 :   Meter._({required APIMeter delegate, 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           32 :   @override
      52           64 :   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            1 :   @override
      58            2 :   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            1 :   @override
      64            2 :   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            1 :   @override
      70            2 :   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           24 :   @override
      77           48 :   bool isEnabled() => _provider.enabled;
      78              : 
      79              :   /// Gets the MeterProvider that created this Meter.
      80              :   ///
      81              :   /// @return The MeterProvider instance
      82           62 :   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           18 :   @override
      98              :   APICounter<T> createCounter<T extends num>({
      99              :     required String name,
     100              :     String? unit,
     101              :     String? description,
     102              :     InstrumentAdvisory? advisory,
     103              :   }) {
     104              :     // First call the API implementation to get the API object
     105           36 :     final apiCounter = _delegate.createCounter<T>(
     106              :       name: name,
     107              :       unit: unit,
     108              :       description: description,
     109              :       advisory: advisory,
     110              :     );
     111              : 
     112              :     // Now wrap it with our SDK implementation
     113           18 :     return Counter<T>(apiCounter: apiCounter, meter: this);
     114              :   }
     115              : 
     116              :   /// Creates an UpDownCounter instrument for recording cumulative values that can increase or decrease.
     117              :   ///
     118              :   /// UpDownCounters are used to measure values that can go up or down over time. They are appropriate
     119              :   /// for values that represent a current state, such as active requests, queue size, or resource usage.
     120              :   ///
     121              :   /// @param name The name of the instrument, which should be unique within the meter
     122              :   /// @param unit Optional unit of measurement (e.g., "ms", "bytes", "requests")
     123              :   /// @param description Optional description of what the instrument measures
     124              :   /// @return An UpDownCounter instrument of the specified numeric type
     125              :   ///
     126              :   /// More information:
     127              :   /// https://opentelemetry.io/docs/specs/otel/metrics/api/#updowncounter
     128            6 :   @override
     129              :   APIUpDownCounter<T> createUpDownCounter<T extends num>({
     130              :     required String name,
     131              :     String? unit,
     132              :     String? description,
     133              :     InstrumentAdvisory? advisory,
     134              :   }) {
     135              :     // First call the API implementation to get the API object
     136           12 :     final apiCounter = _delegate.createUpDownCounter<T>(
     137              :       name: name,
     138              :       unit: unit,
     139              :       description: description,
     140              :       advisory: advisory,
     141              :     );
     142              : 
     143              :     // Now wrap it with our SDK implementation
     144            6 :     return UpDownCounter<T>(apiCounter: apiCounter, meter: this);
     145              :   }
     146              : 
     147              :   /// Creates a Histogram instrument for recording a distribution of values.
     148              :   ///
     149              :   /// Histograms are used to measure the distribution of values, such as request durations or
     150              :   /// response sizes. They provide statistics about the distribution, including count, sum,
     151              :   /// min, max, and quantiles.
     152              :   ///
     153              :   /// @param name The name of the instrument, which should be unique within the meter
     154              :   /// @param unit Optional unit of measurement (e.g., "ms", "bytes")
     155              :   /// @param description Optional description of what the instrument measures
     156              :   /// @param boundaries Deprecated: use `advisory.explicitBucketBoundaries`.
     157              :   ///   When both are given, [boundaries] wins so existing callers keep
     158              :   ///   their buckets.
     159              :   /// @param advisory Optional advisory parameters; the SDK honors
     160              :   ///   `explicitBucketBoundaries` for the bucket layout
     161              :   /// @return A Histogram instrument of the specified numeric type
     162              :   ///
     163              :   /// More information:
     164              :   /// https://opentelemetry.io/docs/specs/otel/metrics/api/#histogram
     165            8 :   @override
     166              :   APIHistogram<T> createHistogram<T extends num>({
     167              :     required String name,
     168              :     String? unit,
     169              :     String? description,
     170              :     @Deprecated(
     171              :         'Use advisory: InstrumentAdvisory(explicitBucketBoundaries: ...) instead')
     172              :     List<double>? boundaries,
     173              :     InstrumentAdvisory? advisory,
     174              :   }) {
     175              :     // First call the API implementation to get the API object. It merges
     176              :     // boundaries into the advisory, so the SDK Histogram reads the
     177              :     // effective boundaries from apiHistogram.advisory.
     178           16 :     final apiHistogram = _delegate.createHistogram<T>(
     179              :       name: name,
     180              :       unit: unit,
     181              :       description: description,
     182              :       // ignore: deprecated_member_use
     183              :       boundaries: boundaries,
     184              :       advisory: advisory,
     185              :     );
     186              : 
     187              :     // Now wrap it with our SDK implementation
     188            8 :     return Histogram<T>(apiHistogram: apiHistogram, meter: this);
     189              :   }
     190              : 
     191              :   /// Creates a Gauge instrument for recording the current value at the time of measurement.
     192              :   ///
     193              :   /// Gauges are used to measure the instantaneous value of something, such as the current
     194              :   /// CPU usage, memory usage, or temperature. They report the most recently observed value.
     195              :   ///
     196              :   /// @param name The name of the instrument, which should be unique within the meter
     197              :   /// @param unit Optional unit of measurement (e.g., "ms", "bytes", "percent")
     198              :   /// @param description Optional description of what the instrument measures
     199              :   /// @return A Gauge instrument of the specified numeric type
     200              :   ///
     201              :   /// More information:
     202              :   /// https://opentelemetry.io/docs/specs/otel/metrics/api/#gauge
     203            7 :   @override
     204              :   APIGauge<T> createGauge<T extends num>({
     205              :     required String name,
     206              :     String? unit,
     207              :     String? description,
     208              :     InstrumentAdvisory? advisory,
     209              :   }) {
     210              :     // First call the API implementation to get the API object
     211           14 :     final apiGauge = _delegate.createGauge<T>(
     212              :       name: name,
     213              :       unit: unit,
     214              :       description: description,
     215              :       advisory: advisory,
     216              :     );
     217              : 
     218              :     // Now wrap it with our SDK implementation
     219            7 :     return Gauge<T>(apiGauge: apiGauge, meter: this);
     220              :   }
     221              : 
     222              :   /// Creates an ObservableCounter instrument for asynchronously recording cumulative, monotonically increasing values.
     223              :   ///
     224              :   /// ObservableCounters are used when measurements are expensive to compute and should be
     225              :   /// collected only when needed, or when they come from an external source. They are appropriate
     226              :   /// for the same use cases as Counters, but with asynchronous collection.
     227              :   ///
     228              :   /// @param name The name of the instrument, which should be unique within the meter
     229              :   /// @param unit Optional unit of measurement (e.g., "ms", "bytes", "requests")
     230              :   /// @param description Optional description of what the instrument measures
     231              :   /// @param advisory Optional advisory parameters for the instrument
     232              :   /// @param callbacks Callback functions invoked when measurements are collected
     233              :   /// @param callback Deprecated: use [callbacks]; a [callback] is prepended to it
     234              :   /// @return An ObservableCounter instrument of the specified numeric type
     235              :   ///
     236              :   /// More information:
     237              :   /// https://opentelemetry.io/docs/specs/otel/metrics/api/#asynchronous-counter
     238           11 :   @override
     239              :   APIObservableCounter<T> createObservableCounter<T extends num>({
     240              :     required String name,
     241              :     String? unit,
     242              :     String? description,
     243              :     InstrumentAdvisory? advisory,
     244              :     List<ObservableCallback<T>> callbacks = const [],
     245              :     @Deprecated('Use callbacks instead') ObservableCallback<T>? callback,
     246              :   }) {
     247              :     // First call the API implementation to get the API object. It merges
     248              :     // the deprecated callback into callbacks.
     249           22 :     final apiCounter = _delegate.createObservableCounter<T>(
     250              :       name: name,
     251              :       unit: unit,
     252              :       description: description,
     253              :       advisory: advisory,
     254              :       callbacks: callbacks,
     255              :       // ignore: deprecated_member_use
     256              :       callback: callback,
     257              :     );
     258              : 
     259              :     // Now wrap it with our SDK implementation
     260           11 :     final counter = ObservableCounter<T>(apiCounter: apiCounter, meter: this);
     261              : 
     262              :     // Register the instrument with the meter provider
     263           22 :     _provider.registerInstrument(name, counter);
     264              : 
     265              :     return counter;
     266              :   }
     267              : 
     268              :   /// Creates an ObservableUpDownCounter instrument for asynchronously recording cumulative values that can increase or decrease.
     269              :   ///
     270              :   /// ObservableUpDownCounters are used when measurements are expensive to compute and should be
     271              :   /// collected only when needed, or when they come from an external source. They are appropriate
     272              :   /// for the same use cases as UpDownCounters, but with asynchronous collection.
     273              :   ///
     274              :   /// @param name The name of the instrument, which should be unique within the meter
     275              :   /// @param unit Optional unit of measurement (e.g., "ms", "bytes", "requests")
     276              :   /// @param description Optional description of what the instrument measures
     277              :   /// @param advisory Optional advisory parameters for the instrument
     278              :   /// @param callbacks Callback functions invoked when measurements are collected
     279              :   /// @param callback Deprecated: use [callbacks]; a [callback] is prepended to it
     280              :   /// @return An ObservableUpDownCounter instrument of the specified numeric type
     281              :   ///
     282              :   /// More information:
     283              :   /// https://opentelemetry.io/docs/specs/otel/metrics/api/#asynchronous-updowncounter
     284            8 :   @override
     285              :   APIObservableUpDownCounter<T> createObservableUpDownCounter<T extends num>({
     286              :     required String name,
     287              :     String? unit,
     288              :     String? description,
     289              :     InstrumentAdvisory? advisory,
     290              :     List<ObservableCallback<T>> callbacks = const [],
     291              :     @Deprecated('Use callbacks instead') ObservableCallback<T>? callback,
     292              :   }) {
     293              :     // First call the API implementation to get the API object. It merges
     294              :     // the deprecated callback into callbacks.
     295           16 :     final apiCounter = _delegate.createObservableUpDownCounter<T>(
     296              :       name: name,
     297              :       unit: unit,
     298              :       description: description,
     299              :       advisory: advisory,
     300              :       callbacks: callbacks,
     301              :       // ignore: deprecated_member_use
     302              :       callback: callback,
     303              :     );
     304              : 
     305              :     // Now wrap it with our SDK implementation
     306            8 :     final counter = ObservableUpDownCounter<T>(
     307              :       apiCounter: apiCounter,
     308              :       meter: this,
     309              :     );
     310              : 
     311              :     // Register the instrument with the meter provider
     312           16 :     _provider.registerInstrument(name, counter);
     313              : 
     314              :     return counter;
     315              :   }
     316              : 
     317              :   /// Creates an ObservableGauge instrument for asynchronously recording the current value at collection time.
     318              :   ///
     319              :   /// ObservableGauges are used when measurements are expensive to compute and should be
     320              :   /// collected only when needed, or when they come from an external source. They are appropriate
     321              :   /// for the same use cases as Gauges, but with asynchronous collection.
     322              :   ///
     323              :   /// @param name The name of the instrument, which should be unique within the meter
     324              :   /// @param unit Optional unit of measurement (e.g., "ms", "bytes", "percent")
     325              :   /// @param description Optional description of what the instrument measures
     326              :   /// @param advisory Optional advisory parameters for the instrument
     327              :   /// @param callbacks Callback functions invoked when measurements are collected
     328              :   /// @param callback Deprecated: use [callbacks]; a [callback] is prepended to it
     329              :   /// @return An ObservableGauge instrument of the specified numeric type
     330              :   ///
     331              :   /// More information:
     332              :   /// https://opentelemetry.io/docs/specs/otel/metrics/api/#asynchronous-gauge
     333            8 :   @override
     334              :   APIObservableGauge<T> createObservableGauge<T extends num>({
     335              :     required String name,
     336              :     String? unit,
     337              :     String? description,
     338              :     InstrumentAdvisory? advisory,
     339              :     List<ObservableCallback<T>> callbacks = const [],
     340              :     @Deprecated('Use callbacks instead') ObservableCallback<T>? callback,
     341              :   }) {
     342              :     // First call the API implementation to get the API object. It merges
     343              :     // the deprecated callback into callbacks.
     344           16 :     final apiGauge = _delegate.createObservableGauge<T>(
     345              :       name: name,
     346              :       unit: unit,
     347              :       description: description,
     348              :       advisory: advisory,
     349              :       callbacks: callbacks,
     350              :       // ignore: deprecated_member_use
     351              :       callback: callback,
     352              :     );
     353              : 
     354              :     // Now wrap it with our SDK implementation
     355            8 :     final gauge = ObservableGauge<T>(apiGauge: apiGauge, meter: this);
     356              : 
     357              :     // Register the instrument with the meter provider
     358           16 :     _provider.registerInstrument(name, gauge);
     359              : 
     360              :     return gauge;
     361              :   }
     362              : 
     363              :   /// Batch callbacks registered through [registerBatchCallback], run once
     364              :   /// per collection by [MeterProvider.collectAllMetrics].
     365              :   final List<_BatchCallbackRegistration> _batchCallbacks = [];
     366              : 
     367              :   /// Registers one callback that observes several of this meter's
     368              :   /// asynchronous instruments at once.
     369              :   ///
     370              :   /// Per metrics/api.md the instruments MUST all belong to this meter; an
     371              :   /// instrument from another meter, or one that is not an SDK asynchronous
     372              :   /// instrument, is reported through [OTelErrorHandling] and the callback is
     373              :   /// not registered. The returned registration's `unregister()` stops the
     374              :   /// callback from being invoked on later collections.
     375            1 :   @override
     376              :   APIBatchCallbackRegistration registerBatchCallback(
     377              :     BatchObservableCallback callback,
     378              :     Set<APIObservableInstrument> instruments,
     379              :   ) {
     380            2 :     for (final instrument in instruments) {
     381            1 :       if (!identical(instrument.meter, this) ||
     382            1 :           instrument is! SDKObservableInstrument) {
     383            3 :         OTelErrorHandling.report(ArgumentError(
     384            1 :           'registerBatchCallback: instrument "${instrument.name}" belongs '
     385              :           'to a different Meter; the callback was not registered.',
     386              :         ));
     387            1 :         return _NoopBatchCallbackRegistration();
     388              :       }
     389              :     }
     390            1 :     final registration = _BatchCallbackRegistration(
     391              :       meter: this,
     392              :       callback: callback,
     393            2 :       instruments: instruments.cast<SDKObservableInstrument>().toSet(),
     394              :     );
     395            2 :     _batchCallbacks.add(registration);
     396              :     return registration;
     397              :   }
     398              : 
     399              :   /// Invokes every registered batch callback once, queuing its observations
     400              :   /// on the instruments it covers for their next `collect()`.
     401              :   ///
     402              :   /// Called by [MeterProvider.collectAllMetrics] before the instruments
     403              :   /// collect. A callback that throws is reported and the rest still run.
     404           16 :   void runBatchCallbacks() {
     405           48 :     if (!isEnabled() || _batchCallbacks.isEmpty) return;
     406            3 :     for (final registration in List.of(_batchCallbacks)) {
     407            2 :       final result = _BatchObservableResult(registration.instruments);
     408              :       try {
     409            2 :         registration.callback(result);
     410              :       } catch (e, stackTrace) {
     411            1 :         OTelErrorHandling.report(e, stackTrace);
     412              :       }
     413              :     }
     414              :   }
     415              : }
     416              : 
     417              : /// A live registration for a batch callback on an SDK [Meter].
     418              : class _BatchCallbackRegistration implements APIBatchCallbackRegistration {
     419              :   final Meter meter;
     420              :   final BatchObservableCallback callback;
     421              :   final Set<SDKObservableInstrument> instruments;
     422              : 
     423            1 :   _BatchCallbackRegistration({
     424              :     required this.meter,
     425              :     required this.callback,
     426              :     required this.instruments,
     427              :   });
     428              : 
     429            1 :   @override
     430              :   void unregister() {
     431            3 :     meter._batchCallbacks.remove(this);
     432              :   }
     433              : }
     434              : 
     435              : /// Registration handed back when a batch callback was rejected or the meter
     436              : /// is a no-op; unregistering it does nothing.
     437              : class _NoopBatchCallbackRegistration implements APIBatchCallbackRegistration {
     438            1 :   @override
     439              :   void unregister() {}
     440              : }
     441              : 
     442              : /// The [BatchObservableResult] handed to a batch callback.
     443              : ///
     444              : /// An observation for an instrument the callback was not registered with is
     445              : /// dropped and reported, per metrics/api.md ("the callback SHOULD only
     446              : /// report observations for the instruments it was registered with").
     447              : class _BatchObservableResult implements BatchObservableResult {
     448              :   final Set<SDKObservableInstrument> _instruments;
     449              : 
     450            1 :   _BatchObservableResult(this._instruments);
     451              : 
     452            1 :   @override
     453              :   void observe(APIObservableInstrument instrument, num value,
     454              :       [Attributes? attributes]) {
     455            1 :     if (instrument is! SDKObservableInstrument ||
     456            2 :         !_instruments.contains(instrument)) {
     457            3 :       OTelErrorHandling.report(ArgumentError(
     458            1 :         'Batch callback observed instrument "${instrument.name}", which it '
     459              :         'was not registered with; the observation was dropped.',
     460              :       ));
     461              :       return;
     462              :     }
     463            1 :     instrument.observeFromBatch(value, attributes);
     464              :   }
     465              : }
     466              : 
     467              : /// A no-op implementation of Meter that doesn't record any metrics.
     468              : ///
     469              : /// This implementation is used when the MeterProvider has been shut down
     470              : /// or if metrics collection is disabled. It provides the same interface as
     471              : /// a regular Meter but does nothing when measurements are recorded.
     472              : ///
     473              : /// More information:
     474              : /// https://opentelemetry.io/docs/specs/otel/metrics/api/#no-op-implementations
     475              : class NoopMeter implements APIMeter {
     476              :   @override
     477              :   final String name;
     478              : 
     479              :   @override
     480              :   final String? version;
     481              : 
     482              :   @override
     483              :   final String? schemaUrl;
     484              : 
     485              :   @override
     486              :   final Attributes? attributes = null;
     487              : 
     488            1 :   @override
     489              :   bool isEnabled() => false;
     490              : 
     491              :   /// Creates a new NoopMeter with the specified name and optional version and schema URL.
     492              :   ///
     493              :   /// @param name The name of the instrumentation scope
     494              :   /// @param version Optional version of the instrumentation scope
     495              :   /// @param schemaUrl Optional URL of the schema defining the instrumentation scope
     496            4 :   NoopMeter({required this.name, this.version, this.schemaUrl});
     497              : 
     498            1 :   @override
     499              :   APICounter<T> createCounter<T extends num>({
     500              :     required String name,
     501              :     String? unit,
     502              :     String? description,
     503              :     InstrumentAdvisory? advisory,
     504              :   }) {
     505            1 :     return NoopCounter<T>(
     506              :       name: name,
     507              :       unit: unit,
     508              :       description: description,
     509              :       advisory: advisory,
     510              :     );
     511              :   }
     512              : 
     513            1 :   @override
     514              :   APIUpDownCounter<T> createUpDownCounter<T extends num>({
     515              :     required String name,
     516              :     String? unit,
     517              :     String? description,
     518              :     InstrumentAdvisory? advisory,
     519              :   }) {
     520            1 :     return NoopUpDownCounter<T>(
     521              :       name: name,
     522              :       unit: unit,
     523              :       description: description,
     524              :       advisory: advisory,
     525              :     );
     526              :   }
     527              : 
     528            2 :   @override
     529              :   APIHistogram<T> createHistogram<T extends num>({
     530              :     required String name,
     531              :     String? unit,
     532              :     String? description,
     533              :     @Deprecated(
     534              :         'Use advisory: InstrumentAdvisory(explicitBucketBoundaries: ...) instead')
     535              :     List<double>? boundaries,
     536              :     InstrumentAdvisory? advisory,
     537              :   }) {
     538            2 :     return NoopHistogram<T>(
     539              :       name: name,
     540              :       unit: unit,
     541              :       description: description,
     542              :       advisory: boundaries != null
     543            2 :           ? InstrumentAdvisory(
     544              :               explicitBucketBoundaries: boundaries,
     545            0 :               attributeKeys: advisory?.attributeKeys,
     546              :             )
     547              :           : advisory,
     548              :     );
     549              :   }
     550              : 
     551            1 :   @override
     552              :   APIGauge<T> createGauge<T extends num>({
     553              :     required String name,
     554              :     String? unit,
     555              :     String? description,
     556              :     InstrumentAdvisory? advisory,
     557              :   }) {
     558            1 :     return NoopGauge<T>(
     559              :       name: name,
     560              :       unit: unit,
     561              :       description: description,
     562              :       advisory: advisory,
     563              :     );
     564              :   }
     565              : 
     566            1 :   @override
     567              :   APIObservableCounter<T> createObservableCounter<T extends num>({
     568              :     required String name,
     569              :     String? unit,
     570              :     String? description,
     571              :     InstrumentAdvisory? advisory,
     572              :     List<ObservableCallback<T>> callbacks = const [],
     573              :     @Deprecated('Use callbacks instead') ObservableCallback<T>? callback,
     574              :   }) {
     575            1 :     return NoopObservableCounter<T>(
     576              :       name: name,
     577              :       unit: unit,
     578              :       description: description,
     579              :       advisory: advisory,
     580            2 :       callbacks: [if (callback != null) callback, ...callbacks],
     581              :     );
     582              :   }
     583              : 
     584            1 :   @override
     585              :   APIObservableUpDownCounter<T> createObservableUpDownCounter<T extends num>({
     586              :     required String name,
     587              :     String? unit,
     588              :     String? description,
     589              :     InstrumentAdvisory? advisory,
     590              :     List<ObservableCallback<T>> callbacks = const [],
     591              :     @Deprecated('Use callbacks instead') ObservableCallback<T>? callback,
     592              :   }) {
     593            1 :     return NoopObservableUpDownCounter<T>(
     594              :       name: name,
     595              :       unit: unit,
     596              :       description: description,
     597              :       advisory: advisory,
     598            2 :       callbacks: [if (callback != null) callback, ...callbacks],
     599              :     );
     600              :   }
     601              : 
     602            2 :   @override
     603              :   APIObservableGauge<T> createObservableGauge<T extends num>({
     604              :     required String name,
     605              :     String? unit,
     606              :     String? description,
     607              :     InstrumentAdvisory? advisory,
     608              :     List<ObservableCallback<T>> callbacks = const [],
     609              :     @Deprecated('Use callbacks instead') ObservableCallback<T>? callback,
     610              :   }) {
     611            2 :     return NoopObservableGauge<T>(
     612              :       name: name,
     613              :       unit: unit,
     614              :       description: description,
     615              :       advisory: advisory,
     616            4 :       callbacks: [if (callback != null) callback, ...callbacks],
     617              :     );
     618              :   }
     619              : 
     620            1 :   @override
     621              :   APIBatchCallbackRegistration registerBatchCallback(
     622              :     BatchObservableCallback callback,
     623              :     Set<APIObservableInstrument> instruments,
     624              :   ) {
     625            1 :     return _NoopBatchCallbackRegistration();
     626              :   }
     627              : }
     628              : 
     629              : /// No-op implementation of Counter instrument.
     630              : ///
     631              : /// This implementation conforms to the OpenTelemetry specification for no-op implementations,
     632              : /// maintaining the same interface as a functional Counter but performing no operations.
     633              : class NoopCounter<T extends num> implements APICounter<T> {
     634              :   @override
     635              :   final String name;
     636              : 
     637              :   @override
     638              :   final String? description;
     639              : 
     640              :   @override
     641              :   final String? unit;
     642              : 
     643            1 :   @override
     644              :   bool isEnabled() => false;
     645              : 
     646              :   @override
     647              :   final APIMeter meter;
     648              : 
     649              :   /// Creates a new NoopCounter with the specified name, unit, and description.
     650              :   ///
     651              :   /// @param name The name of the instrument
     652              :   /// @param unit Optional unit of measurement
     653              :   /// @param description Optional description of what the instrument measures
     654              :   @override
     655              :   final InstrumentAdvisory? advisory;
     656              : 
     657            1 :   NoopCounter({required this.name, this.unit, this.description, this.advisory})
     658            1 :       : meter = NoopMeter(name: 'noop-meter');
     659              : 
     660              :   /// Records a measurement (no-op implementation).
     661              :   ///
     662              :   /// @param value The measurement value (ignored)
     663              :   /// @param attributes Optional attributes to associate with the measurement (ignored)
     664            1 :   @override
     665              :   void add(T value, [Attributes? attributes]) {
     666              :     // No-op
     667              :   }
     668              : 
     669              :   /// Records a measurement with attributes as a map (no-op implementation).
     670              :   ///
     671              :   /// @param value The measurement value (ignored)
     672              :   /// @param attributeMap Map of attribute names to values (ignored)
     673            1 :   @override
     674              :   void addWithMap(T value, Map<String, Object> attributeMap) {
     675              :     // No-op
     676              :   }
     677              : 
     678            1 :   @override
     679              :   bool get isCounter => true;
     680              : 
     681            1 :   @override
     682              :   bool get isGauge => false;
     683              : 
     684            1 :   @override
     685              :   bool get isHistogram => false;
     686              : 
     687            1 :   @override
     688              :   bool get isUpDownCounter => false;
     689              : }
     690              : 
     691              : /// No-op implementation of UpDownCounter instrument.
     692              : ///
     693              : /// This implementation conforms to the OpenTelemetry specification for no-op implementations,
     694              : /// maintaining the same interface as a functional UpDownCounter but performing no operations.
     695              : class NoopUpDownCounter<T extends num> implements APIUpDownCounter<T> {
     696              :   @override
     697              :   final String name;
     698              : 
     699              :   @override
     700              :   final String? description;
     701              : 
     702              :   @override
     703              :   final String? unit;
     704              : 
     705            1 :   @override
     706              :   bool isEnabled() => false;
     707              : 
     708              :   @override
     709              :   final APIMeter meter;
     710              : 
     711              :   /// Creates a new NoopUpDownCounter with the specified name, unit, and description.
     712              :   ///
     713              :   /// @param name The name of the instrument
     714              :   /// @param unit Optional unit of measurement
     715              :   /// @param description Optional description of what the instrument measures
     716              :   @override
     717              :   final InstrumentAdvisory? advisory;
     718              : 
     719            1 :   NoopUpDownCounter(
     720              :       {required this.name, this.unit, this.description, this.advisory})
     721            1 :       : meter = NoopMeter(name: 'noop-meter');
     722              : 
     723              :   /// Records a measurement (no-op implementation).
     724              :   ///
     725              :   /// @param value The measurement value (ignored)
     726              :   /// @param attributes Optional attributes to associate with the measurement (ignored)
     727            1 :   @override
     728              :   void add(T value, [Attributes? attributes]) {
     729              :     // No-op
     730              :   }
     731              : 
     732              :   /// Records a measurement with attributes as a map (no-op implementation).
     733              :   ///
     734              :   /// @param value The measurement value (ignored)
     735              :   /// @param attributeMap Map of attribute names to values (ignored)
     736            1 :   @override
     737              :   void addWithMap(T value, Map<String, Object> attributeMap) {
     738              :     // No-op
     739              :   }
     740              : 
     741            1 :   @override
     742              :   bool get isCounter => false;
     743              : 
     744            1 :   @override
     745              :   bool get isGauge => false;
     746              : 
     747            1 :   @override
     748              :   bool get isHistogram => false;
     749              : 
     750            1 :   @override
     751              :   bool get isUpDownCounter => true;
     752              : }
     753              : 
     754              : /// No-op implementation of Histogram instrument.
     755              : ///
     756              : /// This implementation conforms to the OpenTelemetry specification for no-op implementations,
     757              : /// maintaining the same interface as a functional Histogram but performing no operations.
     758              : class NoopHistogram<T extends num> implements APIHistogram<T> {
     759              :   @override
     760              :   final String name;
     761              : 
     762              :   @override
     763              :   final String? description;
     764              : 
     765              :   @override
     766              :   final String? unit;
     767              : 
     768              :   @override
     769              :   final InstrumentAdvisory? advisory;
     770              : 
     771            0 :   @Deprecated('Use advisory?.explicitBucketBoundaries instead')
     772              :   @override
     773            0 :   List<double>? get boundaries => advisory?.explicitBucketBoundaries;
     774              : 
     775            1 :   @override
     776              :   bool isEnabled() => false;
     777              : 
     778              :   @override
     779              :   final APIMeter meter;
     780              : 
     781              :   /// Creates a new NoopHistogram with the specified name, unit, description, and advisory.
     782              :   ///
     783              :   /// @param name The name of the instrument
     784              :   /// @param unit Optional unit of measurement
     785              :   /// @param description Optional description of what the instrument measures
     786              :   /// @param advisory Optional advisory parameters, carrying any bucket boundaries
     787            2 :   NoopHistogram({
     788              :     required this.name,
     789              :     this.unit,
     790              :     this.description,
     791              :     this.advisory,
     792            2 :   }) : meter = NoopMeter(name: 'noop-meter');
     793              : 
     794              :   /// Records a measurement (no-op implementation).
     795              :   ///
     796              :   /// @param value The measurement value (ignored)
     797              :   /// @param attributes Optional attributes to associate with the measurement (ignored)
     798            1 :   @override
     799              :   void record(T value, [Attributes? attributes]) {
     800              :     // No-op
     801              :   }
     802              : 
     803              :   /// Records a measurement with attributes as a map (no-op implementation).
     804              :   ///
     805              :   /// @param value The measurement value (ignored)
     806              :   /// @param attributeMap Map of attribute names to values (ignored)
     807            1 :   @override
     808              :   void recordWithMap(T value, Map<String, Object> attributeMap) {
     809              :     // No-op
     810              :   }
     811              : 
     812            1 :   @override
     813              :   bool get isCounter => false;
     814              : 
     815            1 :   @override
     816              :   bool get isGauge => false;
     817              : 
     818            1 :   @override
     819              :   bool get isHistogram => true;
     820              : 
     821            1 :   @override
     822              :   bool get isUpDownCounter => false;
     823              : }
     824              : 
     825              : /// No-op implementation of Gauge instrument.
     826              : ///
     827              : /// This implementation conforms to the OpenTelemetry specification for no-op implementations,
     828              : /// maintaining the same interface as a functional Gauge but performing no operations.
     829              : class NoopGauge<T extends num> implements APIGauge<T> {
     830              :   @override
     831              :   final String name;
     832              : 
     833              :   @override
     834              :   final String? description;
     835              : 
     836              :   @override
     837              :   final String? unit;
     838              : 
     839            1 :   @override
     840              :   bool isEnabled() => false;
     841              : 
     842              :   @override
     843              :   final APIMeter meter;
     844              : 
     845              :   /// Creates a new NoopGauge with the specified name, unit, and description.
     846              :   ///
     847              :   /// @param name The name of the instrument
     848              :   /// @param unit Optional unit of measurement
     849              :   /// @param description Optional description of what the instrument measures
     850              :   @override
     851              :   final InstrumentAdvisory? advisory;
     852              : 
     853            1 :   NoopGauge({required this.name, this.unit, this.description, this.advisory})
     854            1 :       : meter = NoopMeter(name: 'noop-meter');
     855              : 
     856              :   /// Records a measurement (no-op implementation).
     857              :   ///
     858              :   /// @param value The measurement value (ignored)
     859              :   /// @param attributes Optional attributes to associate with the measurement (ignored)
     860            1 :   @override
     861              :   void record(T value, [Attributes? attributes]) {
     862              :     // No-op
     863              :   }
     864              : 
     865              :   /// Records a measurement with attributes as a map (no-op implementation).
     866              :   ///
     867              :   /// @param value The measurement value (ignored)
     868              :   /// @param attributeMap Map of attribute names to values (ignored)
     869            1 :   @override
     870              :   void recordWithMap(T value, Map<String, Object> attributeMap) {
     871              :     // No-op
     872              :   }
     873              : 
     874            1 :   @override
     875              :   bool get isCounter => false;
     876              : 
     877            1 :   @override
     878              :   bool get isGauge => true;
     879              : 
     880            1 :   @override
     881              :   bool get isHistogram => false;
     882              : 
     883            1 :   @override
     884              :   bool get isUpDownCounter => false;
     885              : }
     886              : 
     887              : /// No-op implementation of ObservableCounter instrument.
     888              : ///
     889              : /// This implementation conforms to the OpenTelemetry specification for no-op implementations,
     890              : /// maintaining the same interface as a functional ObservableCounter but performing no operations.
     891              : class NoopObservableCounter<T extends num> implements APIObservableCounter<T> {
     892              :   @override
     893              :   final String name;
     894              : 
     895              :   @override
     896              :   final String? description;
     897              : 
     898              :   @override
     899              :   final String? unit;
     900              : 
     901            1 :   @override
     902              :   bool isEnabled() => false;
     903              : 
     904              :   @override
     905              :   final APIMeter meter;
     906              : 
     907              :   @override
     908              :   final InstrumentAdvisory? advisory;
     909              : 
     910              :   final List<ObservableCallback<T>> _callbacks = [];
     911              : 
     912              :   /// Creates a new NoopObservableCounter with the specified name, unit, description, and callbacks.
     913              :   ///
     914              :   /// @param name The name of the instrument
     915              :   /// @param unit Optional unit of measurement
     916              :   /// @param description Optional description of what the instrument measures
     917              :   /// @param advisory Optional advisory parameters
     918              :   /// @param callbacks Callback functions that will be called when measurements are collected
     919            2 :   NoopObservableCounter({
     920              :     required this.name,
     921              :     this.unit,
     922              :     this.description,
     923              :     this.advisory,
     924              :     List<ObservableCallback<T>> callbacks = const [],
     925            2 :   }) : meter = NoopMeter(name: 'noop-meter') {
     926            2 :     for (final callback in callbacks) {
     927            0 :       addCallback(callback);
     928              :     }
     929              :   }
     930              : 
     931              :   /// Gets all registered callbacks.
     932              :   ///
     933              :   /// @return An unmodifiable list of registered callbacks
     934            1 :   @override
     935            2 :   List<ObservableCallback<T>> get callbacks => List.unmodifiable(_callbacks);
     936              : 
     937              :   /// Registers a callback function for collecting measurements.
     938              :   ///
     939              :   /// @param callback The callback function to register
     940              :   /// @return A registration object that can be used to unregister the callback
     941            1 :   @override
     942              :   APICallbackRegistration<T> addCallback(ObservableCallback<T> callback) {
     943            2 :     _callbacks.add(callback);
     944            1 :     return _NoopCallbackRegistration<T>(this, callback);
     945              :   }
     946              : 
     947              :   /// Unregisters a previously registered callback function.
     948              :   ///
     949              :   /// @param callback The callback function to unregister
     950            1 :   @override
     951              :   void removeCallback(ObservableCallback<T> callback) {
     952            2 :     _callbacks.remove(callback);
     953              :   }
     954              : 
     955              :   /// Collects measurements from all registered callbacks (no-op implementation).
     956              :   ///
     957              :   /// @return An empty list of measurements
     958            2 :   @override
     959              :   List<Measurement> collect() {
     960            2 :     return <Measurement>[];
     961              :   }
     962              : }
     963              : 
     964              : /// No-op implementation of ObservableUpDownCounter instrument.
     965              : ///
     966              : /// This implementation conforms to the OpenTelemetry specification for no-op implementations,
     967              : /// maintaining the same interface as a functional ObservableUpDownCounter but performing no operations.
     968              : class NoopObservableUpDownCounter<T extends num>
     969              :     implements APIObservableUpDownCounter<T> {
     970              :   @override
     971              :   final String name;
     972              : 
     973              :   @override
     974              :   final String? description;
     975              : 
     976              :   @override
     977              :   final String? unit;
     978              : 
     979            1 :   @override
     980              :   bool isEnabled() => false;
     981              : 
     982              :   @override
     983              :   final APIMeter meter;
     984              : 
     985              :   @override
     986              :   final InstrumentAdvisory? advisory;
     987              : 
     988              :   final List<ObservableCallback<T>> _callbacks = [];
     989              : 
     990              :   /// Creates a new NoopObservableUpDownCounter with the specified name, unit, description, and callbacks.
     991              :   ///
     992              :   /// @param name The name of the instrument
     993              :   /// @param unit Optional unit of measurement
     994              :   /// @param description Optional description of what the instrument measures
     995              :   /// @param advisory Optional advisory parameters
     996              :   /// @param callbacks Callback functions that will be called when measurements are collected
     997            2 :   NoopObservableUpDownCounter({
     998              :     required this.name,
     999              :     this.unit,
    1000              :     this.description,
    1001              :     this.advisory,
    1002              :     List<ObservableCallback<T>> callbacks = const [],
    1003            2 :   }) : meter = NoopMeter(name: 'noop-meter') {
    1004            2 :     for (final callback in callbacks) {
    1005            0 :       addCallback(callback);
    1006              :     }
    1007              :   }
    1008              : 
    1009              :   /// Gets all registered callbacks.
    1010              :   ///
    1011              :   /// @return An unmodifiable list of registered callbacks
    1012            1 :   @override
    1013            2 :   List<ObservableCallback<T>> get callbacks => List.unmodifiable(_callbacks);
    1014              : 
    1015              :   /// Registers a callback function for collecting measurements.
    1016              :   ///
    1017              :   /// @param callback The callback function to register
    1018              :   /// @return A registration object that can be used to unregister the callback
    1019            1 :   @override
    1020              :   APICallbackRegistration<T> addCallback(ObservableCallback<T> callback) {
    1021            2 :     _callbacks.add(callback);
    1022            1 :     return _NoopCallbackRegistration<T>(this, callback);
    1023              :   }
    1024              : 
    1025              :   /// Unregisters a previously registered callback function.
    1026              :   ///
    1027              :   /// @param callback The callback function to unregister
    1028            1 :   @override
    1029              :   void removeCallback(ObservableCallback<T> callback) {
    1030            2 :     _callbacks.remove(callback);
    1031              :   }
    1032              : 
    1033              :   /// Collects measurements from all registered callbacks (no-op implementation).
    1034              :   ///
    1035              :   /// @return An empty list of measurements
    1036            2 :   @override
    1037              :   List<Measurement> collect() {
    1038            2 :     return <Measurement>[];
    1039              :   }
    1040              : }
    1041              : 
    1042              : /// No-op implementation of ObservableGauge instrument.
    1043              : ///
    1044              : /// This implementation conforms to the OpenTelemetry specification for no-op implementations,
    1045              : /// maintaining the same interface as a functional ObservableGauge but performing no operations.
    1046              : class NoopObservableGauge<T extends num> implements APIObservableGauge<T> {
    1047              :   @override
    1048              :   final String name;
    1049              : 
    1050              :   @override
    1051              :   final String? description;
    1052              : 
    1053              :   @override
    1054              :   final String? unit;
    1055              : 
    1056            1 :   @override
    1057              :   bool isEnabled() => false;
    1058              : 
    1059              :   @override
    1060              :   final APIMeter meter;
    1061              : 
    1062              :   @override
    1063              :   final InstrumentAdvisory? advisory;
    1064              : 
    1065              :   final List<ObservableCallback<T>> _callbacks = [];
    1066              : 
    1067              :   /// Creates a new NoopObservableGauge with the specified name, unit, description, and callbacks.
    1068              :   ///
    1069              :   /// @param name The name of the instrument
    1070              :   /// @param unit Optional unit of measurement
    1071              :   /// @param description Optional description of what the instrument measures
    1072              :   /// @param advisory Optional advisory parameters
    1073              :   /// @param callbacks Callback functions that will be called when measurements are collected
    1074            3 :   NoopObservableGauge({
    1075              :     required this.name,
    1076              :     this.unit,
    1077              :     this.description,
    1078              :     this.advisory,
    1079              :     List<ObservableCallback<T>> callbacks = const [],
    1080            3 :   }) : meter = NoopMeter(name: 'noop-meter') {
    1081            4 :     for (final callback in callbacks) {
    1082            1 :       addCallback(callback);
    1083              :     }
    1084              :   }
    1085              : 
    1086              :   /// Gets all registered callbacks.
    1087              :   ///
    1088              :   /// @return An unmodifiable list of registered callbacks
    1089            2 :   @override
    1090            4 :   List<ObservableCallback<T>> get callbacks => List.unmodifiable(_callbacks);
    1091              : 
    1092              :   /// Registers a callback function for collecting measurements.
    1093              :   ///
    1094              :   /// @param callback The callback function to register
    1095              :   /// @return A registration object that can be used to unregister the callback
    1096            2 :   @override
    1097              :   APICallbackRegistration<T> addCallback(ObservableCallback<T> callback) {
    1098            4 :     _callbacks.add(callback);
    1099            2 :     return _NoopCallbackRegistration<T>(this, callback);
    1100              :   }
    1101              : 
    1102              :   /// Unregisters a previously registered callback function.
    1103              :   ///
    1104              :   /// @param callback The callback function to unregister
    1105            1 :   @override
    1106              :   void removeCallback(ObservableCallback<T> callback) {
    1107            2 :     _callbacks.remove(callback);
    1108              :   }
    1109              : 
    1110              :   /// Collects measurements from all registered callbacks (no-op implementation).
    1111              :   ///
    1112              :   /// @return An empty list of measurements
    1113            2 :   @override
    1114              :   List<Measurement> collect() {
    1115            2 :     return <Measurement>[];
    1116              :   }
    1117              : }
    1118              : 
    1119              : /// No-op implementation of callback registration for observable instruments.
    1120              : ///
    1121              : /// This implementation allows unregistering callbacks from no-op instruments.
    1122              : class _NoopCallbackRegistration<T extends num>
    1123              :     implements APICallbackRegistration<T> {
    1124              :   final dynamic _instrument;
    1125              :   final ObservableCallback<T> _callback;
    1126              : 
    1127              :   /// Creates a new NoopCallbackRegistration.
    1128              :   ///
    1129              :   /// @param instrument The instrument that owns the callback
    1130              :   /// @param callback The callback function to be unregistered
    1131            2 :   _NoopCallbackRegistration(this._instrument, this._callback);
    1132              : 
    1133              :   /// Unregisters the callback from the instrument.
    1134            1 :   @override
    1135              :   void unregister() {
    1136            2 :     if (_instrument is APIObservableCounter<T>) {
    1137            3 :       (_instrument as APIObservableCounter<T>).removeCallback(_callback);
    1138            2 :     } else if (_instrument is APIObservableUpDownCounter<T>) {
    1139            3 :       (_instrument as APIObservableUpDownCounter<T>).removeCallback(_callback);
    1140            2 :     } else if (_instrument is APIObservableGauge<T>) {
    1141            3 :       (_instrument as APIObservableGauge<T>).removeCallback(_callback);
    1142              :     }
    1143              :   }
    1144              : }
        

Generated by: LCOV version 2.0-1