@@ -10,22 +10,61 @@ import (
10
10
"time"
11
11
12
12
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp/internal/retry"
13
+ "go.opentelemetry.io/otel/internal/global"
14
+ )
15
+
16
+ // Default values.
17
+ var (
18
+ defaultEndpoint = "localhost:4318"
19
+ defaultPath = "/v1/logs"
20
+ defaultTimeout = 10 * time .Second
21
+ defaultProxy HTTPTransportProxyFunc = http .ProxyFromEnvironment
22
+ defaultRetryCfg = RetryConfig (retry .DefaultConfig )
13
23
)
14
24
15
25
// Option applies an option to the Exporter.
16
26
type Option interface {
17
27
applyHTTPOption (config ) config
18
28
}
19
29
30
+ type fnOpt func (config ) config
31
+
32
+ func (f fnOpt ) applyHTTPOption (c config ) config { return f (c ) }
33
+
20
34
type config struct {
21
- // TODO: implement.
35
+ endpoint setting [string ]
36
+ path setting [string ]
37
+ insecure setting [bool ]
38
+ tlsCfg setting [* tls.Config ]
39
+ headers setting [map [string ]string ]
40
+ compression setting [Compression ]
41
+ timeout setting [time.Duration ]
42
+ proxy setting [HTTPTransportProxyFunc ]
43
+ retryCfg setting [RetryConfig ]
22
44
}
23
45
24
46
func newConfig (options []Option ) config {
25
47
var c config
26
48
for _ , opt := range options {
27
49
c = opt .applyHTTPOption (c )
28
50
}
51
+
52
+ c .endpoint = c .endpoint .Resolve (
53
+ fallback [string ](defaultEndpoint ),
54
+ )
55
+ c .path = c .path .Resolve (
56
+ fallback [string ](defaultPath ),
57
+ )
58
+ c .timeout = c .timeout .Resolve (
59
+ fallback [time.Duration ](defaultTimeout ),
60
+ )
61
+ c .proxy = c .proxy .Resolve (
62
+ fallback [HTTPTransportProxyFunc ](defaultProxy ),
63
+ )
64
+ c .retryCfg = c .retryCfg .Resolve (
65
+ fallback [RetryConfig ](defaultRetryCfg ),
66
+ )
67
+
29
68
return c
30
69
}
31
70
@@ -41,8 +80,10 @@ func newConfig(options []Option) config {
41
80
// By default, if an environment variable is not set, and this option is not
42
81
// passed, "localhost:4318" will be used.
43
82
func WithEndpoint (endpoint string ) Option {
44
- // TODO: implement.
45
- return nil
83
+ return fnOpt (func (c config ) config {
84
+ c .endpoint = newSetting (endpoint )
85
+ return c
86
+ })
46
87
}
47
88
48
89
// WithEndpointURL sets the target endpoint URL the Exporter will connect to.
@@ -59,15 +100,34 @@ func WithEndpoint(endpoint string) Option {
59
100
//
60
101
// By default, if an environment variable is not set, and this option is not
61
102
// passed, "localhost:4318" will be used.
62
- func WithEndpointURL (u string ) Option {
63
- // TODO: implement.
64
- return nil
103
+ func WithEndpointURL (rawURL string ) Option {
104
+ u , err := url .Parse (rawURL )
105
+ if err != nil {
106
+ global .Error (err , "otlpmetric: parse endpoint url" , "url" , rawURL )
107
+ return fnOpt (func (c config ) config { return c })
108
+ }
109
+ return fnOpt (func (c config ) config {
110
+ c .endpoint = newSetting (u .Host )
111
+ c .path = newSetting (u .Path )
112
+ if u .Scheme != "https" {
113
+ c .insecure = newSetting (true )
114
+ } else {
115
+ c .insecure = newSetting (false )
116
+ }
117
+ return c
118
+ })
65
119
}
66
120
67
- // Compression describes the compression used for payloads sent to the
68
- // collector.
121
+ // Compression describes the compression used for exported payloads.
69
122
type Compression int
70
123
124
+ const (
125
+ // NoCompression represents that no compression should be used.
126
+ NoCompression Compression = iota
127
+ // GzipCompression represents that gzip compression should be used.
128
+ GzipCompression
129
+ )
130
+
71
131
// WithCompression sets the compression strategy the Exporter will use to
72
132
// compress the HTTP body.
73
133
//
@@ -80,8 +140,10 @@ type Compression int
80
140
// By default, if an environment variable is not set, and this option is not
81
141
// passed, no compression strategy will be used.
82
142
func WithCompression (compression Compression ) Option {
83
- // TODO: implement.
84
- return nil
143
+ return fnOpt (func (c config ) config {
144
+ c .compression = newSetting (compression )
145
+ return c
146
+ })
85
147
}
86
148
87
149
// WithURLPath sets the URL path the Exporter will send requests to.
@@ -94,8 +156,10 @@ func WithCompression(compression Compression) Option {
94
156
// By default, if an environment variable is not set, and this option is not
95
157
// passed, "/v1/logs" will be used.
96
158
func WithURLPath (urlPath string ) Option {
97
- // TODO: implement.
98
- return nil
159
+ return fnOpt (func (c config ) config {
160
+ c .path = newSetting (urlPath )
161
+ return c
162
+ })
99
163
}
100
164
101
165
// WithTLSClientConfig sets the TLS configuration the Exporter will use for
@@ -110,8 +174,10 @@ func WithURLPath(urlPath string) Option {
110
174
// By default, if an environment variable is not set, and this option is not
111
175
// passed, the system default configuration is used.
112
176
func WithTLSClientConfig (tlsCfg * tls.Config ) Option {
113
- // TODO: implement.
114
- return nil
177
+ return fnOpt (func (c config ) config {
178
+ c .tlsCfg = newSetting (tlsCfg .Clone ())
179
+ return c
180
+ })
115
181
}
116
182
117
183
// WithInsecure disables client transport security for the Exporter's HTTP
@@ -126,8 +192,10 @@ func WithTLSClientConfig(tlsCfg *tls.Config) Option {
126
192
// By default, if an environment variable is not set, and this option is not
127
193
// passed, client security will be used.
128
194
func WithInsecure () Option {
129
- // TODO: implement.
130
- return nil
195
+ return fnOpt (func (c config ) config {
196
+ c .insecure = newSetting (true )
197
+ return c
198
+ })
131
199
}
132
200
133
201
// WithHeaders will send the provided headers with each HTTP requests.
@@ -142,8 +210,10 @@ func WithInsecure() Option {
142
210
// By default, if an environment variable is not set, and this option is not
143
211
// passed, no user headers will be set.
144
212
func WithHeaders (headers map [string ]string ) Option {
145
- // TODO: implement.
146
- return nil
213
+ return fnOpt (func (c config ) config {
214
+ c .headers = newSetting (headers )
215
+ return c
216
+ })
147
217
}
148
218
149
219
// WithTimeout sets the max amount of time an Exporter will attempt an export.
@@ -161,8 +231,10 @@ func WithHeaders(headers map[string]string) Option {
161
231
// By default, if an environment variable is not set, and this option is not
162
232
// passed, a timeout of 10 seconds will be used.
163
233
func WithTimeout (duration time.Duration ) Option {
164
- // TODO: implement.
165
- return nil
234
+ return fnOpt (func (c config ) config {
235
+ c .timeout = newSetting (duration )
236
+ return c
237
+ })
166
238
}
167
239
168
240
// RetryConfig defines configuration for retrying the export of log data that
@@ -180,8 +252,10 @@ type RetryConfig retry.Config
180
252
// 5 seconds after receiving a retryable error and increase exponentially
181
253
// after each error for no more than a total time of 1 minute.
182
254
func WithRetry (rc RetryConfig ) Option {
183
- // TODO: implement.
184
- return nil
255
+ return fnOpt (func (c config ) config {
256
+ c .retryCfg = newSetting (rc )
257
+ return c
258
+ })
185
259
}
186
260
187
261
// HTTPTransportProxyFunc is a function that resolves which URL to use as proxy
@@ -193,6 +267,53 @@ type HTTPTransportProxyFunc func(*http.Request) (*url.URL, error)
193
267
// proxy to use for an HTTP request. If this option is not used, the client
194
268
// will use [http.ProxyFromEnvironment].
195
269
func WithProxy (pf HTTPTransportProxyFunc ) Option {
196
- // TODO: implement.
197
- return nil
270
+ return fnOpt (func (c config ) config {
271
+ c .proxy = newSetting (pf )
272
+ return c
273
+ })
274
+ }
275
+
276
+ // setting is a configuration setting value.
277
+ type setting [T any ] struct {
278
+ Value T
279
+ Set bool
280
+ }
281
+
282
+ // newSetting returns a new setting with the value set.
283
+ func newSetting [T any ](value T ) setting [T ] {
284
+ return setting [T ]{Value : value , Set : true }
285
+ }
286
+
287
+ // resolver returns an updated setting after applying an resolution operation.
288
+ type resolver [T any ] func (setting [T ]) setting [T ]
289
+
290
+ // Resolve returns a resolved version of s.
291
+ //
292
+ // It will apply all the passed fn in the order provided, chaining together the
293
+ // return setting to the next input. The setting s is used as the initial
294
+ // argument to the first fn.
295
+ //
296
+ // Each fn needs to validate if it should apply given the Set state of the
297
+ // setting. This will not perform any checks on the set state when chaining
298
+ // function.
299
+ func (s setting [T ]) Resolve (fn ... resolver [T ]) setting [T ] {
300
+ for _ , f := range fn {
301
+ s = f (s )
302
+ }
303
+ return s
304
+ }
305
+
306
+ // fallback returns a resolve that will set a setting value to val if it is not
307
+ // already set.
308
+ //
309
+ // This is usually passed at the end of a resolver chain to ensure a default is
310
+ // applied if the setting has not already been set.
311
+ func fallback [T any ](val T ) resolver [T ] {
312
+ return func (s setting [T ]) setting [T ] {
313
+ if ! s .Set {
314
+ s .Value = val
315
+ s .Set = true
316
+ }
317
+ return s
318
+ }
198
319
}
0 commit comments