Log all startup errors in KestrelServer

This commit is contained in:
Stephen Halter 2016-08-18 10:42:01 -07:00
parent 972be6e8c1
commit 7bd30ea693
3 changed files with 57 additions and 17 deletions

View File

@ -56,17 +56,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel
public void Start<TContext>(IHttpApplication<TContext> application) public void Start<TContext>(IHttpApplication<TContext> application)
{ {
ValidateOptions();
if (_disposables != null)
{
// The server has already started and/or has not been cleaned up yet
throw new InvalidOperationException("Server has already started.");
}
_disposables = new Stack<IDisposable>();
try try
{ {
ValidateOptions();
if (_disposables != null)
{
// The server has already started and/or has not been cleaned up yet
throw new InvalidOperationException("Server has already started.");
}
_disposables = new Stack<IDisposable>();
var dateHeaderValueManager = new DateHeaderValueManager(); var dateHeaderValueManager = new DateHeaderValueManager();
var trace = new KestrelTrace(_logger); var trace = new KestrelTrace(_logger);
var engine = new KestrelEngine(new ServiceContext var engine = new KestrelEngine(new ServiceContext
@ -180,8 +180,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel
throw new InvalidOperationException("No recognized listening addresses were configured."); throw new InvalidOperationException("No recognized listening addresses were configured.");
} }
} }
catch catch (Exception ex)
{ {
_logger.LogCritical(0, ex, "Unable to start Kestrel.");
Dispose(); Dispose();
throw; throw;
} }

View File

@ -21,32 +21,38 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
[InlineData(-1337)] [InlineData(-1337)]
public void StartWithNonPositiveThreadCountThrows(int threadCount) public void StartWithNonPositiveThreadCountThrows(int threadCount)
{ {
var server = CreateServer(new KestrelServerOptions() { ThreadCount = threadCount }); var testLogger = new TestApplicationErrorLogger();
var server = CreateServer(new KestrelServerOptions() { ThreadCount = threadCount }, testLogger);
var exception = Assert.Throws<ArgumentOutOfRangeException>(() => StartDummyApplication(server)); var exception = Assert.Throws<ArgumentOutOfRangeException>(() => StartDummyApplication(server));
Assert.Equal("threadCount", exception.ParamName); Assert.Equal("threadCount", exception.ParamName);
Assert.Equal(1, testLogger.CriticalErrorsLogged);
} }
[Fact] [Fact]
public void StartWithInvalidAddressThrows() public void StartWithInvalidAddressThrows()
{ {
var server = CreateServer(new KestrelServerOptions()); var testLogger = new TestApplicationErrorLogger();
var server = CreateServer(new KestrelServerOptions(), testLogger);
server.Features.Get<IServerAddressesFeature>().Addresses.Add("http:/asdf"); server.Features.Get<IServerAddressesFeature>().Addresses.Add("http:/asdf");
var exception = Assert.Throws<FormatException>(() => StartDummyApplication(server)); var exception = Assert.Throws<FormatException>(() => StartDummyApplication(server));
Assert.Contains("Invalid URL", exception.Message); Assert.Contains("Invalid URL", exception.Message);
Assert.Equal(1, testLogger.CriticalErrorsLogged);
} }
[Fact] [Fact]
public void StartWithEmptyAddressesThrows() public void StartWithEmptyAddressesThrows()
{ {
var server = CreateServer(new KestrelServerOptions()); var testLogger = new TestApplicationErrorLogger();
var server = CreateServer(new KestrelServerOptions(), testLogger);
var exception = Assert.Throws<InvalidOperationException>(() => StartDummyApplication(server)); var exception = Assert.Throws<InvalidOperationException>(() => StartDummyApplication(server));
Assert.Equal("No recognized listening addresses were configured.", exception.Message); Assert.Equal("No recognized listening addresses were configured.", exception.Message);
Assert.Equal(1, testLogger.CriticalErrorsLogged);
} }
[Theory] [Theory]
@ -54,30 +60,56 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
[InlineData(int.MaxValue - 1, int.MaxValue)] [InlineData(int.MaxValue - 1, int.MaxValue)]
public void StartWithMaxRequestBufferSizeLessThanMaxRequestLineSizeThrows(long maxRequestBufferSize, int maxRequestLineSize) public void StartWithMaxRequestBufferSizeLessThanMaxRequestLineSizeThrows(long maxRequestBufferSize, int maxRequestLineSize)
{ {
var testLogger = new TestApplicationErrorLogger();
var options = new KestrelServerOptions(); var options = new KestrelServerOptions();
options.Limits.MaxRequestBufferSize = maxRequestBufferSize; options.Limits.MaxRequestBufferSize = maxRequestBufferSize;
options.Limits.MaxRequestLineSize = maxRequestLineSize; options.Limits.MaxRequestLineSize = maxRequestLineSize;
var server = CreateServer(options); var server = CreateServer(options, testLogger);
var exception = Assert.Throws<InvalidOperationException>(() => StartDummyApplication(server)); var exception = Assert.Throws<InvalidOperationException>(() => StartDummyApplication(server));
Assert.Equal( Assert.Equal(
$"Maximum request buffer size ({maxRequestBufferSize}) must be greater than or equal to maximum request line size ({maxRequestLineSize}).", $"Maximum request buffer size ({maxRequestBufferSize}) must be greater than or equal to maximum request line size ({maxRequestLineSize}).",
exception.Message); exception.Message);
Assert.Equal(1, testLogger.CriticalErrorsLogged);
} }
private static KestrelServer CreateServer(KestrelServerOptions options) private static KestrelServer CreateServer(KestrelServerOptions options, ILogger testLogger)
{ {
var lifetime = new LifetimeNotImplemented(); var lifetime = new LifetimeNotImplemented();
var logger = new LoggerFactory();
return new KestrelServer(Options.Create(options), lifetime, logger); return new KestrelServer(Options.Create(options), lifetime, new TestLoggerFactory(testLogger));
} }
private static void StartDummyApplication(IServer server) private static void StartDummyApplication(IServer server)
{ {
server.Start(new DummyApplication(context => TaskUtilities.CompletedTask)); server.Start(new DummyApplication(context => TaskUtilities.CompletedTask));
} }
private class TestLoggerFactory : ILoggerFactory
{
private readonly ILogger _testLogger;
public TestLoggerFactory(ILogger testLogger)
{
_testLogger = testLogger;
}
public ILogger CreateLogger(string categoryName)
{
return _testLogger;
}
public void AddProvider(ILoggerProvider provider)
{
throw new NotImplementedException();
}
public void Dispose()
{
throw new NotImplementedException();
}
}
} }
} }

View File

@ -15,6 +15,8 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
public int TotalErrorsLogged { get; set; } public int TotalErrorsLogged { get; set; }
public int CriticalErrorsLogged { get; set; }
public int ApplicationErrorsLogged { get; set; } public int ApplicationErrorsLogged { get; set; }
public IDisposable BeginScope<TState>(TState state) public IDisposable BeginScope<TState>(TState state)
@ -42,6 +44,11 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
{ {
TotalErrorsLogged++; TotalErrorsLogged++;
} }
if (logLevel == LogLevel.Critical)
{
CriticalErrorsLogged++;
}
} }
} }
} }