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
33 : /// @param secure Whether to use TLS for gRPC connections
34 : /// @param logRecordExporter Optional custom exporter (overrides env var)
35 : /// @param logRecordProcessor Optional custom processor (overrides env var)
36 : /// @param resource Optional resource for the LoggerProvider
37 : /// @return The configured LoggerProvider
38 119 : static LoggerProvider configureLoggerProvider({
39 : String endpoint = 'http://localhost:4318',
40 : bool secure = false,
41 : LogRecordExporter? logRecordExporter,
42 : LogRecordProcessor? logRecordProcessor,
43 : Resource? resource,
44 : }) {
45 : // Get the logger provider
46 119 : final logProvider = OTel.loggerProvider();
47 :
48 : // Set resource if provided
49 : if (resource != null) {
50 119 : logProvider.resource = resource;
51 : }
52 :
53 : // If a custom processor is provided, use it directly
54 : if (logRecordProcessor != null) {
55 3 : logProvider.addLogRecordProcessor(logRecordProcessor);
56 : return logProvider;
57 : }
58 :
59 : // Determine exporter type from environment or use provided exporter
60 118 : final exporterType = OTelEnv.getExporter(signal: 'logs') ?? 'otlp';
61 :
62 118 : if (exporterType == 'none') {
63 : // No exporter configured - return provider without processor
64 0 : if (OTelLog.isDebug()) {
65 0 : OTelLog.debug(
66 : 'LogsConfiguration: OTEL_LOGS_EXPORTER=none, no processor added');
67 : }
68 : return logProvider;
69 : }
70 :
71 : // Create exporter if not provided
72 116 : logRecordExporter ??= _createExporter(exporterType, endpoint, secure);
73 :
74 : if (logRecordExporter == null) {
75 0 : if (OTelLog.isDebug()) {
76 0 : OTelLog.debug(
77 : 'LogsConfiguration: No exporter created, no processor added');
78 : }
79 : return logProvider;
80 : }
81 :
82 : // Create processor with BLRP configuration from environment
83 118 : final processor = _createProcessor(logRecordExporter);
84 :
85 : // Add the processor
86 118 : logProvider.addLogRecordProcessor(processor);
87 :
88 118 : if (OTelLog.isDebug()) {
89 118 : OTelLog.debug(
90 118 : 'LogsConfiguration: Configured LoggerProvider with $exporterType exporter');
91 : }
92 :
93 : return logProvider;
94 : }
95 :
96 : /// Creates a log record exporter based on the exporter type.
97 116 : static LogRecordExporter? _createExporter(
98 : String exporterType,
99 : String endpoint,
100 : bool secure,
101 : ) {
102 : // Get OTLP config for logs signal
103 116 : final otlpConfig = OTelEnv.getOtlpConfig(signal: 'logs');
104 :
105 : // Use env endpoint if available, otherwise use provided endpoint
106 116 : final effectiveEndpoint = otlpConfig['endpoint'] as String? ?? endpoint;
107 116 : final envInsecure = otlpConfig['insecure'] as bool?;
108 : final effectiveSecure = envInsecure != null ? !envInsecure : secure;
109 :
110 116 : if (exporterType == 'console') {
111 0 : if (OTelLog.isDebug()) {
112 0 : OTelLog.debug('LogsConfiguration: Creating ConsoleLogRecordExporter');
113 : }
114 0 : return ConsoleLogRecordExporter();
115 : }
116 :
117 116 : if (exporterType == 'otlp') {
118 : // Determine protocol - default to http/protobuf
119 116 : final protocol = otlpConfig['protocol'] as String? ?? 'http/protobuf';
120 :
121 116 : if (protocol == 'grpc') {
122 0 : if (OTelLog.isDebug()) {
123 0 : OTelLog.debug(
124 : 'LogsConfiguration: Creating OtlpGrpcLogRecordExporter');
125 : }
126 0 : return OtlpGrpcLogRecordExporter(
127 0 : OtlpGrpcLogRecordExporterConfig(
128 : endpoint: effectiveEndpoint,
129 : insecure: !effectiveSecure,
130 0 : headers: otlpConfig['headers'] as Map<String, String>? ?? {},
131 0 : timeout: otlpConfig['timeout'] as Duration? ??
132 : const Duration(seconds: 10),
133 0 : compression: otlpConfig['compression'] == 'gzip',
134 0 : certificate: otlpConfig['certificate'] as String?,
135 0 : clientKey: otlpConfig['clientKey'] as String?,
136 0 : clientCertificate: otlpConfig['clientCertificate'] as String?,
137 : ),
138 : );
139 : } else {
140 : // Default to http/protobuf
141 116 : if (OTelLog.isDebug()) {
142 116 : OTelLog.debug(
143 : 'LogsConfiguration: Creating OtlpHttpLogRecordExporter');
144 : }
145 116 : return OtlpHttpLogRecordExporter(
146 116 : OtlpHttpLogRecordExporterConfig(
147 : endpoint: effectiveEndpoint,
148 232 : headers: otlpConfig['headers'] as Map<String, String>? ?? {},
149 116 : timeout: otlpConfig['timeout'] as Duration? ??
150 : const Duration(seconds: 10),
151 232 : compression: otlpConfig['compression'] == 'gzip',
152 116 : certificate: otlpConfig['certificate'] as String?,
153 116 : clientKey: otlpConfig['clientKey'] as String?,
154 116 : clientCertificate: otlpConfig['clientCertificate'] as String?,
155 : ),
156 : );
157 : }
158 : }
159 :
160 : // Unknown exporter type
161 0 : if (OTelLog.isDebug()) {
162 0 : OTelLog.debug('LogsConfiguration: Unknown exporter type: $exporterType');
163 : }
164 : return null;
165 : }
166 :
167 : /// Creates a log record processor with BLRP configuration from environment.
168 118 : static LogRecordProcessor _createProcessor(LogRecordExporter exporter) {
169 118 : final blrpConfig = OTelEnv.getBlrpConfig();
170 :
171 118 : if (blrpConfig.isEmpty) {
172 : // Use defaults
173 118 : return BatchLogRecordProcessor(
174 : exporter,
175 : const BatchLogRecordProcessorConfig(),
176 : );
177 : }
178 :
179 : // Build config from environment
180 0 : final scheduleDelay = blrpConfig['scheduleDelay'] as Duration?;
181 0 : final exportTimeout = blrpConfig['exportTimeout'] as Duration?;
182 0 : final maxQueueSize = blrpConfig['maxQueueSize'] as int?;
183 0 : final maxExportBatchSize = blrpConfig['maxExportBatchSize'] as int?;
184 :
185 0 : return BatchLogRecordProcessor(
186 : exporter,
187 0 : BatchLogRecordProcessorConfig(
188 : scheduleDelay: scheduleDelay ?? const Duration(milliseconds: 1000),
189 : exportTimeout: exportTimeout ?? const Duration(seconds: 30),
190 : maxQueueSize: maxQueueSize ?? 2048,
191 : maxExportBatchSize: maxExportBatchSize ?? 512,
192 : ),
193 : );
194 : }
195 :
196 : /// Creates a simple (synchronous) log record processor instead of batch.
197 : ///
198 : /// This is useful for development/debugging or when you want immediate export.
199 2 : static LogRecordProcessor createSimpleProcessor(LogRecordExporter exporter) {
200 2 : return SimpleLogRecordProcessor(exporter);
201 : }
202 : }
|