コード例 #1
0
        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));
            }
        }
コード例 #2
0
        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;
            }
        }