LCOV - code coverage report
Current view: top level - lib/src/logs/export - logs_config.dart (source / functions) Coverage Total Hit
Test: lcov.info Lines: 96.7 % 61 59
Test Date: 2026-08-27 23:42:02 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              : 
       6              : import '../../environment/otel_env.dart';
       7              : import '../../otel.dart';
       8              : import '../../resource/resource.dart';
       9              : import '../log_record_processor.dart';
      10              : import '../logger_provider.dart';
      11              : import 'batch_log_record_processor.dart';
      12              : import 'console_log_record_exporter.dart';
      13              : import 'log_record_exporter.dart';
      14              : import 'otlp/http/otlp_http_log_record_exporter.dart';
      15              : import 'otlp/http/otlp_http_log_record_exporter_config.dart';
      16              : import 'otlp/otlp_grpc_log_record_exporter.dart';
      17              : import 'otlp/otlp_grpc_log_record_exporter_config.dart';
      18              : import 'simple_log_record_processor.dart';
      19              : 
      20              : /// Configuration for logs exporters and processors.
      21              : ///
      22              : /// This class provides methods to configure the LoggerProvider based on
      23              : /// environment variables and explicit configuration parameters.
      24              : class LogsConfiguration {
      25              :   /// Configures a LoggerProvider with the given settings.
      26              :   ///
      27              :   /// This configures everything needed for the logs pipeline:
      28              :   /// - An exporter (based on OTEL_LOGS_EXPORTER env var or defaults to OTLP)
      29              :   /// - A processor (BatchLogRecordProcessor with BLRP env var config)
      30              :   /// - Sets up resources on the LoggerProvider
      31              :   ///
      32              :   /// @param endpoint The endpoint URL for the exporter (null to use the
      33              :   ///   protocol-dependent default, issue #220)
      34              :   /// @param secure Whether to use TLS for gRPC connections
      35              :   /// @param logRecordExporter Optional custom exporter (overrides env var)
      36              :   /// @param logRecordProcessor Optional custom processor (overrides env var)
      37              :   /// @param resource Optional resource for the LoggerProvider
      38              :   /// @return The configured LoggerProvider
      39          127 :   static LoggerProvider configureLoggerProvider({
      40              :     String? endpoint,
      41              :     bool? secure,
      42              :     LogRecordExporter? logRecordExporter,
      43              :     LogRecordProcessor? logRecordProcessor,
      44              :     Resource? resource,
      45              :     OtlpEnvironmentValues? otlpConfig,
      46              :     List<String>? exporters,
      47              :     BlrpEnvironmentValues? blrpConfig,
      48              :   }) {
      49            4 :     otlpConfig ??= OTelEnv.getOtlpConfig(signal: 'logs');
      50            8 :     exporters ??= OTelEnv.getExporters(signal: 'logs') ?? ['otlp'];
      51            4 :     blrpConfig ??= OTelEnv.getBlrpConfig();
      52              : 
      53              :     // Get the logger provider
      54          127 :     final logProvider = OTel.loggerProvider();
      55              : 
      56              :     // Set resource if provided
      57              :     if (resource != null) {
      58          127 :       logProvider.resource = resource;
      59              :     }
      60              : 
      61              :     // If a custom processor is provided, use it directly
      62              :     if (logRecordProcessor != null) {
      63            3 :       logProvider.addLogRecordProcessor(logRecordProcessor);
      64              :       return logProvider;
      65              :     }
      66              : 
      67              :     // Explicitly provided exporter wins; otherwise read the env selection.
      68              :     if (logRecordExporter != null) {
      69            4 :       logProvider.addLogRecordProcessor(
      70            4 :           _createProcessor(logRecordExporter, blrpConfig));
      71              :       return logProvider;
      72              :     }
      73              : 
      74              :     // Multiple exporters install one processor per exporter.
      75          124 :     if (exporters.contains('none')) {
      76            5 :       if (exporters.length > 1 && OTelLog.isWarn()) {
      77            1 :         OTelLog.warn("OTEL_LOGS_EXPORTER contains 'none' alongside other "
      78              :             'values; installing no processor.');
      79            2 :       } else if (OTelLog.isDebug()) {
      80            1 :         OTelLog.debug(
      81              :             'LogsConfiguration: OTEL_LOGS_EXPORTER=none, no processor added');
      82              :       }
      83              :       return logProvider;
      84              :     }
      85              : 
      86          123 :     final createdExporters = <LogRecordExporter>[];
      87          246 :     for (final name in exporters) {
      88          123 :       if (name == 'logging') {
      89            1 :         if (OTelLog.isWarn()) {
      90            1 :           OTelLog.warn("OTEL_LOGS_EXPORTER value 'logging' is deprecated "
      91              :               "in the spec and not supported; use 'console'.");
      92              :         }
      93              :         continue;
      94              :       }
      95          123 :       final created = _createExporter(name, endpoint, secure, otlpConfig);
      96              :       if (created != null) {
      97          123 :         createdExporters.add(created);
      98            1 :       } else if (OTelLog.isWarn()) {
      99            2 :         OTelLog.warn("OTEL_LOGS_EXPORTER value '$name' is not supported; "
     100              :             'ignoring. Supported: otlp, console, none.');
     101              :       }
     102              :     }
     103          123 :     if (createdExporters.isEmpty) {
     104            1 :       if (OTelLog.isWarn()) {
     105            1 :         OTelLog.warn('OTEL_LOGS_EXPORTER produced no usable exporter; '
     106              :             'falling back to the default otlp exporter.');
     107              :       }
     108            1 :       final fallback = _createExporter('otlp', endpoint, secure, otlpConfig);
     109              :       if (fallback != null) {
     110            1 :         createdExporters.add(fallback);
     111              :       }
     112              :     }
     113          246 :     for (final exporter in createdExporters) {
     114          246 :       logProvider.addLogRecordProcessor(_createProcessor(exporter, blrpConfig));
     115              :     }
     116              : 
     117          123 :     if (OTelLog.isDebug()) {
     118          242 :       OTelLog.debug('LogsConfiguration: Configured LoggerProvider with '
     119          121 :           '${createdExporters.length} exporter(s) from OTEL_LOGS_EXPORTER');
     120              :     }
     121              : 
     122              :     return logProvider;
     123              :   }
     124              : 
     125              :   /// Creates a log record exporter based on the exporter type.
     126          123 :   static LogRecordExporter? _createExporter(
     127              :     String exporterType,
     128              :     String? endpoint,
     129              :     bool? secure,
     130              :     OtlpEnvironmentValues otlpConfig,
     131              :   ) {
     132              :     final protocol = otlpConfig.protocol ?? 'http/protobuf';
     133              : 
     134              :     // Use env endpoint if available, otherwise use provided endpoint. The
     135              :     // default endpoint depends on the protocol (issue #220): OTLP/gRPC uses
     136              :     // port 4317, the HTTP protocols use port 4318.
     137              :     final effectiveEndpoint = otlpConfig.endpoint ??
     138              :         endpoint ??
     139           97 :         (protocol == 'grpc' ? OTel.defaultGrpcEndpoint : OTel.defaultEndpoint);
     140              :     final envInsecure = otlpConfig.insecure;
     141          123 :     final effectiveSecure = OTelEnv.resolveOtlpSecure(
     142              :       envInsecure: envInsecure,
     143              :       endpoint: effectiveEndpoint,
     144              :       explicitSecure: secure,
     145              :     );
     146              : 
     147          123 :     if (exporterType == 'console') {
     148            1 :       if (OTelLog.isDebug()) {
     149            0 :         OTelLog.debug('LogsConfiguration: Creating ConsoleLogRecordExporter');
     150              :       }
     151            1 :       return ConsoleLogRecordExporter();
     152              :     }
     153              : 
     154          123 :     if (exporterType == 'otlp') {
     155          123 :       if (protocol == 'grpc') {
     156            3 :         if (OTelLog.isDebug()) {
     157            2 :           OTelLog.debug(
     158              :               'LogsConfiguration: Creating OtlpGrpcLogRecordExporter');
     159              :         }
     160            3 :         return OtlpGrpcLogRecordExporter(
     161            3 :           OtlpGrpcLogRecordExporterConfig(
     162              :             endpoint: effectiveEndpoint,
     163              :             insecure: !effectiveSecure,
     164            3 :             headers: otlpConfig.headers ?? {},
     165              :             timeout: otlpConfig.timeout ?? const Duration(seconds: 10),
     166            3 :             compression: otlpConfig.compression == 'gzip',
     167              :             certificate: otlpConfig.certificate,
     168              :             clientKey: otlpConfig.clientKey,
     169              :             clientCertificate: otlpConfig.clientCertificate,
     170              :           ),
     171              :         );
     172              :       } else {
     173              :         // Default to http/protobuf
     174          122 :         if (OTelLog.isDebug()) {
     175          120 :           OTelLog.debug(
     176              :               'LogsConfiguration: Creating OtlpHttpLogRecordExporter');
     177              :         }
     178          122 :         return OtlpHttpLogRecordExporter(
     179          122 :           OtlpHttpLogRecordExporterConfig(
     180              :             endpoint: effectiveEndpoint,
     181          122 :             headers: otlpConfig.headers ?? {},
     182              :             timeout: otlpConfig.timeout ?? const Duration(seconds: 10),
     183          122 :             compression: otlpConfig.compression == 'gzip',
     184              :             certificate: otlpConfig.certificate,
     185              :             clientKey: otlpConfig.clientKey,
     186              :             clientCertificate: otlpConfig.clientCertificate,
     187              :           ),
     188              :         );
     189              :       }
     190              :     }
     191              : 
     192              :     // Unknown exporter type
     193            1 :     if (OTelLog.isDebug()) {
     194            0 :       OTelLog.debug('LogsConfiguration: Unknown exporter type: $exporterType');
     195              :     }
     196              :     return null;
     197              :   }
     198              : 
     199              :   /// Creates a log record processor with BLRP configuration from environment.
     200          125 :   static LogRecordProcessor _createProcessor(
     201              :       LogRecordExporter exporter, BlrpEnvironmentValues blrpConfig) {
     202              :     final processorConfig =
     203          125 :         BatchLogRecordProcessorConfig.fromBlrpEnvironmentValues(blrpConfig);
     204          125 :     return BatchLogRecordProcessor(exporter, processorConfig);
     205              :   }
     206              : 
     207              :   /// Creates a simple (synchronous) log record processor instead of batch.
     208              :   ///
     209              :   /// This is useful for development/debugging or when you want immediate export.
     210            2 :   static LogRecordProcessor createSimpleProcessor(LogRecordExporter exporter) {
     211            2 :     return SimpleLogRecordProcessor(exporter);
     212              :   }
     213              : }
        

Generated by: LCOV version 2.0-1