| 288 | } |
| 289 | |
| 290 | func (s *service) Flush() { |
| 291 | // This shouldn't really be required since flush should only be called once, but just in case... |
| 292 | s.mu.Lock() |
| 293 | defer s.mu.Unlock() |
| 294 | |
| 295 | if s.previouslyCalled { |
| 296 | return |
| 297 | } |
| 298 | s.previouslyCalled = true |
| 299 | |
| 300 | if s.sampleRate > 0 && s.sampleRate < 100 && int(s.sampleBucket) >= s.sampleRate { |
| 301 | return |
| 302 | } |
| 303 | |
| 304 | // When the service has been disabled mid-invocation (e.g. an enterprise host |
| 305 | // was contacted), discard any recorded events. We still call the flusher |
| 306 | // with an empty payload so that the log-mode flusher can surface the |
| 307 | // absence of telemetry rather than leaving the user staring at silence. |
| 308 | events := s.events |
| 309 | if s.disabled { |
| 310 | events = nil |
| 311 | } |
| 312 | |
| 313 | payload := SendTelemetryPayload{ |
| 314 | Events: make([]PayloadEvent, len(events)), |
| 315 | } |
| 316 | |
| 317 | for i, recorded := range events { |
| 318 | dimensions := map[string]string{ |
| 319 | "timestamp": recorded.recordedAt.UTC().Format("2006-01-02T15:04:05.000Z"), |
| 320 | } |
| 321 | maps.Copy(dimensions, s.commonDimensions) |
| 322 | maps.Copy(dimensions, recorded.event.Dimensions) |
| 323 | |
| 324 | payload.Events[i] = PayloadEvent{ |
| 325 | Type: recorded.event.Type, |
| 326 | Dimensions: dimensions, |
| 327 | Measures: recorded.event.Measures, |
| 328 | } |
| 329 | } |
| 330 | |
| 331 | s.flush(payload) |
| 332 | } |
| 333 | |
| 334 | // maxPayloadSize is a safety limit for the telemetry payload written to the |
| 335 | // child process stdin pipe. This bounds the data transferred to a reasonable |