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 : import '../../environment/otel_env.dart';
7 :
8 : /// Exemplar filtering policy for metrics export.
9 : enum MetricsExemplarFilter {
10 : /// Export exemplars only when trace/span context is present.
11 : traceBased,
12 :
13 : /// Export all exemplars.
14 : alwaysOn,
15 :
16 : /// Export no exemplars.
17 : alwaysOff,
18 : }
19 :
20 : /// Resolved metrics SDK configuration derived from environment variables.
21 : class MetricsSdkConfig {
22 : /// The default exemplar filter per spec.
23 : static const MetricsExemplarFilter defaultExemplarFilter =
24 : MetricsExemplarFilter.traceBased;
25 :
26 : /// The default periodic export interval per spec.
27 : static const Duration defaultExportInterval = Duration(seconds: 60);
28 :
29 : /// The default periodic export timeout per spec.
30 : static const Duration defaultExportTimeout = Duration(seconds: 30);
31 :
32 : /// The exemplar filtering policy.
33 : ///
34 : /// Parsed from `OTEL_METRICS_EXEMPLAR_FILTER`.
35 : final MetricsExemplarFilter exemplarFilter;
36 :
37 : /// Periodic export interval.
38 : ///
39 : /// Parsed from `OTEL_METRIC_EXPORT_INTERVAL`.
40 : final Duration exportInterval;
41 :
42 : /// Periodic export timeout.
43 : ///
44 : /// Parsed from `OTEL_METRIC_EXPORT_TIMEOUT`.
45 : final Duration exportTimeout;
46 :
47 132 : const MetricsSdkConfig({
48 : this.exemplarFilter = defaultExemplarFilter,
49 : this.exportInterval = defaultExportInterval,
50 : this.exportTimeout = defaultExportTimeout,
51 : });
52 :
53 : /// Creates a configuration by reading metrics environment variables via [OTelEnv].
54 : ///
55 : /// Applies spec defaults and validates inputs, emitting warnings for
56 : /// unusable values.
57 132 : factory MetricsSdkConfig.fromEnvironment(
58 : [MetricsEnvironmentValues? overrides]) {
59 131 : final env = overrides ?? OTelEnv.getMetricsConfig();
60 :
61 : var filter = defaultExemplarFilter;
62 : if (env.exemplarFilter != null) {
63 2 : switch (env.exemplarFilter!.toLowerCase()) {
64 2 : case 'always_on':
65 : filter = MetricsExemplarFilter.alwaysOn;
66 : break;
67 2 : case 'always_off':
68 : filter = MetricsExemplarFilter.alwaysOff;
69 : break;
70 2 : case 'trace_based':
71 : filter = MetricsExemplarFilter.traceBased;
72 : break;
73 : default:
74 2 : if (OTelLog.isWarn()) {
75 4 : OTelLog.warn(
76 : 'MetricsSdkConfig: Invalid OTEL_METRICS_EXEMPLAR_FILTER '
77 : 'value "${env.exemplarFilter}", using default (trace_based).');
78 : }
79 : }
80 : }
81 :
82 : var interval = defaultExportInterval;
83 : if (env.exportInterval != null) {
84 : final t = env.exportInterval!;
85 2 : if (t.inMilliseconds <= 0) {
86 1 : if (OTelLog.isWarn()) {
87 2 : OTelLog.warn(
88 : 'MetricsSdkConfig: Non-positive OTEL_METRIC_EXPORT_INTERVAL '
89 1 : '(${t.inMilliseconds} ms) is invalid per spec, using default '
90 1 : '(${defaultExportInterval.inMilliseconds} ms).');
91 : }
92 : } else {
93 : interval = t;
94 : }
95 : }
96 :
97 : var timeout = defaultExportTimeout;
98 : if (env.exportTimeout != null) {
99 : final t = env.exportTimeout!;
100 2 : if (t.inMilliseconds == 0) {
101 : // Spec defines 0 as no limit for timeouts
102 : timeout = const Duration(days: 365);
103 1 : if (OTelLog.isDebug()) {
104 0 : OTelLog.debug(
105 : 'MetricsSdkConfig: OTEL_METRIC_EXPORT_TIMEOUT set to 0 (no limit). Switched to a large number internally.');
106 : }
107 2 : } else if (t.inMilliseconds < 0) {
108 1 : if (OTelLog.isWarn()) {
109 2 : OTelLog.warn('MetricsSdkConfig: Negative OTEL_METRIC_EXPORT_TIMEOUT '
110 1 : '(${t.inMilliseconds} ms) is invalid per spec, using default '
111 1 : '(${defaultExportTimeout.inMilliseconds} ms).');
112 : }
113 : } else {
114 : timeout = t;
115 : }
116 : }
117 :
118 132 : return MetricsSdkConfig(
119 : exemplarFilter: filter,
120 : exportInterval: interval,
121 : exportTimeout: timeout,
122 : );
123 : }
124 : }
|