-
Notifications
You must be signed in to change notification settings - Fork 652
Stream apphost logs across backchannel. #9990
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
ce06774
WIP.
mitchdenny 9a5e4d5
Better registration and circular dependency management.
mitchdenny 232dddc
Functionality complete.
mitchdenny cea8aaa
Remove unnecessary variable.
mitchdenny d744a36
Fix tests.
mitchdenny 46ed1eb
WIP
mitchdenny ebbee5d
Tidy up commented out code.
mitchdenny 744211d
Output tweaks.
mitchdenny 7878fd7
Merge branch 'main' into mitchdenny/maddy-was-definately-not-right
mitchdenny 532d413
Fix tests.
mitchdenny d0392b5
Remove dead code.
mitchdenny b7cfc37
Update src/Aspire.Hosting/Backchannel/AppHostRpcTarget.cs
mitchdenny e2aa372
Fix compile error.
mitchdenny f829370
Refactor log capture to simplify task execution and handle cancellati…
davidfowl 82f11cd
Enhance logging and error handling in RunCommand for better clarity a…
davidfowl File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 101 additions & 0 deletions
101
src/Aspire.Hosting/Backchannel/BackchannelLoggerProvider.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Threading.Channels; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace Aspire.Hosting.Backchannel; | ||
|
||
internal class BackchannelLoggerProvider : ILoggerProvider | ||
{ | ||
private readonly Channel<BackchannelLogEntry> _channel = Channel.CreateUnbounded<BackchannelLogEntry>(); | ||
private readonly IServiceProvider _serviceProvider; | ||
private readonly object _channelRegisteredLock = new(); | ||
private readonly CancellationTokenSource _backgroundChannelRegistrationCts = new(); | ||
private Task? _backgroundChannelRegistrationTask; | ||
|
||
public BackchannelLoggerProvider(IServiceProvider serviceProvider) | ||
{ | ||
ArgumentNullException.ThrowIfNull(serviceProvider); | ||
_serviceProvider = serviceProvider; | ||
} | ||
|
||
private void RegisterLogChannel() | ||
{ | ||
// Why do we execute this on a background task? This method is spawned on a background | ||
// task by the CreateLogger method. The CreateLogger method is called when creating many | ||
// of the services registered in DI - but registering the log channel requires that we | ||
// can resolve the AppHostRpcTarget service (thus creating a circular dependency). To resolve | ||
// this we take a dependency on IServiceProvider so that on a separate background task we | ||
// can resolve AppHostRpcTarget which in turn would have taken a dependency on a logger | ||
// from this provider. | ||
var target = _serviceProvider.GetRequiredService<AppHostRpcTarget>(); | ||
target.RegisterLogChannel(_channel); | ||
} | ||
|
||
public ILogger CreateLogger(string categoryName) | ||
{ | ||
if (_backgroundChannelRegistrationTask == null) | ||
{ | ||
lock (_channelRegisteredLock) | ||
{ | ||
if (_backgroundChannelRegistrationTask == null) | ||
{ | ||
_backgroundChannelRegistrationTask = Task.Run( | ||
RegisterLogChannel, | ||
_backgroundChannelRegistrationCts.Token); | ||
} | ||
} | ||
} | ||
|
||
return new BackchannelLogger(categoryName, _channel); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
_backgroundChannelRegistrationCts.Cancel(); | ||
_channel.Writer.Complete(); | ||
} | ||
} | ||
|
||
internal class BackchannelLogger(string categoryName, Channel<BackchannelLogEntry> channel) : ILogger | ||
{ | ||
public IDisposable? BeginScope<TState>(TState state) where TState : notnull | ||
{ | ||
return default; | ||
} | ||
|
||
public bool IsEnabled(LogLevel logLevel) | ||
{ | ||
return true; | ||
} | ||
|
||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter) | ||
{ | ||
if (IsEnabled(logLevel)) | ||
{ | ||
var entry = new BackchannelLogEntry | ||
{ | ||
Timestamp = DateTimeOffset.UtcNow, | ||
CategoryName = categoryName, | ||
LogLevel = logLevel, | ||
EventId = eventId, | ||
Message = formatter(state, exception), | ||
Exception = exception, | ||
}; | ||
|
||
channel.Writer.TryWrite(entry); | ||
} | ||
} | ||
} | ||
|
||
internal class BackchannelLogEntry | ||
{ | ||
public required EventId EventId { get; set; } | ||
public required LogLevel LogLevel { get; set; } | ||
public required string Message { get; set; } | ||
public Exception? Exception { get; set; } | ||
public required DateTimeOffset Timestamp { get; set; } | ||
public required string CategoryName { get; set; } | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.