public void RoundTripRootSpanTest()
        {
            var parentSpanContext = new Mock <ISpanContext>();
            var traceContext      = new Mock <ITraceContext>();
            var spanContext       = new SpanContext(parentSpanContext.Object, traceContext.Object, serviceName: null);

            var span = new Span(spanContext, start: null);

            span.ServiceName = "ServiceName";
            span.SetTag("k0", "v0");
            span.SetTag("k1", "v1");
            span.SetTag("k2", "v2");

            var tracerSettings = new TracerSettings();
            var serializerSpan = new ZipkinSerializer.ZipkinSpan(span, tracerSettings);

            var serializer = new ZipkinSerializer();

            using var ms = new MemoryStream();

            serializer.Serialize(ms, new[] { new[] { span } }, tracerSettings);

            ms.Position = 0;
            var jsonText     = new StreamReader(ms).ReadToEnd();
            var actualTraces = JsonConvert.DeserializeObject <List <TestZipkinSpan> >(jsonText);

            Assert.Single(actualTraces);

            var actualSpan = actualTraces[0];

            actualSpan.AssertZipkinSerializerSpan(serializerSpan);
        }
        public void RoundTripRootSpanTest()
        {
            var span       = SpanFactory.CreateSpan();
            var zipkinSpan = new ZipkinSerializer.ZipkinSpan(span);

            var serializer = new ZipkinSerializer();

            using var ms = new MemoryStream();

            serializer.Serialize(ms, new[] { new[] { span } });

            ms.Position = 0;
            var jsonText     = new StreamReader(ms).ReadToEnd();
            var actualTraces = JsonConvert.DeserializeObject <List <TestZipkinSpan> >(jsonText);

            Assert.Single(actualTraces);

            var actualSpan = actualTraces[0];

            actualSpan.AssertZipkinSerializerSpan(zipkinSpan);
        }
Exemple #3
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";

                // Disable automatic instrumentation for Zipkin exporter
                request.Headers.Add(CommonHttpHeaderNames.TracingEnabled, "false");

                // Add SignalFx Access Token if configured
                if (!string.IsNullOrWhiteSpace(_settings.SignalFxAccessToken))
                {
                    request.Headers.Add("X-Sf-Token", _settings.SignalFxAccessToken);
                }

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

                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;
            }
        }