broke out butterfly into seperate project (#521)

* broke out butterfly into seperate project

* nearly did it...

* updated docs as I have broken the butterfly code off into a seperate dll
This commit is contained in:
Tom Pallister 2018-08-03 08:11:47 +01:00 committed by GitHub
parent 24f8a18579
commit 37fb32b7f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 66 additions and 485 deletions

View File

@ -1,19 +1,29 @@
Tracing Tracing
======= =======
Ocelot providers tracing functionality from the excellent `Butterfly <https://github.com/liuhaoyang/butterfly>`_ project. This page details how to perform distributed tracing with Ocelot. At the moment we only support Butterfly but other tracers might just work without
anything Ocelot specific.
Butterfly
^^^^^^^^^
Ocelot providers tracing functionality from the excellent `Butterfly <https://github.com/liuhaoyang/butterfly>`_ project. The code for the Ocelot integration
can be found `here <https://github.com/ThreeMammals/Ocelot.Tracing.Butterfly>`_.
In order to use the tracing please read the Butterfly documentation. In order to use the tracing please read the Butterfly documentation.
In ocelot you need to do the following if you wish to trace a ReRoute. In ocelot you need to do the following if you wish to trace a ReRoute.
``Install-Package Ocelot.Tracing.Butterfly``
In your ConfigureServices method In your ConfigureServices method
.. code-block:: csharp .. code-block:: csharp
services services
.AddOcelot() .AddOcelot()
.AddOpenTracing(option => // this comes from Ocelot.Tracing.Butterfly package
.AddButterfly(option =>
{ {
//this is the url that the butterfly collector server is running on... //this is the url that the butterfly collector server is running on...
option.CollectorUrl = "http://localhost:9618"; option.CollectorUrl = "http://localhost:9618";

View File

@ -1,18 +1,17 @@
namespace Ocelot.Configuration.Creator namespace Ocelot.Configuration.Creator
{ {
using System; using System;
using Butterfly.Client.Tracing; using Logging;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Ocelot.Configuration.File; using Ocelot.Configuration.File;
using Ocelot.Requester;
public class HttpHandlerOptionsCreator : IHttpHandlerOptionsCreator public class HttpHandlerOptionsCreator : IHttpHandlerOptionsCreator
{ {
private readonly IServiceTracer _tracer; private readonly ITracer _tracer;
public HttpHandlerOptionsCreator(IServiceProvider services) public HttpHandlerOptionsCreator(IServiceProvider services)
{ {
_tracer = services.GetService<IServiceTracer>(); _tracer = services.GetService<ITracer>();
} }
public HttpHandlerOptions Create(FileHttpHandlerOptions options) public HttpHandlerOptions Create(FileHttpHandlerOptions options)

View File

@ -1,4 +1,3 @@
using Butterfly.Client.AspNetCore;
using CacheManager.Core; using CacheManager.Core;
using System; using System;
using System.Net.Http; using System.Net.Http;
@ -17,8 +16,6 @@ namespace Ocelot.DependencyInjection
IOcelotBuilder AddCacheManager(Action<ConfigurationBuilderCachePart> settings); IOcelotBuilder AddCacheManager(Action<ConfigurationBuilderCachePart> settings);
IOcelotBuilder AddOpenTracing(Action<ButterflyOptions> settings);
IOcelotAdministrationBuilder AddAdministration(string path, string secret); IOcelotAdministrationBuilder AddAdministration(string path, string secret);
IOcelotAdministrationBuilder AddAdministration(string path, Action<IdentityServerAuthenticationOptions> configOptions); IOcelotAdministrationBuilder AddAdministration(string path, Action<IdentityServerAuthenticationOptions> configOptions);

View File

@ -40,10 +40,8 @@ namespace Ocelot.DependencyInjection
using Ocelot.Configuration; using Ocelot.Configuration;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
using System.Net.Http; using System.Net.Http;
using Butterfly.Client.AspNetCore;
using Ocelot.Infrastructure; using Ocelot.Infrastructure;
using Ocelot.Infrastructure.Consul; using Ocelot.Infrastructure.Consul;
using Butterfly.Client.Tracing;
using Ocelot.Middleware.Multiplexer; using Ocelot.Middleware.Multiplexer;
using ServiceDiscovery.Providers; using ServiceDiscovery.Providers;
using Steeltoe.Common.Discovery; using Steeltoe.Common.Discovery;
@ -228,12 +226,6 @@ namespace Ocelot.DependencyInjection
return this; return this;
} }
public IOcelotBuilder AddOpenTracing(Action<ButterflyOptions> settings)
{
_services.AddButterfly(settings);
return this;
}
public IOcelotBuilder AddStoreOcelotConfigurationInConsul() public IOcelotBuilder AddStoreOcelotConfigurationInConsul()
{ {
_services.AddHostedService<FileConfigurationPoller>(); _services.AddHostedService<FileConfigurationPoller>();

View File

@ -2,26 +2,20 @@
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DiagnosticAdapter; using Microsoft.Extensions.DiagnosticAdapter;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Butterfly.Client.AspNetCore;
using Butterfly.OpenTracing;
using Ocelot.Middleware; using Ocelot.Middleware;
using Butterfly.Client.Tracing;
using System.Linq;
using System.Collections.Generic;
using Ocelot.Infrastructure.Extensions;
using Ocelot.Requester;
namespace Ocelot.Logging namespace Ocelot.Logging
{ {
public class OcelotDiagnosticListener public class OcelotDiagnosticListener
{ {
private readonly IServiceTracer _tracer;
private readonly IOcelotLogger _logger; private readonly IOcelotLogger _logger;
private readonly ITracer _tracer;
public OcelotDiagnosticListener(IOcelotLoggerFactory factory, IServiceProvider services) public OcelotDiagnosticListener(IOcelotLoggerFactory factory, IServiceProvider serviceProvider)
{ {
_tracer = services.GetService<IServiceTracer>();
_logger = factory.CreateLogger<OcelotDiagnosticListener>(); _logger = factory.CreateLogger<OcelotDiagnosticListener>();
_tracer = serviceProvider.GetService<ITracer>();
} }
[DiagnosticName("Ocelot.MiddlewareException")] [DiagnosticName("Ocelot.MiddlewareException")]
@ -67,29 +61,7 @@ namespace Ocelot.Logging
private void Event(HttpContext httpContext, string @event) private void Event(HttpContext httpContext, string @event)
{ {
// todo - if the user isnt using tracing the code gets here and will blow up on _tracer?.Event(httpContext, @event);
// _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));
} }
} }
} }

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<RuntimeFrameworkVersion>2.0.0</RuntimeFrameworkVersion> <RuntimeFrameworkVersion>2.0.0</RuntimeFrameworkVersion>
@ -25,10 +25,6 @@
<DebugSymbols>True</DebugSymbols> <DebugSymbols>True</DebugSymbols>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Butterfly.Client" Version="0.0.8" />
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8">
<NoWarn>NU1701</NoWarn>
</PackageReference>
<PackageReference Include="FluentValidation" Version="7.6.104" /> <PackageReference Include="FluentValidation" Version="7.6.104" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.6.0" /> <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.6.0" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.1.1" /> <PackageReference Include="Microsoft.AspNetCore" Version="2.1.1" />

View File

@ -2,7 +2,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using Butterfly.Client.Tracing;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Logging; using Ocelot.Logging;

View File

@ -1,21 +1,19 @@
using System; namespace Ocelot.Requester
{
using Logging;
using System;
using System.Net.Http; using System.Net.Http;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Butterfly.Client.Tracing;
using Butterfly.OpenTracing;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
namespace Ocelot.Requester
{
public class OcelotHttpTracingHandler : DelegatingHandler, ITracingHandler public class OcelotHttpTracingHandler : DelegatingHandler, ITracingHandler
{ {
private readonly IServiceTracer _tracer; private readonly ITracer _tracer;
private readonly IRequestScopedDataRepository _repo; private readonly IRequestScopedDataRepository _repo;
private const string PrefixSpanId = "ot-spanId";
public OcelotHttpTracingHandler( public OcelotHttpTracingHandler(
IServiceTracer tracer, ITracer tracer,
IRequestScopedDataRepository repo, IRequestScopedDataRepository repo,
HttpMessageHandler httpMessageHandler = null) HttpMessageHandler httpMessageHandler = null)
{ {
@ -28,46 +26,8 @@ namespace Ocelot.Requester
HttpRequestMessage request, HttpRequestMessage request,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
return _tracer.ChildTraceAsync($"httpclient {request.Method}", DateTimeOffset.UtcNow, span => TracingSendAsync(span, request, cancellationToken));
}
protected virtual async Task<HttpResponseMessage> TracingSendAsync( return _tracer.SendAsync(request, cancellationToken, x => _repo.Add("TraceId", x), (r,c) => base.SendAsync(r, c));
ISpan span,
HttpRequestMessage request,
CancellationToken cancellationToken)
{
if (request.Headers.Contains(PrefixSpanId))
{
request.Headers.Remove(PrefixSpanId);
request.Headers.TryAddWithoutValidation(PrefixSpanId, span.SpanContext.SpanId);
}
_repo.Add("TraceId", 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 base.SendAsync(request, cancellationToken);
span.Log(LogField.CreateNew().ClientReceive());
return responseMessage;
} }
} }
} }

View File

@ -1,13 +1,13 @@
namespace Ocelot.Requester namespace Ocelot.Requester
{ {
using System; using System;
using Butterfly.Client.Tracing; using Logging;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
public class TracingHandlerFactory : ITracingHandlerFactory public class TracingHandlerFactory : ITracingHandlerFactory
{ {
private readonly IServiceTracer _tracer; private readonly ITracer _tracer;
private readonly IRequestScopedDataRepository _repo; private readonly IRequestScopedDataRepository _repo;
public TracingHandlerFactory( public TracingHandlerFactory(
@ -15,7 +15,7 @@ namespace Ocelot.Requester
IRequestScopedDataRepository repo) IRequestScopedDataRepository repo)
{ {
_repo = repo; _repo = repo;
_tracer = services.GetService<IServiceTracer>(); _tracer = services.GetService<ITracer>();
} }
public ITracingHandler Get() public ITracingHandler Get()

View File

@ -1,284 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Ocelot.Configuration.File;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
using Butterfly.Client.AspNetCore;
using static Rafty.Infrastructure.Wait;
namespace Ocelot.AcceptanceTests
{
using Xunit.Abstractions;
public class ButterflyTracingTests : IDisposable
{
private IWebHost _serviceOneBuilder;
private IWebHost _serviceTwoBuilder;
private IWebHost _fakeButterfly;
private readonly Steps _steps;
private string _downstreamPathOne;
private string _downstreamPathTwo;
private int _butterflyCalled;
private readonly ITestOutputHelper _output;
public ButterflyTracingTests(ITestOutputHelper output)
{
_output = output;
_steps = new Steps();
}
[Fact]
public void should_forward_tracing_information_from_ocelot_and_downstream_services()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/api/values",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51887,
}
},
UpstreamPathTemplate = "/api001/values",
UpstreamHttpMethod = new List<string> { "Get" },
HttpHandlerOptions = new FileHttpHandlerOptions
{
UseTracing = true
},
QoSOptions = new FileQoSOptions
{
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak = 10,
TimeoutValue = 5000
}
},
new FileReRoute
{
DownstreamPathTemplate = "/api/values",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51388,
}
},
UpstreamPathTemplate = "/api002/values",
UpstreamHttpMethod = new List<string> { "Get" },
HttpHandlerOptions = new FileHttpHandlerOptions
{
UseTracing = true
},
QoSOptions = new FileQoSOptions
{
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak = 10,
TimeoutValue = 5000
}
}
}
};
var butterflyUrl = "http://localhost:9618";
this.Given(x => GivenFakeButterfly(butterflyUrl))
.And(x => GivenServiceOneIsRunning("http://localhost:51887", "/api/values", 200, "Hello from Laura", butterflyUrl))
.And(x => GivenServiceTwoIsRunning("http://localhost:51388", "/api/values", 200, "Hello from Tom", butterflyUrl))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunningUsingButterfly(butterflyUrl))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/api001/values"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/api002/values"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Tom"))
.BDDfy();
var commandOnAllStateMachines = WaitFor(10000).Until(() => _butterflyCalled >= 4);
_output.WriteLine($"_butterflyCalled is {_butterflyCalled}");
commandOnAllStateMachines.ShouldBeTrue();
}
[Fact]
public void should_return_tracing_header()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/api/values",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51387,
}
},
UpstreamPathTemplate = "/api001/values",
UpstreamHttpMethod = new List<string> { "Get" },
HttpHandlerOptions = new FileHttpHandlerOptions
{
UseTracing = true
},
QoSOptions = new FileQoSOptions
{
ExceptionsAllowedBeforeBreaking = 3,
DurationOfBreak = 10,
TimeoutValue = 5000
},
DownstreamHeaderTransform = new Dictionary<string, string>()
{
{"Trace-Id", "{TraceId}"},
{"Tom", "Laura"}
}
}
}
};
var butterflyUrl = "http://localhost:9618";
this.Given(x => GivenFakeButterfly(butterflyUrl))
.And(x => GivenServiceOneIsRunning("http://localhost:51387", "/api/values", 200, "Hello from Laura", butterflyUrl))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunningUsingButterfly(butterflyUrl))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/api001/values"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.And(x => _steps.ThenTheTraceHeaderIsSet("Trace-Id"))
.And(x => _steps.ThenTheResponseHeaderIs("Tom", "Laura"))
.BDDfy();
}
private void GivenServiceOneIsRunning(string baseUrl, string basePath, int statusCode, string responseBody, string butterflyUrl)
{
_serviceOneBuilder = new WebHostBuilder()
.UseUrls(baseUrl)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.ConfigureServices(services => {
services.AddButterfly(option =>
{
option.CollectorUrl = butterflyUrl;
option.Service = "Service One";
option.IgnoredRoutesRegexPatterns = new string[0];
});
})
.Configure(app =>
{
app.UsePathBase(basePath);
app.Run(async context =>
{
_downstreamPathOne = !string.IsNullOrEmpty(context.Request.PathBase.Value) ? context.Request.PathBase.Value : context.Request.Path.Value;
if(_downstreamPathOne != basePath)
{
context.Response.StatusCode = statusCode;
await context.Response.WriteAsync("downstream path didnt match base path");
}
else
{
context.Response.StatusCode = statusCode;
await context.Response.WriteAsync(responseBody);
}
});
})
.Build();
_serviceOneBuilder.Start();
}
private void GivenFakeButterfly(string baseUrl)
{
_fakeButterfly = new WebHostBuilder()
.UseUrls(baseUrl)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.Configure(app =>
{
app.Run(async context =>
{
_butterflyCalled++;
await context.Response.WriteAsync("OK...");
});
})
.Build();
_fakeButterfly.Start();
}
private void GivenServiceTwoIsRunning(string baseUrl, string basePath, int statusCode, string responseBody, string butterflyUrl)
{
_serviceTwoBuilder = new WebHostBuilder()
.UseUrls(baseUrl)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.ConfigureServices(services => {
services.AddButterfly(option =>
{
option.CollectorUrl = butterflyUrl;
option.Service = "Service Two";
option.IgnoredRoutesRegexPatterns = new string[0];
});
})
.Configure(app =>
{
app.UsePathBase(basePath);
app.Run(async context =>
{
_downstreamPathTwo = !string.IsNullOrEmpty(context.Request.PathBase.Value) ? context.Request.PathBase.Value : context.Request.Path.Value;
if(_downstreamPathTwo != basePath)
{
context.Response.StatusCode = statusCode;
await context.Response.WriteAsync("downstream path didnt match base path");
}
else
{
context.Response.StatusCode = statusCode;
await context.Response.WriteAsync(responseBody);
}
});
})
.Build();
_serviceTwoBuilder.Start();
}
internal void ThenTheDownstreamUrlPathShouldBe(string expectedDownstreamPathOne, string expectedDownstreamPath)
{
_downstreamPathOne.ShouldBe(expectedDownstreamPathOne);
_downstreamPathTwo.ShouldBe(expectedDownstreamPath);
}
public void Dispose()
{
_serviceOneBuilder?.Dispose();
_serviceTwoBuilder?.Dispose();
_fakeButterfly?.Dispose();
_steps.Dispose();
}
}
}

