@@ -18,23 +18,26 @@ import (
18
18
19
19
// Default periodic reader timing.
20
20
const (
21
- defaultTimeout = time .Millisecond * 30000
22
- defaultInterval = time .Millisecond * 60000
21
+ defaultTimeout = time .Millisecond * 30000
22
+ defaultInterval = time .Millisecond * 60000
23
+ defaultShutdownWait = time .Duration (0 )
23
24
)
24
25
25
26
// periodicReaderConfig contains configuration options for a PeriodicReader.
26
27
type periodicReaderConfig struct {
27
- interval time.Duration
28
- timeout time.Duration
29
- producers []Producer
28
+ interval time.Duration
29
+ timeout time.Duration
30
+ shutdownWait time.Duration
31
+ producers []Producer
30
32
}
31
33
32
34
// newPeriodicReaderConfig returns a periodicReaderConfig configured with
33
35
// options.
34
36
func newPeriodicReaderConfig (options []PeriodicReaderOption ) periodicReaderConfig {
35
37
c := periodicReaderConfig {
36
- interval : envDuration (envInterval , defaultInterval ),
37
- timeout : envDuration (envTimeout , defaultTimeout ),
38
+ interval : envDuration (envInterval , defaultInterval ),
39
+ timeout : envDuration (envTimeout , defaultTimeout ),
40
+ shutdownWait : envDuration (envShutdownWait , defaultShutdownWait ),
38
41
}
39
42
for _ , o := range options {
40
43
c = o .applyPeriodic (c )
@@ -94,6 +97,24 @@ func WithInterval(d time.Duration) PeriodicReaderOption {
94
97
})
95
98
}
96
99
100
+ // WithShutdownWait configures the wait time to export remainning metrics in shutdown for a
101
+ // PeriodicReader.
102
+ //
103
+ // This option overrides any value set for the
104
+ // OTEL_METRIC_EXPORT_SHUTDOWN_WAIT environment variable.
105
+ //
106
+ // If this option is not used or d is less than or equal to zero, 0 seconds
107
+ // is used as the default.
108
+ func WithShutdownWait (d time.Duration ) PeriodicReaderOption {
109
+ return periodicReaderOptionFunc (func (conf periodicReaderConfig ) periodicReaderConfig {
110
+ if d <= 0 {
111
+ return conf
112
+ }
113
+ conf .shutdownWait = d
114
+ return conf
115
+ })
116
+ }
117
+
97
118
// NewPeriodicReader returns a Reader that collects and exports metric data to
98
119
// the exporter at a defined interval. By default, the returned Reader will
99
120
// collect and export data every 60 seconds, and will cancel any attempts that
@@ -107,12 +128,13 @@ func NewPeriodicReader(exporter Exporter, options ...PeriodicReaderOption) *Peri
107
128
conf := newPeriodicReaderConfig (options )
108
129
ctx , cancel := context .WithCancel (context .Background ())
109
130
r := & PeriodicReader {
110
- interval : conf .interval ,
111
- timeout : conf .timeout ,
112
- exporter : exporter ,
113
- flushCh : make (chan chan error ),
114
- cancel : cancel ,
115
- done : make (chan struct {}),
131
+ interval : conf .interval ,
132
+ timeout : conf .timeout ,
133
+ shutdownWait : conf .shutdownWait ,
134
+ exporter : exporter ,
135
+ flushCh : make (chan chan error ),
136
+ cancel : cancel ,
137
+ done : make (chan struct {}),
116
138
rmPool : sync.Pool {
117
139
New : func () interface {} {
118
140
return & metricdata.ResourceMetrics {}
@@ -138,10 +160,11 @@ type PeriodicReader struct {
138
160
isShutdown bool
139
161
externalProducers atomic.Value
140
162
141
- interval time.Duration
142
- timeout time.Duration
143
- exporter Exporter
144
- flushCh chan chan error
163
+ interval time.Duration
164
+ timeout time.Duration
165
+ shutdownWait time.Duration
166
+ exporter Exporter
167
+ flushCh chan chan error
145
168
146
169
done chan struct {}
147
170
cancel context.CancelFunc
@@ -329,6 +352,9 @@ func (r *PeriodicReader) Shutdown(ctx context.Context) error {
329
352
m := r .rmPool .Get ().(* metricdata.ResourceMetrics )
330
353
err = r .collect (ctx , ph , m )
331
354
if err == nil {
355
+ if r .shutdownWait > 0 {
356
+ time .Sleep (r .shutdownWait )
357
+ }
332
358
err = r .export (ctx , m )
333
359
}
334
360
r .rmPool .Put (m )
0 commit comments