1// Code created by gotmpl. DO NOT MODIFY.
2// source: internal/shared/otlp/otlpmetric/oconf/envconfig.go.tmpl
3
4// Copyright The OpenTelemetry Authors
5//
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18package oconf
19
20import (
21 "crypto/tls"
22 "crypto/x509"
23 "net/url"
24 "os"
25 "path"
26 "strings"
27 "time"
28
29 "{{ .envconfigImportPath }}"
30 "go.opentelemetry.io/otel/internal/global"
31 "go.opentelemetry.io/otel/sdk/metric"
32 "go.opentelemetry.io/otel/sdk/metric/metricdata"
33)
34
35// DefaultEnvOptionsReader is the default environments reader.
36var DefaultEnvOptionsReader = envconfig.EnvOptionsReader{
37 GetEnv: os.Getenv,
38 ReadFile: os.ReadFile,
39 Namespace: "OTEL_EXPORTER_OTLP",
40}
41
42// ApplyGRPCEnvConfigs applies the env configurations for gRPC.
43func ApplyGRPCEnvConfigs(cfg Config) Config {
44 opts := getOptionsFromEnv()
45 for _, opt := range opts {
46 cfg = opt.ApplyGRPCOption(cfg)
47 }
48 return cfg
49}
50
51// ApplyHTTPEnvConfigs applies the env configurations for HTTP.
52func ApplyHTTPEnvConfigs(cfg Config) Config {
53 opts := getOptionsFromEnv()
54 for _, opt := range opts {
55 cfg = opt.ApplyHTTPOption(cfg)
56 }
57 return cfg
58}
59
60func getOptionsFromEnv() []GenericOption {
61 opts := []GenericOption{}
62
63 tlsConf := &tls.Config{}
64 DefaultEnvOptionsReader.Apply(
65 envconfig.WithURL("ENDPOINT", func(u *url.URL) {
66 opts = append(opts, withEndpointScheme(u))
67 opts = append(opts, newSplitOption(func(cfg Config) Config {
68 cfg.Metrics.Endpoint = u.Host
69 // For OTLP/HTTP endpoint URLs without a per-signal
70 // configuration, the passed endpoint is used as a base URL
71 // and the signals are sent to these paths relative to that.
72 cfg.Metrics.URLPath = path.Join(u.Path, DefaultMetricsPath)
73 return cfg
74 }, withEndpointForGRPC(u)))
75 }),
76 envconfig.WithURL("METRICS_ENDPOINT", func(u *url.URL) {
77 opts = append(opts, withEndpointScheme(u))
78 opts = append(opts, newSplitOption(func(cfg Config) Config {
79 cfg.Metrics.Endpoint = u.Host
80 // For endpoint URLs for OTLP/HTTP per-signal variables, the
81 // URL MUST be used as-is without any modification. The only
82 // exception is that if an URL contains no path part, the root
83 // path / MUST be used.
84 path := u.Path
85 if path == "" {
86 path = "/"
87 }
88 cfg.Metrics.URLPath = path
89 return cfg
90 }, withEndpointForGRPC(u)))
91 }),
92 envconfig.WithCertPool("CERTIFICATE", func(p *x509.CertPool) { tlsConf.RootCAs = p }),
93 envconfig.WithCertPool("METRICS_CERTIFICATE", func(p *x509.CertPool) { tlsConf.RootCAs = p }),
94 envconfig.WithClientCert("CLIENT_CERTIFICATE", "CLIENT_KEY", func(c tls.Certificate) { tlsConf.Certificates = []tls.Certificate{c} }),
95 envconfig.WithClientCert("METRICS_CLIENT_CERTIFICATE", "METRICS_CLIENT_KEY", func(c tls.Certificate) { tlsConf.Certificates = []tls.Certificate{c} }),
96 envconfig.WithBool("INSECURE", func(b bool) { opts = append(opts, withInsecure(b)) }),
97 envconfig.WithBool("METRICS_INSECURE", func(b bool) { opts = append(opts, withInsecure(b)) }),
98 withTLSConfig(tlsConf, func(c *tls.Config) { opts = append(opts, WithTLSClientConfig(c)) }),
99 envconfig.WithHeaders("HEADERS", func(h map[string]string) { opts = append(opts, WithHeaders(h)) }),
100 envconfig.WithHeaders("METRICS_HEADERS", func(h map[string]string) { opts = append(opts, WithHeaders(h)) }),
101 WithEnvCompression("COMPRESSION", func(c Compression) { opts = append(opts, WithCompression(c)) }),
102 WithEnvCompression("METRICS_COMPRESSION", func(c Compression) { opts = append(opts, WithCompression(c)) }),
103 envconfig.WithDuration("TIMEOUT", func(d time.Duration) { opts = append(opts, WithTimeout(d)) }),
104 envconfig.WithDuration("METRICS_TIMEOUT", func(d time.Duration) { opts = append(opts, WithTimeout(d)) }),
105 withEnvTemporalityPreference("METRICS_TEMPORALITY_PREFERENCE", func(t metric.TemporalitySelector) { opts = append(opts, WithTemporalitySelector(t)) }),
106 withEnvAggPreference("METRICS_DEFAULT_HISTOGRAM_AGGREGATION", func(a metric.AggregationSelector) { opts = append(opts, WithAggregationSelector(a)) }),
107 )
108
109 return opts
110}
111
112func withEndpointForGRPC(u *url.URL) func(cfg Config) Config {
113 return func(cfg Config) Config {
114 // For OTLP/gRPC endpoints, this is the target to which the
115 // exporter is going to send telemetry.
116 cfg.Metrics.Endpoint = path.Join(u.Host, u.Path)
117 return cfg
118 }
119}
120
121// WithEnvCompression retrieves the specified config and passes it to ConfigFn as a Compression.
122func WithEnvCompression(n string, fn func(Compression)) func(e *envconfig.EnvOptionsReader) {
123 return func(e *envconfig.EnvOptionsReader) {
124 if v, ok := e.GetEnvValue(n); ok {
125 cp := NoCompression
126 if v == "gzip" {
127 cp = GzipCompression
128 }
129
130 fn(cp)
131 }
132 }
133}
134
135func withEndpointScheme(u *url.URL) GenericOption {
136 switch strings.ToLower(u.Scheme) {
137 case "http", "unix":
138 return WithInsecure()
139 default:
140 return WithSecure()
141 }
142}
143
144// revive:disable-next-line:flag-parameter
145func withInsecure(b bool) GenericOption {
146 if b {
147 return WithInsecure()
148 }
149 return WithSecure()
150}
151
152func withTLSConfig(c *tls.Config, fn func(*tls.Config)) func(e *envconfig.EnvOptionsReader) {
153 return func(e *envconfig.EnvOptionsReader) {
154 if c.RootCAs != nil || len(c.Certificates) > 0 {
155 fn(c)
156 }
157 }
158}
159
160func withEnvTemporalityPreference(n string, fn func(metric.TemporalitySelector)) func(e *envconfig.EnvOptionsReader) {
161 return func(e *envconfig.EnvOptionsReader) {
162 if s, ok := e.GetEnvValue(n); ok {
163 switch strings.ToLower(s) {
164 case "cumulative":
165 fn(cumulativeTemporality)
166 case "delta":
167 fn(deltaTemporality)
168 case "lowmemory":
169 fn(lowMemory)
170 default:
171 global.Warn("OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE is set to an invalid value, ignoring.", "value", s)
172 }
173 }
174 }
175}
176
177func cumulativeTemporality(metric.InstrumentKind) metricdata.Temporality {
178 return metricdata.CumulativeTemporality
179}
180
181func deltaTemporality(ik metric.InstrumentKind) metricdata.Temporality {
182 switch ik {
183 case metric.InstrumentKindCounter, metric.InstrumentKindHistogram, metric.InstrumentKindObservableCounter:
184 return metricdata.DeltaTemporality
185 default:
186 return metricdata.CumulativeTemporality
187 }
188}
189
190func lowMemory(ik metric.InstrumentKind) metricdata.Temporality {
191 switch ik {
192 case metric.InstrumentKindCounter, metric.InstrumentKindHistogram:
193 return metricdata.DeltaTemporality
194 default:
195 return metricdata.CumulativeTemporality
196 }
197}
198
199func withEnvAggPreference(n string, fn func(metric.AggregationSelector)) func(e *envconfig.EnvOptionsReader) {
200 return func(e *envconfig.EnvOptionsReader) {
201 if s, ok := e.GetEnvValue(n); ok {
202 switch strings.ToLower(s) {
203 case "explicit_bucket_histogram":
204 fn(metric.DefaultAggregationSelector)
205 case "base2_exponential_bucket_histogram":
206 fn(func(kind metric.InstrumentKind) metric.Aggregation {
207 if kind == metric.InstrumentKindHistogram {
208 return metric.AggregationBase2ExponentialHistogram{
209 MaxSize: 160,
210 MaxScale: 20,
211 NoMinMax: false,
212 }
213 }
214 return metric.DefaultAggregationSelector(kind)
215 })
216 default:
217 global.Warn("OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION is set to an invalid value, ignoring.", "value", s)
218 }
219 }
220 }
221}
View as plain text