Added some logging at last!

This commit is contained in:
TomPallister 2016-11-04 20:17:15 +00:00
parent 47afc850ff
commit 8582ba45a9
19 changed files with 352 additions and 73 deletions

View File

@ -21,7 +21,7 @@ to do this.
## How to install ## How to install
Ocelot is designed to work with ASP.NET core only and is currently built to .NET Standard 1.4 [this](https://docs.microsoft.com/en-us/dotnet/articles/standard/library) documentation may prove helpful when working out if Ocelot would be suitable for you. Ocelot is designed to work with ASP.NET core only and is currently built to netcoreapp1.4 [this](https://docs.microsoft.com/en-us/dotnet/articles/standard/library) documentation may prove helpful when working out if Ocelot would be suitable for you.
Install Ocelot and it's dependecies using nuget. At the moment all we have is the pre version. Once we have something working in a half decent way we will drop a version. Install Ocelot and it's dependecies using nuget. At the moment all we have is the pre version. Once we have something working in a half decent way we will drop a version.
@ -79,7 +79,8 @@ This is pretty much all you need to get going.......more to come!
## Logging ## Logging
Ocelot uses the standard logging interfaces ILoggerFactory / ILogger<T> as such you can use any logging provider you like such as default, nlog, serilog or whatever you want. Ocelot uses the standard logging interfaces ILoggerFactory / ILogger<T> at the moment. This is encapsulated in IOcelotLogger with
an implementation for the standard asp.net core logging stuff at the moment.
## Caching ## Caching

View File

@ -2,10 +2,12 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Ocelot.Authentication.Handler.Factory; using Ocelot.Authentication.Handler.Factory;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Errors; using Ocelot.Errors;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Middleware; using Ocelot.Middleware;
namespace Ocelot.Authentication.Middleware namespace Ocelot.Authentication.Middleware
@ -15,45 +17,64 @@ namespace Ocelot.Authentication.Middleware
private readonly RequestDelegate _next; private readonly RequestDelegate _next;
private readonly IApplicationBuilder _app; private readonly IApplicationBuilder _app;
private readonly IAuthenticationHandlerFactory _authHandlerFactory; private readonly IAuthenticationHandlerFactory _authHandlerFactory;
private readonly IOcelotLogger _logger;
public AuthenticationMiddleware(RequestDelegate next, public AuthenticationMiddleware(RequestDelegate next,
IApplicationBuilder app, IApplicationBuilder app,
IRequestScopedDataRepository requestScopedDataRepository, IRequestScopedDataRepository requestScopedDataRepository,
IAuthenticationHandlerFactory authHandlerFactory) IAuthenticationHandlerFactory authHandlerFactory,
IOcelotLoggerFactory loggerFactory)
: base(requestScopedDataRepository) : base(requestScopedDataRepository)
{ {
_next = next; _next = next;
_authHandlerFactory = authHandlerFactory; _authHandlerFactory = authHandlerFactory;
_app = app; _app = app;
_logger = loggerFactory.CreateLogger<AuthenticationMiddleware>();
} }
public async Task Invoke(HttpContext context) public async Task Invoke(HttpContext context)
{ {
_logger.LogDebug("started authentication");
if (IsAuthenticatedRoute(DownstreamRoute.ReRoute)) if (IsAuthenticatedRoute(DownstreamRoute.ReRoute))
{ {
var authenticationHandler = _authHandlerFactory.Get(_app, DownstreamRoute.ReRoute.AuthenticationOptions); var authenticationHandler = _authHandlerFactory.Get(_app, DownstreamRoute.ReRoute.AuthenticationOptions);
if (!authenticationHandler.IsError) if (!authenticationHandler.IsError)
{ {
_logger.LogDebug("calling authentication handler for ReRoute");
await authenticationHandler.Data.Handler.Invoke(context); await authenticationHandler.Data.Handler.Invoke(context);
} }
else else
{ {
_logger.LogDebug("there was an error getting authentication handler for ReRoute");
SetPipelineError(authenticationHandler.Errors); SetPipelineError(authenticationHandler.Errors);
} }
if (context.User.Identity.IsAuthenticated) if (context.User.Identity.IsAuthenticated)
{ {
_logger.LogDebug("the user was authenticated");
await _next.Invoke(context); await _next.Invoke(context);
_logger.LogDebug("succesfully called next middleware");
} }
else else
{ {
SetPipelineError(new List<Error> {new UnauthenticatedError($"Request for authenticated route {context.Request.Path} by {context.User.Identity.Name} was unauthenticated")}); _logger.LogDebug("the user was not authenticated");
SetPipelineError(new List<Error> { new UnauthenticatedError($"Request for authenticated route {context.Request.Path} by {context.User.Identity.Name} was unauthenticated") });
} }
} }
else else
{ {
_logger.LogDebug("calling next middleware");
await _next.Invoke(context); await _next.Invoke(context);
_logger.LogDebug("succesfully called next middleware");
} }
} }

View File

@ -1,4 +1,6 @@
using Ocelot.Infrastructure.RequestData; using Microsoft.Extensions.Logging;
using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Responses; using Ocelot.Responses;
namespace Ocelot.Authorisation.Middleware namespace Ocelot.Authorisation.Middleware
@ -13,34 +15,49 @@ namespace Ocelot.Authorisation.Middleware
{ {
private readonly RequestDelegate _next; private readonly RequestDelegate _next;
private readonly IAuthoriser _authoriser; private readonly IAuthoriser _authoriser;
private readonly IOcelotLogger _logger;
public AuthorisationMiddleware(RequestDelegate next, public AuthorisationMiddleware(RequestDelegate next,
IRequestScopedDataRepository requestScopedDataRepository, IRequestScopedDataRepository requestScopedDataRepository,
IAuthoriser authoriser) IAuthoriser authoriser,
IOcelotLoggerFactory loggerFactory)
: base(requestScopedDataRepository) : base(requestScopedDataRepository)
{ {
_next = next; _next = next;
_authoriser = authoriser; _authoriser = authoriser;
_logger = loggerFactory.CreateLogger<AuthorisationMiddleware>();
} }
public async Task Invoke(HttpContext context) public async Task Invoke(HttpContext context)
{ {
_logger.LogDebug("started authorisation");
if (DownstreamRoute.ReRoute.IsAuthorised) if (DownstreamRoute.ReRoute.IsAuthorised)
{ {
_logger.LogDebug("route is authorised");
var authorised = _authoriser.Authorise(context.User, DownstreamRoute.ReRoute.RouteClaimsRequirement); var authorised = _authoriser.Authorise(context.User, DownstreamRoute.ReRoute.RouteClaimsRequirement);
if (authorised.IsError) if (authorised.IsError)
{ {
_logger.LogDebug("error authorising user");
SetPipelineError(authorised.Errors); SetPipelineError(authorised.Errors);
return; return;
} }
if (IsAuthorised(authorised)) if (IsAuthorised(authorised))
{ {
_logger.LogDebug("user is authorised calling next middleware");
await _next.Invoke(context); await _next.Invoke(context);
_logger.LogDebug("succesfully called next middleware");
} }
else else
{ {
_logger.LogDebug("user is not authorised setting pipeline error");
SetPipelineError(new List<Error> SetPipelineError(new List<Error>
{ {
new UnauthorisedError( new UnauthorisedError(
@ -50,7 +67,11 @@ namespace Ocelot.Authorisation.Middleware
} }
else else
{ {
_logger.LogDebug("AuthorisationMiddleware.Invoke route is not authorised calling next middleware");
await _next.Invoke(context); await _next.Invoke(context);
_logger.LogDebug("succesfully called next middleware");
} }
} }

View File

@ -4,6 +4,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Middleware; using Ocelot.Middleware;
namespace Ocelot.Cache.Middleware namespace Ocelot.Cache.Middleware
@ -11,11 +12,11 @@ namespace Ocelot.Cache.Middleware
public class OutputCacheMiddleware : OcelotMiddleware public class OutputCacheMiddleware : OcelotMiddleware
{ {
private readonly RequestDelegate _next; private readonly RequestDelegate _next;
private readonly ILogger _logger; private readonly IOcelotLogger _logger;
private readonly IOcelotCache<HttpResponseMessage> _outputCache; private readonly IOcelotCache<HttpResponseMessage> _outputCache;
public OutputCacheMiddleware(RequestDelegate next, public OutputCacheMiddleware(RequestDelegate next,
ILoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
IRequestScopedDataRepository scopedDataRepository, IRequestScopedDataRepository scopedDataRepository,
IOcelotCache<HttpResponseMessage> outputCache) IOcelotCache<HttpResponseMessage> outputCache)
:base(scopedDataRepository) :base(scopedDataRepository)
@ -35,26 +36,30 @@ namespace Ocelot.Cache.Middleware
return; return;
} }
_logger.LogDebug("OutputCacheMiddleware.Invoke stared checking cache for downstreamUrlKey", downstreamUrlKey); _logger.LogDebug("started checking cache for {downstreamUrlKey}", downstreamUrlKey);
var cached = _outputCache.Get(downstreamUrlKey); var cached = _outputCache.Get(downstreamUrlKey);
if (cached != null) if (cached != null)
{ {
_logger.LogDebug("cache entry exists for {downstreamUrlKey}", downstreamUrlKey);
SetHttpResponseMessageThisRequest(cached); SetHttpResponseMessageThisRequest(cached);
_logger.LogDebug("OutputCacheMiddleware.Invoke finished returned cached response for downstreamUrlKey", downstreamUrlKey); _logger.LogDebug("finished returned cached response for {downstreamUrlKey}", downstreamUrlKey);
return; return;
} }
_logger.LogDebug("OutputCacheMiddleware.Invoke no resonse cached for downstreamUrlKey", downstreamUrlKey); _logger.LogDebug("no resonse cached for {downstreamUrlKey}", downstreamUrlKey);
await _next.Invoke(context); await _next.Invoke(context);
_logger.LogDebug("succesfully called next middleware");
if (PipelineError()) if (PipelineError())
{ {
_logger.LogDebug("OutputCacheMiddleware.Invoke there was a pipeline error for downstreamUrlKey", downstreamUrlKey); _logger.LogDebug("there was a pipeline error for {downstreamUrlKey}", downstreamUrlKey);
return; return;
} }
@ -63,7 +68,7 @@ namespace Ocelot.Cache.Middleware
_outputCache.Add(downstreamUrlKey, response, TimeSpan.FromSeconds(DownstreamRoute.ReRoute.FileCacheOptions.TtlSeconds)); _outputCache.Add(downstreamUrlKey, response, TimeSpan.FromSeconds(DownstreamRoute.ReRoute.FileCacheOptions.TtlSeconds));
_logger.LogDebug("OutputCacheMiddleware.Invoke finished response added to cache for downstreamUrlKey", downstreamUrlKey); _logger.LogDebug("finished response added to cache for {downstreamUrlKey}", downstreamUrlKey);
} }
} }
} }

View File

@ -2,6 +2,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Middleware; using Ocelot.Middleware;
namespace Ocelot.Claims.Middleware namespace Ocelot.Claims.Middleware
@ -10,30 +11,43 @@ namespace Ocelot.Claims.Middleware
{ {
private readonly RequestDelegate _next; private readonly RequestDelegate _next;
private readonly IAddClaimsToRequest _addClaimsToRequest; private readonly IAddClaimsToRequest _addClaimsToRequest;
private readonly IOcelotLogger _logger;
public ClaimsBuilderMiddleware(RequestDelegate next, public ClaimsBuilderMiddleware(RequestDelegate next,
IRequestScopedDataRepository requestScopedDataRepository, IRequestScopedDataRepository requestScopedDataRepository,
IOcelotLoggerFactory loggerFactory,
IAddClaimsToRequest addClaimsToRequest) IAddClaimsToRequest addClaimsToRequest)
: base(requestScopedDataRepository) : base(requestScopedDataRepository)
{ {
_next = next; _next = next;
_addClaimsToRequest = addClaimsToRequest; _addClaimsToRequest = addClaimsToRequest;
_logger = loggerFactory.CreateLogger<ClaimsBuilderMiddleware>();
} }
public async Task Invoke(HttpContext context) public async Task Invoke(HttpContext context)
{ {
_logger.LogDebug("started claims middleware");
if (DownstreamRoute.ReRoute.ClaimsToClaims.Any()) if (DownstreamRoute.ReRoute.ClaimsToClaims.Any())
{ {
_logger.LogDebug("this route has instructions to convert claims to other claims");
var result = _addClaimsToRequest.SetClaimsOnContext(DownstreamRoute.ReRoute.ClaimsToClaims, context); var result = _addClaimsToRequest.SetClaimsOnContext(DownstreamRoute.ReRoute.ClaimsToClaims, context);
if (result.IsError) if (result.IsError)
{ {
_logger.LogDebug("error converting claims to other claims, setting pipeline error");
SetPipelineError(result.Errors); SetPipelineError(result.Errors);
return; return;
} }
} }
_logger.LogDebug("calling next middleware");
await _next.Invoke(context); await _next.Invoke(context);
_logger.LogDebug("succesfully called next middleware");
} }
} }
} }

View File

@ -22,6 +22,7 @@ using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer;
using Ocelot.Headers; using Ocelot.Headers;
using Ocelot.Infrastructure.Claims.Parser; using Ocelot.Infrastructure.Claims.Parser;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.QueryStrings; using Ocelot.QueryStrings;
using Ocelot.Request.Builder; using Ocelot.Request.Builder;
using Ocelot.Requester; using Ocelot.Requester;
@ -57,7 +58,7 @@ namespace Ocelot.DependencyInjection
{ {
services.AddMvcCore().AddJsonFormatters(); services.AddMvcCore().AddJsonFormatters();
services.AddLogging(); services.AddLogging();
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
services.AddSingleton<IRemoveOutputHeaders, RemoveOutputHeaders>(); services.AddSingleton<IRemoveOutputHeaders, RemoveOutputHeaders>();
services.AddSingleton<IOcelotConfigurationProvider, OcelotConfigurationProvider>(); services.AddSingleton<IOcelotConfigurationProvider, OcelotConfigurationProvider>();
services.AddSingleton<IClaimToThingConfigurationParser, ClaimToThingConfigurationParser>(); services.AddSingleton<IClaimToThingConfigurationParser, ClaimToThingConfigurationParser>();

View File

@ -2,6 +2,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Ocelot.DownstreamRouteFinder.Finder; using Ocelot.DownstreamRouteFinder.Finder;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Middleware; using Ocelot.Middleware;
namespace Ocelot.DownstreamRouteFinder.Middleware namespace Ocelot.DownstreamRouteFinder.Middleware
@ -10,31 +11,47 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
{ {
private readonly RequestDelegate _next; private readonly RequestDelegate _next;
private readonly IDownstreamRouteFinder _downstreamRouteFinder; private readonly IDownstreamRouteFinder _downstreamRouteFinder;
private readonly IOcelotLogger _logger;
public DownstreamRouteFinderMiddleware(RequestDelegate next, public DownstreamRouteFinderMiddleware(RequestDelegate next,
IOcelotLoggerFactory loggerFactory,
IDownstreamRouteFinder downstreamRouteFinder, IDownstreamRouteFinder downstreamRouteFinder,
IRequestScopedDataRepository requestScopedDataRepository) IRequestScopedDataRepository requestScopedDataRepository)
:base(requestScopedDataRepository) :base(requestScopedDataRepository)
{ {
_next = next; _next = next;
_downstreamRouteFinder = downstreamRouteFinder; _downstreamRouteFinder = downstreamRouteFinder;
_logger = loggerFactory.CreateLogger<DownstreamRouteFinderMiddleware>();
} }
public async Task Invoke(HttpContext context) public async Task Invoke(HttpContext context)
{ {
_logger.LogDebug("started calling downstream route finder middleware");
var upstreamUrlPath = context.Request.Path.ToString(); var upstreamUrlPath = context.Request.Path.ToString();
_logger.LogDebug("upstream url path is {upstreamUrlPath}", upstreamUrlPath);
var downstreamRoute = _downstreamRouteFinder.FindDownstreamRoute(upstreamUrlPath, context.Request.Method); var downstreamRoute = _downstreamRouteFinder.FindDownstreamRoute(upstreamUrlPath, context.Request.Method);
if (downstreamRoute.IsError) if (downstreamRoute.IsError)
{ {
_logger.LogDebug("IDownstreamRouteFinder returned an error, setting pipeline error");
SetPipelineError(downstreamRoute.Errors); SetPipelineError(downstreamRoute.Errors);
return; return;
} }
_logger.LogDebug("downstream template is {downstreamRoute.Data.ReRoute.DownstreamTemplate}", downstreamRoute.Data.ReRoute.DownstreamTemplate);
SetDownstreamRouteForThisRequest(downstreamRoute.Data); SetDownstreamRouteForThisRequest(downstreamRoute.Data);
_logger.LogDebug("calling next middleware");
await _next.Invoke(context); await _next.Invoke(context);
_logger.LogDebug("succesfully called next middleware");
} }
} }
} }

View File

@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Http;
using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer; using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Middleware; using Ocelot.Middleware;
namespace Ocelot.DownstreamUrlCreator.Middleware namespace Ocelot.DownstreamUrlCreator.Middleware
@ -11,29 +12,42 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
{ {
private readonly RequestDelegate _next; private readonly RequestDelegate _next;
private readonly IDownstreamUrlPathPlaceholderReplacer _urlReplacer; private readonly IDownstreamUrlPathPlaceholderReplacer _urlReplacer;
private readonly IOcelotLogger _logger;
public DownstreamUrlCreatorMiddleware(RequestDelegate next, public DownstreamUrlCreatorMiddleware(RequestDelegate next,
IOcelotLoggerFactory loggerFactory,
IDownstreamUrlPathPlaceholderReplacer urlReplacer, IDownstreamUrlPathPlaceholderReplacer urlReplacer,
IRequestScopedDataRepository requestScopedDataRepository) IRequestScopedDataRepository requestScopedDataRepository)
:base(requestScopedDataRepository) :base(requestScopedDataRepository)
{ {
_next = next; _next = next;
_urlReplacer = urlReplacer; _urlReplacer = urlReplacer;
_logger = loggerFactory.CreateLogger<DownstreamUrlCreatorMiddleware>();
} }
public async Task Invoke(HttpContext context) public async Task Invoke(HttpContext context)
{ {
_logger.LogDebug("started calling downstream url creator middleware");
var downstreamUrl = _urlReplacer.Replace(DownstreamRoute.ReRoute.DownstreamTemplate, DownstreamRoute.TemplatePlaceholderNameAndValues); var downstreamUrl = _urlReplacer.Replace(DownstreamRoute.ReRoute.DownstreamTemplate, DownstreamRoute.TemplatePlaceholderNameAndValues);
if (downstreamUrl.IsError) if (downstreamUrl.IsError)
{ {
_logger.LogDebug("IDownstreamUrlPathPlaceholderReplacer returned an error, setting pipeline error");
SetPipelineError(downstreamUrl.Errors); SetPipelineError(downstreamUrl.Errors);
return; return;
} }
_logger.LogDebug("downstream url is {downstreamUrl.Data.Value}", downstreamUrl.Data.Value);
SetDownstreamUrlForThisRequest(downstreamUrl.Data.Value); SetDownstreamUrlForThisRequest(downstreamUrl.Data.Value);
_logger.LogDebug("calling next middleware");
await _next.Invoke(context); await _next.Invoke(context);
_logger.LogDebug("succesfully called next middleware");
} }
} }
} }

View File

@ -0,0 +1,67 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
namespace Ocelot.Errors.Middleware
{
public class ExceptionHandlerMiddleware
{
private readonly RequestDelegate _next;
private readonly IOcelotLogger _logger;
private readonly IRequestScopedDataRepository _requestScopedDataRepository;
public ExceptionHandlerMiddleware(RequestDelegate next,
IOcelotLoggerFactory loggerFactory,
IRequestScopedDataRepository requestScopedDataRepository)
{
_next = next;
_requestScopedDataRepository = requestScopedDataRepository;
_logger = loggerFactory.CreateLogger<ExceptionHandlerMiddleware>();
}
public async Task Invoke(HttpContext context)
{
try
{
_logger.LogDebug("calling middleware");
_requestScopedDataRepository.Add("RequestId", context.TraceIdentifier);
await _next.Invoke(context);
_logger.LogDebug("succesfully called middleware");
}
catch (Exception e)
{
_logger.LogDebug("error calling middleware");
var message = CreateMessage(context, e);
_logger.LogError(message, e);
await SetInternalServerErrorOnResponse(context);
}
}
private static async Task SetInternalServerErrorOnResponse(HttpContext context)
{
context.Response.StatusCode = 500;
context.Response.ContentType = "application/json";
await context.Response.WriteAsync("Internal Server Error");
}
private static string CreateMessage(HttpContext context, Exception e)
{
var message =
$"Exception caught in global error handler, exception message: {e.Message}, exception stack: {e.StackTrace}";
if (e.InnerException != null)
{
message =
$"{message}, inner exception message {e.InnerException.Message}, inner exception stack {e.InnerException.StackTrace}";
}
return $"{message} RequestId: {context.TraceIdentifier}";
}
}
}

View File

@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
namespace Ocelot.Middleware namespace Ocelot.Errors.Middleware
{ {
public static class ExceptionHandlerMiddlewareExtensions public static class ExceptionHandlerMiddlewareExtensions
{ {

View File

@ -0,0 +1,66 @@
using System;
using Microsoft.Extensions.Logging;
using Ocelot.Infrastructure.RequestData;
namespace Ocelot.Logging
{
public interface IOcelotLoggerFactory
{
IOcelotLogger CreateLogger<T>();
}
public class AspDotNetLoggerFactory : IOcelotLoggerFactory
{
private readonly ILoggerFactory _loggerFactory;
private readonly IRequestScopedDataRepository _scopedDataRepository;
public AspDotNetLoggerFactory(ILoggerFactory loggerFactory, IRequestScopedDataRepository scopedDataRepository)
{
_loggerFactory = loggerFactory;
_scopedDataRepository = scopedDataRepository;
}
public IOcelotLogger CreateLogger<T>()
{
var logger = _loggerFactory.CreateLogger<T>();
return new AspDotNetLogger(logger, _scopedDataRepository);
}
}
public interface IOcelotLogger
{
void LogDebug(string message, params object[] args);
void LogError(string message, Exception exception);
}
public class AspDotNetLogger : IOcelotLogger
{
private readonly ILogger _logger;
private readonly IRequestScopedDataRepository _scopedDataRepository;
public AspDotNetLogger(ILogger logger, IRequestScopedDataRepository scopedDataRepository)
{
_logger = logger;
_scopedDataRepository = scopedDataRepository;
}
public void LogDebug(string message, params object[] args)
{
_logger.LogDebug(GetMessageWithRequestId(message), args);
}
public void LogError(string message, Exception exception)
{
_logger.LogError(GetMessageWithRequestId(message), exception);
}
private string GetMessageWithRequestId(string message)
{
var requestId = _scopedDataRepository.Get<string>("RequestId");
return requestId.IsError
? $"{message} : RequestId: Error"
: $"{message} : RequestId: {requestId.Data}";
}
}
}

View File

@ -1,49 +0,0 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
namespace Ocelot.Middleware
{
public class ExceptionHandlerMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
public ExceptionHandlerMiddleware(RequestDelegate next,
ILoggerFactory loggerFactory)
{
_next = next;
_logger = loggerFactory.CreateLogger<ExceptionHandlerMiddleware>();
}
public async Task Invoke(HttpContext context)
{
try
{
await _next.Invoke(context);
}
catch (Exception e)
{
var message = CreateMessage(context, e);
_logger.LogError(new EventId(1, "Ocelot Global Error"), message, e);
context.Response.StatusCode = 500;
context.Response.ContentType = "application/json";
await context.Response.WriteAsync("Internal Server Error");
}
}
private static string CreateMessage(HttpContext context, Exception e)
{
var message =
$"RequestId: {context.TraceIdentifier}, Exception caught in global error handler, exception message: {e.Message}, exception stack: {e.StackTrace}";
if (e.InnerException != null)
{
message =
$"{message}, inner exception message {e.InnerException.Message}, inner exception stack {e.InnerException.StackTrace}";
}
return message;
}
}
}

View File

@ -4,6 +4,7 @@ using Ocelot.Cache.Middleware;
using Ocelot.Claims.Middleware; using Ocelot.Claims.Middleware;
using Ocelot.DownstreamRouteFinder.Middleware; using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.DownstreamUrlCreator.Middleware; using Ocelot.DownstreamUrlCreator.Middleware;
using Ocelot.Errors.Middleware;
using Ocelot.Headers.Middleware; using Ocelot.Headers.Middleware;
using Ocelot.QueryStrings.Middleware; using Ocelot.QueryStrings.Middleware;
using Ocelot.Request.Middleware; using Ocelot.Request.Middleware;

View File

@ -8,10 +8,12 @@ using Microsoft.Extensions.DependencyInjection;
using Moq; using Moq;
using Ocelot.Authentication.Handler.Factory; using Ocelot.Authentication.Handler.Factory;
using Ocelot.Authentication.Middleware; using Ocelot.Authentication.Middleware;
using Ocelot.Cache.Middleware;
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Responses; using Ocelot.Responses;
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
@ -27,15 +29,19 @@ namespace Ocelot.UnitTests.Authentication
private readonly HttpClient _client; private readonly HttpClient _client;
private HttpResponseMessage _result; private HttpResponseMessage _result;
private OkResponse<DownstreamRoute> _downstreamRoute; private OkResponse<DownstreamRoute> _downstreamRoute;
private Mock<IOcelotLoggerFactory> _mockLoggerFactory;
public AuthenticationMiddlewareTests() public AuthenticationMiddlewareTests()
{ {
_url = "http://localhost:51879"; _url = "http://localhost:51879";
_scopedRepository = new Mock<IRequestScopedDataRepository>(); _scopedRepository = new Mock<IRequestScopedDataRepository>();
_authFactory = new Mock<IAuthenticationHandlerFactory>(); _authFactory = new Mock<IAuthenticationHandlerFactory>();
SetUpLogger();
var builder = new WebHostBuilder() var builder = new WebHostBuilder()
.ConfigureServices(x => .ConfigureServices(x =>
{ {
x.AddSingleton(_mockLoggerFactory.Object);
x.AddSingleton(_authFactory.Object); x.AddSingleton(_authFactory.Object);
x.AddSingleton(_scopedRepository.Object); x.AddSingleton(_scopedRepository.Object);
}) })
@ -62,6 +68,17 @@ namespace Ocelot.UnitTests.Authentication
.BDDfy(); .BDDfy();
} }
private void SetUpLogger()
{
_mockLoggerFactory = new Mock<IOcelotLoggerFactory>();
var logger = new Mock<IOcelotLogger>();
_mockLoggerFactory
.Setup(x => x.CreateLogger<AuthenticationMiddleware>())
.Returns(logger.Object);
}
private void ThenNoExceptionsAreThrown() private void ThenNoExceptionsAreThrown()
{ {
//todo not suck //todo not suck

View File

@ -8,10 +8,12 @@ using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Moq; using Moq;
using Ocelot.Authorisation; using Ocelot.Authorisation;
using Ocelot.Cache.Middleware;
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Responses; using Ocelot.Responses;
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
@ -29,15 +31,19 @@ namespace Ocelot.UnitTests.Authorization
private readonly HttpClient _client; private readonly HttpClient _client;
private HttpResponseMessage _result; private HttpResponseMessage _result;
private OkResponse<DownstreamRoute> _downstreamRoute; private OkResponse<DownstreamRoute> _downstreamRoute;
private Mock<IOcelotLoggerFactory> _mockLoggerFactory;
public AuthorisationMiddlewareTests() public AuthorisationMiddlewareTests()
{ {
_url = "http://localhost:51879"; _url = "http://localhost:51879";
_scopedRepository = new Mock<IRequestScopedDataRepository>(); _scopedRepository = new Mock<IRequestScopedDataRepository>();
_authService = new Mock<IAuthoriser>(); _authService = new Mock<IAuthoriser>();
SetUpLogger();
var builder = new WebHostBuilder() var builder = new WebHostBuilder()
.ConfigureServices(x => .ConfigureServices(x =>
{ {
x.AddSingleton(_mockLoggerFactory.Object);
x.AddSingleton(_authService.Object); x.AddSingleton(_authService.Object);
x.AddSingleton(_scopedRepository.Object); x.AddSingleton(_scopedRepository.Object);
}) })
@ -65,6 +71,17 @@ namespace Ocelot.UnitTests.Authorization
.BDDfy(); .BDDfy();
} }
private void SetUpLogger()
{
_mockLoggerFactory = new Mock<IOcelotLoggerFactory>();
var logger = new Mock<IOcelotLogger>();
_mockLoggerFactory
.Setup(x => x.CreateLogger<AuthorisationMiddleware>())
.Returns(logger.Object);
}
private void GivenTheAuthServiceReturns(Response<bool> expected) private void GivenTheAuthServiceReturns(Response<bool> expected)
{ {
_authService _authService

View File

@ -14,6 +14,7 @@ using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Responses; using Ocelot.Responses;
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
@ -24,7 +25,7 @@ namespace Ocelot.UnitTests.Cache
{ {
private readonly Mock<IOcelotCache<HttpResponseMessage>> _cacheManager; private readonly Mock<IOcelotCache<HttpResponseMessage>> _cacheManager;
private readonly Mock<IRequestScopedDataRepository> _scopedRepo; private readonly Mock<IRequestScopedDataRepository> _scopedRepo;
private Mock<IOcelotLoggerFactory> _mockLoggerFactory;
private readonly string _url; private readonly string _url;
private readonly TestServer _server; private readonly TestServer _server;
private readonly HttpClient _client; private readonly HttpClient _client;
@ -35,11 +36,15 @@ namespace Ocelot.UnitTests.Cache
{ {
_cacheManager = new Mock<IOcelotCache<HttpResponseMessage>>(); _cacheManager = new Mock<IOcelotCache<HttpResponseMessage>>();
_scopedRepo = new Mock<IRequestScopedDataRepository>(); _scopedRepo = new Mock<IRequestScopedDataRepository>();
SetUpLogger();
_url = "http://localhost:51879"; _url = "http://localhost:51879";
var builder = new WebHostBuilder() var builder = new WebHostBuilder()
.ConfigureServices(x => .ConfigureServices(x =>
{ {
x.AddLogging(); x.AddLogging();
x.AddSingleton(_mockLoggerFactory.Object);
x.AddSingleton(_cacheManager.Object); x.AddSingleton(_cacheManager.Object);
x.AddSingleton(_scopedRepo.Object); x.AddSingleton(_scopedRepo.Object);
}) })
@ -80,6 +85,17 @@ namespace Ocelot.UnitTests.Cache
.BDDfy(); .BDDfy();
} }
private void SetUpLogger()
{
_mockLoggerFactory = new Mock<IOcelotLoggerFactory>();
var logger = new Mock<IOcelotLogger>();
_mockLoggerFactory
.Setup(x => x.CreateLogger<OutputCacheMiddleware>())
.Returns(logger.Object);
}
private void GivenTheDownstreamRouteIs() private void GivenTheDownstreamRouteIs()
{ {
var reRoute = new ReRouteBuilder().WithIsCached(true).WithCacheOptions(new CacheOptions(100)).Build(); var reRoute = new ReRouteBuilder().WithIsCached(true).WithCacheOptions(new CacheOptions(100)).Build();

View File

@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.TestHost; using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Moq; using Moq;
using Ocelot.Cache.Middleware;
using Ocelot.Claims; using Ocelot.Claims;
using Ocelot.Claims.Middleware; using Ocelot.Claims.Middleware;
using Ocelot.Configuration; using Ocelot.Configuration;
@ -14,6 +15,7 @@ using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Responses; using Ocelot.Responses;
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
@ -29,15 +31,19 @@ namespace Ocelot.UnitTests.Claims
private readonly HttpClient _client; private readonly HttpClient _client;
private Response<DownstreamRoute> _downstreamRoute; private Response<DownstreamRoute> _downstreamRoute;
private HttpResponseMessage _result; private HttpResponseMessage _result;
private Mock<IOcelotLoggerFactory> _mockLoggerFactory;
public ClaimsBuilderMiddlewareTests() public ClaimsBuilderMiddlewareTests()
{ {
_url = "http://localhost:51879"; _url = "http://localhost:51879";
_scopedRepository = new Mock<IRequestScopedDataRepository>(); _scopedRepository = new Mock<IRequestScopedDataRepository>();
_addHeaders = new Mock<IAddClaimsToRequest>(); _addHeaders = new Mock<IAddClaimsToRequest>();
SetUpLogger();
var builder = new WebHostBuilder() var builder = new WebHostBuilder()
.ConfigureServices(x => .ConfigureServices(x =>
{ {
x.AddSingleton(_mockLoggerFactory.Object);
x.AddSingleton(_addHeaders.Object); x.AddSingleton(_addHeaders.Object);
x.AddSingleton(_scopedRepository.Object); x.AddSingleton(_scopedRepository.Object);
}) })
@ -74,6 +80,17 @@ namespace Ocelot.UnitTests.Claims
.BDDfy(); .BDDfy();
} }
private void SetUpLogger()
{
_mockLoggerFactory = new Mock<IOcelotLoggerFactory>();
var logger = new Mock<IOcelotLogger>();
_mockLoggerFactory
.Setup(x => x.CreateLogger<ClaimsBuilderMiddleware>())
.Returns(logger.Object);
}
private void GivenTheAddClaimsToRequestReturns() private void GivenTheAddClaimsToRequestReturns()
{ {
_addHeaders _addHeaders

View File

@ -6,12 +6,14 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost; using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Moq; using Moq;
using Ocelot.Claims.Middleware;
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.Finder; using Ocelot.DownstreamRouteFinder.Finder;
using Ocelot.DownstreamRouteFinder.Middleware; using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Responses; using Ocelot.Responses;
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
@ -27,16 +29,19 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
private readonly HttpClient _client; private readonly HttpClient _client;
private Response<DownstreamRoute> _downstreamRoute; private Response<DownstreamRoute> _downstreamRoute;
private HttpResponseMessage _result; private HttpResponseMessage _result;
private Mock<IOcelotLoggerFactory> _mockLoggerFactory;
public DownstreamRouteFinderMiddlewareTests() public DownstreamRouteFinderMiddlewareTests()
{ {
_url = "http://localhost:51879"; _url = "http://localhost:51879";
_downstreamRouteFinder = new Mock<IDownstreamRouteFinder>(); _downstreamRouteFinder = new Mock<IDownstreamRouteFinder>();
_scopedRepository = new Mock<IRequestScopedDataRepository>(); _scopedRepository = new Mock<IRequestScopedDataRepository>();
SetUpLogger();
var builder = new WebHostBuilder() var builder = new WebHostBuilder()
.ConfigureServices(x => .ConfigureServices(x =>
{ {
x.AddSingleton(_mockLoggerFactory.Object);
x.AddSingleton(_downstreamRouteFinder.Object); x.AddSingleton(_downstreamRouteFinder.Object);
x.AddSingleton(_scopedRepository.Object); x.AddSingleton(_scopedRepository.Object);
}) })
@ -63,6 +68,17 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.BDDfy(); .BDDfy();
} }
private void SetUpLogger()
{
_mockLoggerFactory = new Mock<IOcelotLoggerFactory>();
var logger = new Mock<IOcelotLogger>();
_mockLoggerFactory
.Setup(x => x.CreateLogger<DownstreamRouteFinderMiddleware>())
.Returns(logger.Object);
}
private void ThenTheScopedDataRepositoryIsCalledCorrectly() private void ThenTheScopedDataRepositoryIsCalledCorrectly()
{ {
_scopedRepository _scopedRepository

View File

@ -8,10 +8,12 @@ using Microsoft.Extensions.DependencyInjection;
using Moq; using Moq;
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.DownstreamUrlCreator.Middleware; using Ocelot.DownstreamUrlCreator.Middleware;
using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer; using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Responses; using Ocelot.Responses;
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
@ -28,16 +30,19 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
private Response<DownstreamRoute> _downstreamRoute; private Response<DownstreamRoute> _downstreamRoute;
private HttpResponseMessage _result; private HttpResponseMessage _result;
private OkResponse<DownstreamUrl> _downstreamUrl; private OkResponse<DownstreamUrl> _downstreamUrl;
private Mock<IOcelotLoggerFactory> _mockLoggerFactory;
public DownstreamUrlCreatorMiddlewareTests() public DownstreamUrlCreatorMiddlewareTests()
{ {
_url = "http://localhost:51879"; _url = "http://localhost:51879";
_downstreamUrlTemplateVariableReplacer = new Mock<IDownstreamUrlPathPlaceholderReplacer>(); _downstreamUrlTemplateVariableReplacer = new Mock<IDownstreamUrlPathPlaceholderReplacer>();
_scopedRepository = new Mock<IRequestScopedDataRepository>(); _scopedRepository = new Mock<IRequestScopedDataRepository>();
SetUpLogger();
var builder = new WebHostBuilder() var builder = new WebHostBuilder()
.ConfigureServices(x => .ConfigureServices(x =>
{ {
x.AddSingleton(_mockLoggerFactory.Object);
x.AddSingleton(_downstreamUrlTemplateVariableReplacer.Object); x.AddSingleton(_downstreamUrlTemplateVariableReplacer.Object);
x.AddSingleton(_scopedRepository.Object); x.AddSingleton(_scopedRepository.Object);
}) })
@ -65,6 +70,18 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
.BDDfy(); .BDDfy();
} }
private void SetUpLogger()
{
_mockLoggerFactory = new Mock<IOcelotLoggerFactory>();
var logger = new Mock<IOcelotLogger>();
_mockLoggerFactory
.Setup(x => x.CreateLogger<DownstreamUrlCreatorMiddleware>())
.Returns(logger.Object);
}
private void TheUrlReplacerReturns(string downstreamUrl) private void TheUrlReplacerReturns(string downstreamUrl)
{ {
_downstreamUrl = new OkResponse<DownstreamUrl>(new DownstreamUrl(downstreamUrl)); _downstreamUrl = new OkResponse<DownstreamUrl>(new DownstreamUrl(downstreamUrl));