LCOV - code coverage report
Current view: top level - lib/src/logs - logger_provider.dart (source / functions) Coverage Total Hit
Test: lcov.info Lines: 95.2 % 105 100
Test Date: 2026-07-11 13:35:19 Functions: - 0 0

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

Generated by: LCOV version 2.0-1