mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-26 06:42:51 +08:00

* copied everything from repos back to ocelot repo * added src projects to sln * removed all test projects that have no tests * added all test projects to sln * removed test not on master * merged unit tests * merged acceptance tests * merged integration tests * fixed namepaces * build script creates packages for all projects * updated docs to make sure no references to external repos that we will remove * +semver: breaking
104 lines
3.8 KiB
C#
104 lines
3.8 KiB
C#
namespace Ocelot.Tracing.Butterfly
|
|
{
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Net.Http;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using global::Butterfly.Client.AspNetCore;
|
|
using global::Butterfly.Client.Tracing;
|
|
using global::Butterfly.OpenTracing;
|
|
using Infrastructure.Extensions;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
public class ButterflyTracer : DelegatingHandler, Logging.ITracer
|
|
{
|
|
private readonly IServiceTracer _tracer;
|
|
private const string PrefixSpanId = "ot-spanId";
|
|
|
|
public ButterflyTracer(IServiceProvider services)
|
|
{
|
|
_tracer = services.GetService<IServiceTracer>();
|
|
}
|
|
|
|
public void Event(HttpContext httpContext, string @event)
|
|
{
|
|
// todo - if the user isnt using tracing the code gets here and will blow up on
|
|
// _tracer.Tracer.TryExtract..
|
|
if (_tracer == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var span = httpContext.GetSpan();
|
|
|
|
if (span == null)
|
|
{
|
|
var spanBuilder = new SpanBuilder($"server {httpContext.Request.Method} {httpContext.Request.Path}");
|
|
if (_tracer.Tracer.TryExtract(out var spanContext, httpContext.Request.Headers, (c, k) => c[k].GetValue(),
|
|
c => c.Select(x => new KeyValuePair<string, string>(x.Key, x.Value.GetValue())).GetEnumerator()))
|
|
{
|
|
spanBuilder.AsChildOf(spanContext);
|
|
}
|
|
|
|
span = _tracer.Start(spanBuilder);
|
|
httpContext.SetSpan(span);
|
|
}
|
|
|
|
span?.Log(LogField.CreateNew().Event(@event));
|
|
}
|
|
|
|
public Task<HttpResponseMessage> SendAsync(
|
|
HttpRequestMessage request,
|
|
CancellationToken cancellationToken,
|
|
Action<string> addTraceIdToRepo,
|
|
Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> baseSendAsync)
|
|
{
|
|
return _tracer.ChildTraceAsync($"httpclient {request.Method}", DateTimeOffset.UtcNow, span => TracingSendAsync(span, request, cancellationToken, addTraceIdToRepo, baseSendAsync));
|
|
}
|
|
|
|
protected virtual async Task<HttpResponseMessage> TracingSendAsync(
|
|
ISpan span,
|
|
HttpRequestMessage request,
|
|
CancellationToken cancellationToken,
|
|
Action<string> addTraceIdToRepo,
|
|
Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> baseSendAsync)
|
|
{
|
|
if (request.Headers.Contains(PrefixSpanId))
|
|
{
|
|
request.Headers.Remove(PrefixSpanId);
|
|
request.Headers.TryAddWithoutValidation(PrefixSpanId, span.SpanContext.SpanId);
|
|
}
|
|
|
|
addTraceIdToRepo(span.SpanContext.TraceId);
|
|
|
|
span.Tags.Client().Component("HttpClient")
|
|
.HttpMethod(request.Method.Method)
|
|
.HttpUrl(request.RequestUri.OriginalString)
|
|
.HttpHost(request.RequestUri.Host)
|
|
.HttpPath(request.RequestUri.PathAndQuery)
|
|
.PeerAddress(request.RequestUri.OriginalString)
|
|
.PeerHostName(request.RequestUri.Host)
|
|
.PeerPort(request.RequestUri.Port);
|
|
|
|
_tracer.Tracer.Inject(span.SpanContext, request.Headers, (c, k, v) =>
|
|
{
|
|
if (!c.Contains(k))
|
|
{
|
|
c.Add(k, v);
|
|
}
|
|
});
|
|
|
|
span.Log(LogField.CreateNew().ClientSend());
|
|
|
|
var responseMessage = await baseSendAsync(request, cancellationToken);
|
|
|
|
span.Log(LogField.CreateNew().ClientReceive());
|
|
|
|
return responseMessage;
|
|
}
|
|
}
|
|
}
|