LCOV - code coverage report
Current view: top level - src/trace - tracer_provider.dart (source / functions) Coverage Total Hit
Test: lcov.info Lines: 95.5 % 111 106
Test Date: 2025-11-15 13:23:01 Functions: - 0 0

            Line data    Source code
       1              : // Licensed under the Apache License, Version 2.0
       2              : // Copyright 2025, Michael Bushe, All rights reserved.
       3              : 
       4              : library;
       5              : 
       6              : import 'package:dartastic_opentelemetry_api/dartastic_opentelemetry_api.dart';
       7              : 
       8              : import '../../dartastic_opentelemetry.dart';
       9              : 
      10              : part 'tracer_provider_create.dart';
      11              : 
      12              : /// SDK implementation of the APITracerProvider interface.
      13              : ///
      14              : /// The TracerProvider is the entry point to the tracing API. It is responsible
      15              : /// for creating and managing Tracers, as well as configuring the tracing
      16              : /// pipeline via SpanProcessors and Exporters.
      17              : ///
      18              : /// This implementation delegates some functionality to the API TracerProvider
      19              : /// implementation while adding SDK-specific behaviors like span processor management
      20              : /// and resource association.
      21              : ///
      22              : /// Note: Per [OTEP 0265](https://opentelemetry.io/docs/specs/semconv/general/events/),
      23              : /// span events are being deprecated and will be replaced by the Logging API in future versions.
      24              : ///
      25              : /// More information:
      26              : /// https://opentelemetry.io/docs/specs/otel/trace/sdk/
      27              : class TracerProvider implements APITracerProvider {
      28              :   /// Registry of tracers managed by this provider.
      29              :   final Map<String, Tracer> _tracers = {};
      30              : 
      31              :   /// Span processors registered with this provider.
      32              :   final List<SpanProcessor> _spanProcessors = [];
      33              : 
      34              :   /// The underlying API TracerProvider implementation.
      35              :   final APITracerProvider _delegate;
      36              : 
      37              :   /// The resource associated with this provider.
      38              :   Resource? resource;
      39              : 
      40              :   /// The default sampler to use for new tracers.
      41              :   Sampler? sampler;
      42              : 
      43           73 :   @override
      44          146 :   bool get isShutdown => _delegate.isShutdown;
      45              : 
      46           72 :   @override
      47              :   set isShutdown(bool value) {
      48          144 :     _delegate.isShutdown = value;
      49              :   }
      50              : 
      51              :   /// Private constructor for creating TracerProvider instances.
      52              :   ///
      53              :   /// @param delegate The API TracerProvider implementation to delegate to
      54              :   /// @param resource Optional Resource describing the entity producing telemetry
      55              :   /// @param sampler Optional default sampler for tracers created by this provider
      56           73 :   TracerProvider._({
      57              :     required APITracerProvider delegate,
      58              :     this.resource,
      59              :     Sampler? sampler,
      60              :   }) : _delegate = delegate {
      61           73 :     if (OTelLog.isDebug()) {
      62           73 :       OTelLog.debug(
      63          146 :           'TracerProvider: Created with resource: $resource, sampler: $sampler');
      64           73 :       if (resource != null) {
      65            0 :         OTelLog.debug('Resource attributes:');
      66            0 :         resource!.attributes.toList().forEach((attr) {
      67            0 :           OTelLog.debug('  ${attr.key}: ${attr.value}');
      68              :         });
      69              :       }
      70              :     }
      71              :   }
      72              : 
      73           72 :   @override
      74              :   Future<bool> shutdown() async {
      75           72 :     if (OTelLog.isDebug()) {
      76           71 :       OTelLog.debug(
      77          213 :           'TracerProvider: Shutting down with ${_spanProcessors.length} processors');
      78              :     }
      79           72 :     if (OTelLog.isDebug()) {
      80           71 :       OTelLog.debug(
      81          213 :           'TracerProvider: Shutting down with ${_spanProcessors.length} processors');
      82              :     }
      83              : 
      84           72 :     if (!isShutdown) {
      85              :       // Shutdown all span processors
      86          144 :       for (final processor in _spanProcessors) {
      87           72 :         if (OTelLog.isDebug()) {
      88           71 :           OTelLog.debug(
      89          142 :               'TracerProvider: Shutting down processor ${processor.runtimeType}');
      90              :         }
      91           72 :         if (OTelLog.isDebug()) {
      92           71 :           OTelLog.debug(
      93          142 :               'SDKTracerProvider: Shutting down processor ${processor.runtimeType}');
      94              :         }
      95              :         try {
      96           72 :           await processor.shutdown();
      97           72 :           if (OTelLog.isDebug()) {
      98           71 :             OTelLog.debug(
      99          142 :                 'TracerProvider: Successfully shut down processor ${processor.runtimeType}');
     100              :           }
     101              :         } catch (e) {
     102            1 :           if (OTelLog.isDebug()) {
     103            1 :             OTelLog.debug(
     104            2 :                 'TracerProvider: Error shutting down processor ${processor.runtimeType}: $e');
     105              :           }
     106              :         }
     107              :       }
     108              : 
     109              :       // Clear cached tracers
     110          144 :       _tracers.clear();
     111           72 :       if (OTelLog.isDebug()) {
     112           71 :         OTelLog.debug('TracerProvider: Cleared cached tracers');
     113              :       }
     114              : 
     115              :       try {
     116          144 :         await _delegate.shutdown();
     117           72 :         if (OTelLog.isDebug()) {
     118           71 :           OTelLog.debug('TracerProvider: Delegate shutdown complete');
     119              :         }
     120              :       } catch (e) {
     121            0 :         if (OTelLog.isDebug()) {
     122            0 :           OTelLog.debug('TracerProvider: Error during delegate shutdown: $e');
     123              :         }
     124              :       }
     125              : 
     126           72 :       isShutdown = true;
     127          143 :       if (OTelLog.isDebug()) OTelLog.debug('TracerProvider: Shutdown complete');
     128              :     } else {
     129           61 :       if (OTelLog.isDebug()) OTelLog.debug('TracerProvider: Already shut down');
     130              :     }
     131           72 :     return isShutdown;
     132              :   }
     133              : 
     134           29 :   @override
     135              :   Tracer getTracer(
     136              :     String name, {
     137              :     String? version,
     138              :     String? schemaUrl,
     139              :     Attributes? attributes,
     140              :     Sampler? sampler,
     141              :   }) {
     142           29 :     if (OTelLog.isDebug()) {
     143           29 :       OTelLog.debug(
     144           29 :           'TracerProvider: Getting tracer with name: $name, version: $version, schemaUrl: $schemaUrl');
     145              :     }
     146           29 :     if (isShutdown) {
     147            1 :       throw StateError('TracerProvider has been shut down');
     148              :     }
     149              : 
     150              :     // Ensure resource is set before creating tracer
     151           29 :     ensureResourceIsSet();
     152              : 
     153           29 :     final key = '$name:${version ?? ''}';
     154           58 :     return _tracers.putIfAbsent(
     155              :       key,
     156           58 :       () => SDKTracerCreate.create(
     157           58 :         delegate: _delegate.getTracer(
     158              :           name,
     159              :           version: version,
     160              :           schemaUrl: schemaUrl,
     161              :           attributes: attributes,
     162              :         ),
     163              :         provider: this,
     164              :         sampler: sampler,
     165              :       ) as Tracer,
     166              :     );
     167              :   }
     168              : 
     169              :   /// Adds a span processor to this provider.
     170              :   ///
     171              :   /// Span processors are notified of span lifecycle events and are responsible
     172              :   /// for additional processing of spans, such as exporting them.
     173              :   ///
     174              :   /// @param processor The span processor to add
     175           73 :   void addSpanProcessor(SpanProcessor processor) {
     176           73 :     if (isShutdown) {
     177            1 :       throw StateError('TracerProvider has been shut down');
     178              :     }
     179           73 :     if (OTelLog.isDebug()) {
     180           73 :       OTelLog.debug(
     181          146 :           'SDKTracerProvider: Adding span processor of type ${processor.runtimeType}');
     182              :     }
     183          146 :     _spanProcessors.add(processor);
     184              :   }
     185              : 
     186              :   /// Gets all registered span processors.
     187              :   ///
     188              :   /// @return An unmodifiable list of all span processors
     189           87 :   List<SpanProcessor> get spanProcessors => List.unmodifiable(_spanProcessors);
     190              : 
     191              :   /// Ensures the resource for this provider is properly set.
     192              :   ///
     193              :   /// If no resource has been set, the default resource will be used.
     194           29 :   void ensureResourceIsSet() {
     195           29 :     if (resource == null) {
     196            2 :       resource = OTel.defaultResource;
     197            2 :       if (OTelLog.isDebug()) {
     198            2 :         OTelLog.debug('TracerProvider: Setting resource from default');
     199            2 :         if (resource != null) {
     200            1 :           OTelLog.debug('Resource attributes:');
     201            5 :           resource!.attributes.toList().forEach((attr) {
     202            4 :             if (attr.key == 'tenant_id' || attr.key == 'service.name') {
     203            4 :               OTelLog.debug('  ${attr.key}: ${attr.value}');
     204              :             }
     205              :           });
     206              :         }
     207              :       }
     208              :     }
     209              :   }
     210              : 
     211            1 :   @override
     212            2 :   String get endpoint => _delegate.endpoint;
     213              : 
     214            1 :   @override
     215              :   set endpoint(String value) {
     216            2 :     _delegate.endpoint = value;
     217              :   }
     218              : 
     219            1 :   @override
     220            2 :   String get serviceName => _delegate.serviceName;
     221              : 
     222            1 :   @override
     223              :   set serviceName(String value) {
     224            2 :     _delegate.serviceName = value;
     225              :   }
     226              : 
     227            1 :   @override
     228            2 :   String? get serviceVersion => _delegate.serviceVersion;
     229              : 
     230            1 :   @override
     231              :   set serviceVersion(String? value) {
     232            2 :     _delegate.serviceVersion = value;
     233              :   }
     234              : 
     235            1 :   @override
     236            2 :   bool get enabled => _delegate.enabled;
     237              : 
     238            1 :   @override
     239              :   set enabled(bool value) {
     240            2 :     _delegate.enabled = value;
     241              :   }
     242              : 
     243              :   /// Forces all span processors to flush any queued spans.
     244              :   ///
     245              :   /// This method is useful for ensuring that all spans are exported
     246              :   /// before the application terminates or when immediate visibility
     247              :   /// of spans is required.
     248              :   ///
     249              :   /// @return A Future that completes when all processors have been flushed
     250           72 :   Future<void> forceFlush() async {
     251           72 :     if (OTelLog.isDebug()) {
     252           71 :       OTelLog.debug(
     253          213 :           'TracerProvider: Force flushing ${_spanProcessors.length} processors');
     254              :     }
     255              : 
     256           72 :     if (isShutdown) {
     257           31 :       if (OTelLog.isDebug()) {
     258           30 :         OTelLog.debug(
     259              :             'TracerProvider: Cannot force flush - provider is shut down');
     260              :       }
     261              :       return;
     262              :     }
     263              : 
     264          136 :     for (var processor in _spanProcessors) {
     265              :       try {
     266           68 :         if (OTelLog.isDebug()) {
     267           67 :           OTelLog.debug(
     268          134 :               'TracerProvider: Flushing processor ${processor.runtimeType}');
     269              :         }
     270           68 :         await processor.forceFlush();
     271           68 :         if (OTelLog.isDebug()) {
     272           67 :           OTelLog.debug(
     273          134 :               'TracerProvider: Successfully flushed processor ${processor.runtimeType}');
     274              :         }
     275              :       } catch (e) {
     276            1 :         if (OTelLog.isDebug()) {
     277            1 :           OTelLog.debug(
     278            2 :               'TracerProvider: Error flushing processor ${processor.runtimeType}: $e');
     279              :         }
     280              :       }
     281              :     }
     282              : 
     283           68 :     if (OTelLog.isDebug()) {
     284           67 :       OTelLog.debug('TracerProvider: Force flush complete');
     285              :     }
     286              :   }
     287              : }
        

Generated by: LCOV version 2.0-1