Skip to content

Commit

Permalink
Host: log exception if a service factory fails (dotnet#112534)
Browse files Browse the repository at this point in the history
  • Loading branch information
mus65 authored Feb 20, 2025
1 parent 6211fe4 commit b098f24
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 15 deletions.
29 changes: 14 additions & 15 deletions src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,28 +85,27 @@ public async Task StartAsync(CancellationToken cancellationToken = default)
cancellationToken.ThrowIfCancellationRequested();

List<Exception> exceptions = new();
_hostedServices ??= Services.GetRequiredService<IEnumerable<IHostedService>>();
_hostedLifecycleServices = GetHostLifecycles(_hostedServices);
_hostStarting = true;
bool concurrent = _options.ServicesStartConcurrently;
bool abortOnFirstException = !concurrent;

// Call startup validators.
IStartupValidator? validator = Services.GetService<IStartupValidator>();
if (validator is not null)
try
{
try
{
validator.Validate();
}
catch (Exception ex)
{
exceptions.Add(ex);
_hostedServices ??= Services.GetRequiredService<IEnumerable<IHostedService>>();
_hostedLifecycleServices = GetHostLifecycles(_hostedServices);

// Validation errors cause startup to be aborted.
LogAndRethrow();
}
// Call startup validators.
IStartupValidator? validator = Services.GetService<IStartupValidator>();
validator?.Validate();
}
catch (Exception ex)
{
// service factory or validation failed, abort startup.
exceptions.Add(ex);
LogAndRethrow();
return; // unreachable
}


// Call StartingAsync().
if (_hostedLifecycleServices is not null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1426,6 +1426,33 @@ public async Task BackgroundServiceAsyncExceptionGetsLogged(
}
}

/// <summary>
/// Tests that an exception is logged if a hosted service factory fails.
/// </summary>
[Fact]
public async Task HostedServiceFactoryExceptionGetsLogged()
{
TestLoggerProvider logger = new TestLoggerProvider();

using IHost host = CreateBuilder()
.ConfigureLogging(logging =>
{
logging.AddProvider(logger);
})
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<WorkerTemplateService>(p => throw new InvalidOperationException("factory failed"));
})
.Build();

await Assert.ThrowsAsync<InvalidOperationException>(() => host.StartAsync());

LogEvent[] events = logger.GetEvents();
Assert.Single(events);
Assert.Equal(LogLevel.Error, events[0].LogLevel);
Assert.Equal("HostedServiceStartupFaulted", events[0].EventId.Name);
}

/// <summary>
/// Tests that when a BackgroundService is canceled when stopping the host,
/// no error is logged.
Expand Down

0 comments on commit b098f24

Please sign in to comment.