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 : show OTelLog;
6 :
7 : import '../../environment/otel_env.dart';
8 : import '../../export/otlp_http_protocol.dart';
9 : import '../../otel.dart';
10 : import '../../resource/resource.dart';
11 : import '../sampling/sampler.dart';
12 : import '../span_exception_options.dart';
13 : import '../span_processor.dart';
14 : import '../tracer_provider.dart';
15 : import 'batch_span_processor.dart';
16 : import 'composite_exporter.dart';
17 : import 'console_exporter.dart';
18 : import 'otlp/http/otlp_http_span_exporter.dart';
19 : import 'otlp/http/otlp_http_span_exporter_config.dart';
20 : import 'otlp/otlp_grpc_span_exporter.dart';
21 : import 'otlp/otlp_grpc_span_exporter_config.dart';
22 : import 'span_exporter.dart';
23 :
24 : /// Configuration for traces exporters and processors.
25 : class TracesConfiguration {
26 : /// Configures a TracerProvider with given settings.
27 : ///
28 : /// This configures everything needed for the traces pipeline:
29 : /// - An exporter selected per the OTel spec:
30 : /// `OTEL_TRACES_EXPORTER=otlp` (default) → OtlpHttp/Grpc exporter,
31 : /// `=console` → ConsoleExporter, `=none` → no processor is added.
32 : /// - A processor (defaults to BatchSpanProcessor if none provided)
33 : /// - Sets up resources on the TracerProvider
34 153 : static TracerProvider configureTracerProvider({
35 : String? endpoint,
36 : bool? secure,
37 : SpanProcessor? spanProcessor,
38 : Sampler? sampler,
39 : SpanExceptionOptions spanExceptionOptions = const SpanExceptionOptions(),
40 : Resource? resource,
41 : required OtlpEnvironmentValues otlpConfig,
42 : required List<String> exporters,
43 : required BspEnvironmentValues bspConfig,
44 : }) {
45 153 : final tracerProvider = OTel.tracerProvider();
46 :
47 : if (resource != null) {
48 153 : tracerProvider.resource = resource;
49 : }
50 :
51 : if (spanProcessor == null) {
52 : // Determine protocol - default to http/protobuf if not set
53 : final protocol = otlpConfig.protocol ?? 'http/protobuf';
54 :
55 : final resolvedEndpoint = otlpConfig.endpoint ??
56 : endpoint ??
57 122 : (protocol == 'grpc'
58 : ? OTel.defaultGrpcEndpoint
59 : : OTel.defaultEndpoint);
60 145 : final resolvedSecure = OTelEnv.resolveOtlpSecure(
61 : envInsecure: otlpConfig.insecure,
62 : endpoint: resolvedEndpoint,
63 : explicitSecure: secure,
64 : );
65 :
66 135 : SpanExporter buildOtlpExporter() {
67 : // Create appropriate exporter based on protocol
68 135 : if (protocol == 'grpc') {
69 4 : return OtlpGrpcSpanExporter(
70 4 : OtlpGrpcExporterConfig(
71 : endpoint: resolvedEndpoint,
72 : insecure: !resolvedSecure,
73 4 : headers: otlpConfig.headers ?? {},
74 : timeout: otlpConfig.timeout ?? const Duration(seconds: 10),
75 4 : compression: otlpConfig.compression == 'gzip',
76 : certificate: otlpConfig.certificate,
77 : clientKey: otlpConfig.clientKey,
78 : clientCertificate: otlpConfig.clientCertificate,
79 : ),
80 : );
81 : } else {
82 135 : final httpProtocol = otlpHttpProtocolFromString(protocol) ??
83 : OtlpHttpProtocol.httpProtobuf;
84 135 : return OtlpHttpSpanExporter(
85 135 : OtlpHttpExporterConfig(
86 : endpoint: resolvedEndpoint,
87 135 : headers: otlpConfig.headers ?? {},
88 : timeout: otlpConfig.timeout ?? const Duration(seconds: 10),
89 135 : compression: otlpConfig.compression == 'gzip',
90 : certificate: otlpConfig.certificate,
91 : clientKey: otlpConfig.clientKey,
92 : clientCertificate: otlpConfig.clientCertificate,
93 : protocol: httpProtocol,
94 : ),
95 : );
96 : }
97 : }
98 :
99 145 : if (exporters.contains('none')) {
100 23 : if (exporters.length > 1 && OTelLog.isWarn()) {
101 1 : OTelLog.warn("OTEL_TRACES_EXPORTER contains 'none' alongside other "
102 : 'values; installing no exporter.');
103 : }
104 : } else {
105 135 : final createdExporters = <SpanExporter>[];
106 270 : for (final name in exporters) {
107 : switch (name) {
108 135 : case 'otlp':
109 270 : createdExporters.add(buildOtlpExporter());
110 1 : case 'console':
111 2 : createdExporters.add(ConsoleExporter());
112 1 : case 'logging':
113 1 : if (OTelLog.isWarn()) {
114 1 : OTelLog.warn("OTEL_TRACES_EXPORTER value 'logging' is "
115 : "deprecated in the spec and not supported; use 'console'.");
116 : }
117 : default:
118 1 : if (OTelLog.isWarn()) {
119 2 : OTelLog.warn("OTEL_TRACES_EXPORTER value '$name' is not "
120 : 'supported; ignoring. Supported: otlp, console, none.');
121 : }
122 : }
123 : }
124 135 : if (createdExporters.isEmpty) {
125 1 : if (OTelLog.isWarn()) {
126 1 : OTelLog.warn('OTEL_TRACES_EXPORTER produced no usable exporter; '
127 : 'falling back to the default otlp exporter.');
128 : }
129 2 : createdExporters.add(buildOtlpExporter());
130 : }
131 :
132 : final bspConfigObj =
133 135 : BatchSpanProcessorConfig.fromBspEnvironmentValues(bspConfig);
134 135 : spanProcessor = BatchSpanProcessor(
135 270 : createdExporters.length == 1
136 135 : ? createdExporters.single
137 1 : : CompositeExporter(createdExporters),
138 : bspConfigObj,
139 : );
140 : }
141 : }
142 :
143 : if (spanProcessor != null) {
144 143 : tracerProvider.addSpanProcessor(spanProcessor);
145 : }
146 : if (sampler != null) {
147 4 : tracerProvider.sampler = sampler;
148 : }
149 153 : tracerProvider.spanExceptionOptions = spanExceptionOptions;
150 :
151 : return tracerProvider;
152 : }
153 : }
|