public async Task <IApiResponse> PostAsync(Span[][] traces, FormatterResolverWrapper formatterResolver) { // re-create HttpContent on every retry because some versions of HttpClient always dispose of it, so we can't reuse. using (var content = new TracesMessagePackContent(traces, formatterResolver)) { _request.Content = content; var response = await _client.SendAsync(_request).ConfigureAwait(false); return(new HttpClientResponse(response)); } }
public async Task SendTracesAsync(Span[][] traces) { // retry up to 5 times with exponential back-off var retryLimit = 5; var retryCount = 1; var sleepDuration = 100; // in milliseconds var traceIds = GetUniqueTraceIds(traces); while (true) { HttpResponseMessage responseMessage; try { // re-create HttpContent on every retry because some versions of HttpClient always dispose of it, so we can't reuse. using (var content = new TracesMessagePackContent(traces, _formatterResolver)) { content.Headers.Add(AgentHttpHeaderNames.TraceCount, traceIds.Count.ToString()); try { _statsd?.AppendIncrementCount(TracerMetricNames.Api.Requests); responseMessage = await _client.PostAsync(_tracesEndpoint, content).ConfigureAwait(false); } catch { // count the exceptions thrown by the HttpClient, // not responses with 5xx status codes // (which cause EnsureSuccessStatusCode() to throw below) _statsd?.AppendIncrementCount(TracerMetricNames.Api.Errors); throw; } if (_statsd != null) { // don't bother creating the tags array if trace metrics are disabled string[] tags = { $"status:{(int)responseMessage.StatusCode}" }; // count every response, grouped by status code _statsd.AppendIncrementCount(TracerMetricNames.Api.Responses, tags: tags); } responseMessage.EnsureSuccessStatusCode(); } } catch (Exception ex) { #if DEBUG if (ex.InnerException is InvalidOperationException ioe) { Log.Error("An error occurred while sending traces to the agent at {Endpoint}\n{Exception}", ex, _tracesEndpoint, ex.ToString()); return; } #endif if (retryCount >= retryLimit) { // stop retrying Log.Error("An error occurred while sending traces to the agent at {Endpoint}", ex, _tracesEndpoint); return; } // retry await Task.Delay(sleepDuration).ConfigureAwait(false); retryCount++; sleepDuration *= 2; TracingProcessManager.TraceAgentMetadata.ForcePortFileRead(); continue; } try { if (responseMessage.Content != null && Tracer.Instance.Sampler != null) { // build the sample rate map from the response json var responseContent = await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false); var response = JsonConvert.DeserializeObject<ApiResponse>(responseContent); Tracer.Instance.Sampler.SetDefaultSampleRates(response?.RateByService); } } catch (Exception ex) { Log.Error("Traces sent successfully to the Agent at {Endpoint}, but an error occurred deserializing the response.", ex, _tracesEndpoint); } _statsd?.Send(); return; } }