/// <summary> /// Transmits the current contents of the span buffer to the SplunkTracing Collector. /// Note that this creates a copy of the current spans and clears the span buffer! /// </summary> public async void Flush() { if (_options.Run) { if (_options.EnableMetaEventLogging && _firstReportHasRun == false) { BuildSpan(SplunkTracingConstants.MetaEvent.TracerCreateOperation) .IgnoreActiveSpan() .WithTag(SplunkTracingConstants.MetaEvent.MetaEventKey, true) .WithTag(SplunkTracingConstants.MetaEvent.TracerGuidKey, _options.TracerGuid) .Start() .Finish(); _firstReportHasRun = true; } // save current spans and clear the buffer ISpanRecorder currentBuffer; lock (_lock) { currentBuffer = _spanRecorder.GetSpanBuffer(); _spanRecorder = new SplunkTracingSpanRecorder(); _logger.Trace($"{currentBuffer.GetSpans().Count()} spans in buffer."); } /** * there are two ways spans can be dropped: * 1. the buffer drops a span because it's too large, malformed, etc. * 2. the report failed to be sent to the collector. * since flush is async and there can potentially be any number of buffers in flight to the collector, * we need to set the current drop count on the tracer to be the amount of dropped spans from the buffer * plus the existing dropped spans, then mutate the current buffer to this new total value. */ currentDroppedSpanCount += currentBuffer.DroppedSpanCount; currentBuffer.DroppedSpanCount = currentDroppedSpanCount; if (currentBuffer.GetSpans().Count() > 0) { try { // since translate can throw exceptions, place it in the try and drop spans as appropriate var data = _httpClient.Translate(currentBuffer); var resp = await _httpClient.SendReport(data); if (resp.code > 0) { _logger.Warn($"Errors in report: {resp.text}"); } // if the collector is in developer mode, set the tracer to development mode as well // don't re-enable if it's already enabled though // TODO: iterate through all commands to find devmode flag if (_options.EnableMetaEventLogging == false) { _logger.Info("Enabling meta event logging"); _options.EnableMetaEventLogging = true; } lock (_lock) { _logger.Trace($"Resetting tracer dropped span count as the last report was successful."); currentDroppedSpanCount = 0; } } catch (Exception ex) when(ex is HttpRequestException || ex is TaskCanceledException || ex is OperationCanceledException || ex is Exception) { lock (_lock) { _logger.Warn($"Adding {currentBuffer.GetSpans().Count()} spans to dropped span count (current total: {currentDroppedSpanCount})"); _logger.Warn($"Exception: {ex}"); currentDroppedSpanCount += currentBuffer.GetSpans().Count(); if (this._options.ExceptionHandlerRegistered) { this._options.ExceptionHandler.Invoke(ex); } } } } } }