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 '../../otel.dart';
9 : import '../../resource/resource.dart';
10 : import '../meter_provider.dart';
11 : import '../metric_exporter.dart';
12 : import '../metric_reader.dart';
13 : import 'otlp/http/otlp_http_metric_exporter.dart';
14 : import 'otlp/http/otlp_http_metric_exporter_config.dart';
15 : import 'otlp/otlp_grpc_metric_exporter.dart';
16 : import 'otlp/otlp_grpc_metric_exporter_config.dart';
17 :
18 : /// Configuration for metrics exporters and readers.
19 : class MetricsConfiguration {
20 : /// Configures a MeterProvider with given settings.
21 : ///
22 : /// This configures everything needed for metrics pipeline:
23 : /// - An exporter selected per the OTel spec:
24 : /// `OTEL_METRICS_EXPORTER=otlp` (default) → OtlpHttp/Grpc exporter,
25 : /// `=console` → ConsoleMetricExporter, `=none` → no reader is added.
26 : /// - A reader (defaults to PeriodicExportingMetricReader if none provided)
27 : /// - Sets up resources on the MeterProvider
28 : ///
29 : /// An explicit [metricExporter] or [metricReader] always wins over the
30 : /// env-var selection so programmatic configuration is unsurprising.
31 120 : static MeterProvider configureMeterProvider({
32 : String endpoint = 'http://localhost:4318',
33 : bool secure = false,
34 : MetricExporter? metricExporter,
35 : MetricReader? metricReader,
36 : Resource? resource,
37 : }) {
38 120 : final meterProvider = OTel.meterProvider();
39 : if (resource != null) {
40 120 : meterProvider.resource = resource;
41 : }
42 :
43 : // Honor OTEL_METRICS_EXPORTER, but only when the caller did not pass an
44 : // explicit exporter/reader — explicit args are an unambiguous opt-in and
45 : // should not be silently dropped by env config.
46 : if (metricExporter == null && metricReader == null) {
47 : final exporterType =
48 106 : OTelEnv.getExporter(signal: 'metrics')?.toLowerCase() ?? 'otlp';
49 106 : if (exporterType == 'none') {
50 0 : if (OTelLog.isDebug()) {
51 0 : OTelLog.debug(
52 : 'MetricsConfiguration: OTEL_METRICS_EXPORTER=none, skipping reader');
53 : }
54 : return meterProvider;
55 : }
56 106 : metricExporter = _createExporter(exporterType, endpoint, secure);
57 : if (metricExporter == null) {
58 : return meterProvider;
59 : }
60 : }
61 :
62 15 : metricExporter ??= _createExporter('otlp', endpoint, secure);
63 : if (metricExporter == null) {
64 : return meterProvider;
65 : }
66 :
67 106 : metricReader ??= PeriodicExportingMetricReader(
68 : metricExporter,
69 : interval: const Duration(seconds: 15),
70 : );
71 :
72 120 : meterProvider.addMetricReader(metricReader);
73 : return meterProvider;
74 : }
75 :
76 : /// Creates a metric exporter for [exporterType] (`otlp` or `console`).
77 : /// Returns null for unknown values.
78 120 : static MetricExporter? _createExporter(
79 : String exporterType,
80 : String endpoint,
81 : bool secure,
82 : ) {
83 120 : if (exporterType == 'console') {
84 0 : if (OTelLog.isDebug()) {
85 0 : OTelLog.debug('MetricsConfiguration: Creating ConsoleMetricExporter');
86 : }
87 0 : return ConsoleMetricExporter();
88 : }
89 120 : if (exporterType != 'otlp') {
90 0 : if (OTelLog.isDebug()) {
91 0 : OTelLog.debug(
92 : 'MetricsConfiguration: Unknown OTEL_METRICS_EXPORTER value '
93 : '"$exporterType", falling back to otlp');
94 : }
95 : }
96 :
97 120 : final otlpConfig = OTelEnv.getOtlpConfig(signal: 'metrics');
98 120 : final protocol = otlpConfig['protocol'] as String? ?? 'http/protobuf';
99 120 : final headers = otlpConfig['headers'] as Map<String, String>? ?? const {};
100 : final timeout =
101 120 : otlpConfig['timeout'] as Duration? ?? const Duration(seconds: 10);
102 240 : final compression = otlpConfig['compression'] == 'gzip';
103 120 : final certificate = otlpConfig['certificate'] as String?;
104 120 : final clientKey = otlpConfig['clientKey'] as String?;
105 120 : final clientCertificate = otlpConfig['clientCertificate'] as String?;
106 :
107 120 : if (protocol == 'grpc') {
108 0 : if (OTelLog.isDebug()) {
109 0 : OTelLog.debug(
110 0 : 'MetricsConfiguration: Creating OtlpGrpcMetricExporter for $endpoint');
111 : }
112 0 : return OtlpGrpcMetricExporter(
113 0 : OtlpGrpcMetricExporterConfig(
114 : endpoint: endpoint,
115 : insecure: !secure,
116 : headers: headers,
117 0 : timeoutMillis: timeout.inMilliseconds,
118 : compression: compression,
119 : certificate: certificate,
120 : clientKey: clientKey,
121 : clientCertificate: clientCertificate,
122 : ),
123 : );
124 : }
125 :
126 120 : if (OTelLog.isDebug()) {
127 116 : OTelLog.debug(
128 116 : 'MetricsConfiguration: Creating OtlpHttpMetricExporter for $endpoint');
129 : }
130 120 : return OtlpHttpMetricExporter(
131 120 : OtlpHttpMetricExporterConfig(
132 : endpoint: endpoint,
133 : headers: headers,
134 : timeout: timeout,
135 : compression: compression,
136 : certificate: certificate,
137 : clientKey: clientKey,
138 : clientCertificate: clientCertificate,
139 : ),
140 : );
141 : }
142 : }
|