Ejemplo n.º 1
0
        public async Task <bool> SendTracesAsync(Span[][] traces)
        {
            if (traces == null || traces.Length == 0)
            {
                // Nothing to send, no ping for Zipkin.
                return(true);
            }

            // retry up to 5 times with exponential back-off
            var retryLimit    = 5;
            var retryCount    = 1;
            var sleepDuration = 100; // in milliseconds

            while (true)
            {
                // TODO: Initially same code for Fx and Core.
                var request = WebRequest.CreateHttp(_tracesEndpoint);
                request.Method      = "POST";
                request.ContentType = "application/json";

                using (var requestStream = await request.GetRequestStreamAsync().ConfigureAwait(false))
                {
                    var serializer = new ZipkinSerializer();
                    serializer.Serialize(requestStream, traces, _settings);
                }

                Exception      requestException  = null;
                HttpStatusCode requestStatusCode = 0;
                try
                {
                    using var httpWebResponse = (HttpWebResponse) await request.GetResponseAsync().ConfigureAwait(false);

                    // Zipkin specifies only "Accepted" as valid response, the code is more tolerant here.
                    // Following a criteria equivalent to HttpResponseMessage.EnsureSuccessStatusCode as
                    // done by the OpenTelemetry .NET SDK for their Zipkin exporter:
                    // See https://github.com/open-telemetry/opentelemetry-dotnet/blob/8cda9ef394a1b075fd156d73dace48e48f5b3c9b/src/OpenTelemetry.Exporter.Zipkin/ZipkinExporter.cs#L86
                    if (httpWebResponse.StatusCode >= HttpStatusCode.OK && httpWebResponse.StatusCode < HttpStatusCode.MultipleChoices)
                    {
                        return(true);
                    }

                    requestStatusCode = httpWebResponse.StatusCode;
                    Log.Debug("HTTP error sending traces to {0}: {1}", _tracesEndpoint, httpWebResponse.StatusCode);
                }
                catch (Exception ex)
                {
                    requestException = ex;
                    Log.Debug("Exception sending traces to {0}: {1}", _tracesEndpoint, ex.Message);
                }

                if (retryCount >= retryLimit)
                {
                    if (requestException != null)
                    {
                        Log.Error("No more retries, dropping spans. Last exception sending traces to {0}: {1}", _tracesEndpoint, requestException.Message);
                    }
                    else
                    {
                        Log.Error("No more retries, dropping spans. Last HTTP error sending traces to {0}: {1}", _tracesEndpoint, requestStatusCode);
                    }

                    return(false);
                }

                // retry
                await Task.Delay(sleepDuration).ConfigureAwait(false);

                retryCount++;
                sleepDuration *= 2;
            }
        }