private async Task FlushEventsAsync(FlushPayload payload) { EventOutputFormatter formatter = new EventOutputFormatter(_config); string jsonEvents; int eventCount; try { jsonEvents = formatter.SerializeOutputEvents(payload.Events, payload.Summary, out eventCount); } catch (Exception e) { LogHelpers.LogException(_logger, "Error preparing events, will not send", e); return; } var result = await _eventSender.SendEventDataAsync(EventDataKind.AnalyticsEvents, jsonEvents, eventCount); if (result.Status == DeliveryStatus.FailedAndMustShutDown) { _disabled = true; } if (result.TimeFromServer.HasValue) { Interlocked.Exchange(ref _lastKnownPastTime, UnixMillisecondTime.FromDateTime(result.TimeFromServer.Value).Value); } }
// Grabs a snapshot of the current internal state, and starts a new task to send it to the server. private void StartFlush(EventBuffer buffer) { if (_disabled) { return; } FlushPayload payload = buffer.GetPayload(); if (_diagnosticStore != null) { _diagnosticStore.RecordEventsInBatch(payload.Events.Length); } if (payload.Events.Length > 0 || !payload.Summary.Empty) { lock (_flushWorkersCounter) { // Note that this counter will be 1, not 0, when there are no active flush workers. // This is because a .NET CountdownEvent can't be reused without explicitly resetting // it once it has gone to zero. if (_flushWorkersCounter.CurrentCount >= MaxFlushWorkers + 1) { // We already have too many workers, so just leave the events as is return; } // We haven't hit the limit, we'll go ahead and start a flush task _flushWorkersCounter.AddCount(1); } buffer.Clear(); Task.Run(async() => { try { await FlushEventsAsync(payload); } finally { _flushWorkersCounter.Signal(); } }); } }