@@ -7,6 +7,7 @@ package openfeature
77
88import (
99 "bytes"
10+ "cmp"
1011 "context"
1112 "encoding/json"
1213 "fmt"
@@ -100,60 +101,40 @@ type exposureWriter struct {
100101
101102// newExposureWriter creates a new exposure writer with the given configuration
102103func newExposureWriter (config ProviderConfig ) * exposureWriter {
103- flushInterval := config .ExposureFlushInterval
104- if flushInterval == 0 {
105- flushInterval = defaultExposureFlushInterval
106- }
107-
108- // Get agent URL from environment or default
109- agentURL := internal .AgentURLFromEnv ()
110-
111104 // Build service context from environment variables
112- serviceName := globalconfig .ServiceName ()
113- if serviceName == "" {
114- serviceName = env .Get ("DD_SERVICE" )
115- }
105+ serviceName := cmp .Or (env .Get ("DD_SERVICE" ), globalconfig .ServiceName ())
116106 if serviceName == "" {
117107 serviceName = "unknown"
118108 }
119109
120110 context := exposureContext {
121111 ServiceName : serviceName ,
112+ Version : env .Get ("DD_VERSION" ),
113+ Env : env .Get ("DD_ENV" ),
122114 }
123115
124- // Only include version and env if they are defined
125- if version := env .Get ("DD_VERSION" ); version != "" {
126- context .Version = version
127- }
128-
129- if envName := env .Get ("DD_ENV" ); envName != "" {
130- context .Env = envName
131- }
132-
133- // Create HTTP client with timeout
134- httpClient := & http.Client {
135- Timeout : defaultHTTPTimeout ,
136- }
137-
138- w := & exposureWriter {
116+ return & exposureWriter {
139117 buffer : make ([]exposureEvent , 0 ),
140- flushInterval : flushInterval ,
141- httpClient : httpClient ,
142- agentURL : agentURL ,
143- context : context ,
144- stopChan : make (chan struct {}),
118+ flushInterval : cmp .Or (config .ExposureFlushInterval , defaultExposureFlushInterval ),
119+ httpClient : & http.Client {
120+ Timeout : defaultHTTPTimeout ,
121+ },
122+ agentURL : internal .AgentURLFromEnv (),
123+ context : context ,
124+ stopChan : make (chan struct {}),
145125 }
146-
147- // Start periodic flushing
148- w .start ()
149-
150- return w
151126}
152127
153128// start begins the periodic flushing of exposure events
154129func (w * exposureWriter ) start () {
155130 w .ticker = time .NewTicker (w .flushInterval )
156131 go func () {
132+ defer func () {
133+ if r := recover (); r != nil {
134+ log .Error ("openfeature: exposure writer recovered panic: %v" , r )
135+ }
136+ }()
137+
157138 for {
158139 select {
159140 case <- w .ticker .C :
@@ -189,7 +170,7 @@ func (w *exposureWriter) flush() {
189170
190171 // Move buffer to local variable and create new buffer
191172 events := w .buffer
192- w .buffer = make ([]exposureEvent , 0 )
173+ w .buffer = make ([]exposureEvent , len ( events ) / 2 )
193174 w .mu .Unlock ()
194175
195176 // Build payload
@@ -262,6 +243,8 @@ func (w *exposureWriter) buildRequestURL() string {
262243
263244// stop stops the exposure writer and flushes any remaining events
264245func (w * exposureWriter ) stop () {
246+ w .flush ()
247+
265248 w .mu .Lock ()
266249 if w .stopped {
267250 w .mu .Unlock ()
@@ -270,16 +253,13 @@ func (w *exposureWriter) stop() {
270253 w .stopped = true
271254 w .mu .Unlock ()
272255
256+ // Signal the goroutine to stop
257+ close (w .stopChan )
258+
273259 // Stop the ticker
274260 if w .ticker != nil {
275261 w .ticker .Stop ()
276262 }
277263
278- // Signal the goroutine to stop
279- close (w .stopChan )
280-
281- // Final flush
282- w .flush ()
283-
284264 log .Debug ("openfeature: exposure writer stopped" )
285265}
0 commit comments