View File

@ -31,6 +31,7 @@ using static Ocelot.Infrastructure.Wait;
namespace Ocelot.AcceptanceTests namespace Ocelot.AcceptanceTests
{ {
using Butterfly;
using Configuration.Repository; using Configuration.Repository;
using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
using MediaTypeHeaderValue = System.Net.Http.Headers.MediaTypeHeaderValue; using MediaTypeHeaderValue = System.Net.Http.Headers.MediaTypeHeaderValue;
@ -146,44 +147,6 @@ namespace Ocelot.AcceptanceTests
_ocelotClient = _ocelotServer.CreateClient(); _ocelotClient = _ocelotServer.CreateClient();
} }
internal void GivenOcelotIsRunningUsingButterfly(string butterflyUrl)
{
_webHostBuilder = new WebHostBuilder();
_webHostBuilder
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: false);
config.AddJsonFile("ocelot.json", optional: true, reloadOnChange: false);
config.AddEnvironmentVariables();
})
.ConfigureServices(s =>
{
s.AddOcelot()
.AddOpenTracing(option =>
{
//this is the url that the butterfly collector server is running on...
option.CollectorUrl = butterflyUrl;
option.Service = "Ocelot";
});
})
.Configure(app =>
{
app.Use(async (context, next) =>
{
await next.Invoke();
});
app.UseOcelot().Wait();
});
_ocelotServer = new TestServer(_webHostBuilder);
_ocelotClient = _ocelotServer.CreateClient();
}
internal void GivenIWait(int wait) internal void GivenIWait(int wait)
{ {
Thread.Sleep(wait); Thread.Sleep(wait);

View File

@ -1,6 +1,4 @@
using System; using System;
using Butterfly.Client.Tracing;
using Butterfly.OpenTracing;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Configuration.Creator; using Ocelot.Configuration.Creator;
@ -12,6 +10,12 @@ using Xunit;
namespace Ocelot.UnitTests.Configuration namespace Ocelot.UnitTests.Configuration
{ {
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Ocelot.Logging;
public class HttpHandlerOptionsCreatorTests public class HttpHandlerOptionsCreatorTests
{ {
private IHttpHandlerOptionsCreator _httpHandlerOptionsCreator; private IHttpHandlerOptionsCreator _httpHandlerOptionsCreator;
@ -155,23 +159,21 @@ namespace Ocelot.UnitTests.Configuration
private void GivenARealTracer() private void GivenARealTracer()
{ {
var tracer = new RealTracer(); var tracer = new FakeTracer();
_serviceCollection.AddSingleton<IServiceTracer, RealTracer>(); _serviceCollection.AddSingleton<ITracer, FakeTracer>();
_serviceProvider = _serviceCollection.BuildServiceProvider(); _serviceProvider = _serviceCollection.BuildServiceProvider();
_httpHandlerOptionsCreator = new HttpHandlerOptionsCreator(_serviceProvider); _httpHandlerOptionsCreator = new HttpHandlerOptionsCreator(_serviceProvider);
} }
class RealTracer : IServiceTracer class FakeTracer : ITracer
{ {
public ITracer Tracer => throw new NotImplementedException(); public void Event(HttpContext httpContext, string @event)
{
throw new NotImplementedException();
}
public string ServiceName => throw new NotImplementedException(); public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken, Action<string> addTraceIdToRepo,
Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> baseSendAsync)
public string Environment => throw new NotImplementedException();
public string Identity => throw new NotImplementedException();
public ISpan Start(ISpanBuilder spanBuilder)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }

View File

@ -23,6 +23,8 @@ using Ocelot.Middleware.Multiplexer;
namespace Ocelot.UnitTests.DependencyInjection namespace Ocelot.UnitTests.DependencyInjection
{ {
using Butterfly;
public class OcelotBuilderTests public class OcelotBuilderTests
{ {
private readonly IServiceCollection _services; private readonly IServiceCollection _services;
@ -140,15 +142,6 @@ namespace Ocelot.UnitTests.DependencyInjection
.BDDfy(); .BDDfy();
} }
[Fact]
public void should_set_up_tracing()
{
this.Given(x => WhenISetUpOcelotServices())
.When(x => WhenISetUpOpentracing())
.When(x => WhenIAccessOcelotHttpTracingHandler())
.BDDfy();
}
[Fact] [Fact]
public void should_set_up_without_passing_in_config() public void should_set_up_without_passing_in_config()
{ {
@ -387,24 +380,6 @@ namespace Ocelot.UnitTests.DependencyInjection
} }
} }
private void WhenISetUpOpentracing()
{
try
{
_ocelotBuilder.AddOpenTracing(
option =>
{
option.CollectorUrl = "http://localhost:9618";
option.Service = "Ocelot.ManualTest";
}
);
}
catch (Exception e)
{
_ex = e;
}
}
private void WhenIAccessLoggerFactory() private void WhenIAccessLoggerFactory()
{ {
try try

View File

@ -1,27 +1,27 @@
namespace Ocelot.UnitTests.Requester
{
using System; using System;
using Butterfly.Client.Tracing;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Moq; using Moq;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Requester; using Ocelot.Requester;
using Shouldly; using Shouldly;
using Xunit; using Xunit;
using Ocelot.Logging;
namespace Ocelot.UnitTests.Requester
{
public class TracingHandlerFactoryTests public class TracingHandlerFactoryTests
{ {
private TracingHandlerFactory _factory; private readonly TracingHandlerFactory _factory;
private Mock<IServiceTracer> _tracer; private Mock<ITracer> _tracer;
private IServiceCollection _serviceCollection; private IServiceCollection _serviceCollection;
private IServiceProvider _serviceProvider; private IServiceProvider _serviceProvider;
private Mock<IRequestScopedDataRepository> _repo; private Mock<IRequestScopedDataRepository> _repo;
public TracingHandlerFactoryTests() public TracingHandlerFactoryTests()
{ {
_tracer = new Mock<IServiceTracer>(); _tracer = new Mock<ITracer>();
_serviceCollection = new ServiceCollection(); _serviceCollection = new ServiceCollection();
_serviceCollection.AddSingleton<IServiceTracer>(_tracer.Object); _serviceCollection.AddSingleton<ITracer>(_tracer.Object);
_serviceProvider = _serviceCollection.BuildServiceProvider(); _serviceProvider = _serviceCollection.BuildServiceProvider();
_repo = new Mock<IRequestScopedDataRepository>(); _repo = new Mock<IRequestScopedDataRepository>();
_factory = new TracingHandlerFactory(_serviceProvider, _repo.Object); _factory = new TracingHandlerFactory(_serviceProvider, _repo.Object);