Description
Is there an existing issue for this?
- I have searched the existing issues
Is your feature request related to a problem? Please describe the problem.
I am trying to add additional logging properties when logging from Blazor Server components and related services. I want to be able to log the current URL (not just the original request URL -- by default, ASP.NET Core logs the RequestPath
as /blazor
, which is useless). There's a lot of other situation-dependent properties that would be nice to include that are only known by the Blazor components and other services that are within the circuit's service scope (for example, which tab does the user have selected within a tab component like MudTabs).
I can set some scoped logging properties somewhat reliably by defining a IHubFilter
and calling _logger.BeginScope
from there. I am using Serilog, which respects the log scope data that is set (uses AsyncLocal). But from the IHubFilter, I am not able to get the data I need because it is in a different IServiceProvider scope than the Blazor circuit service scope. I'm also not sure if IHubFilter will work to add logging scope data if a render is triggered by something other than an incoming SignalR call, like a timer.
You'd think a scoped CircuitHandler would be a place to be able to start the logging scope, but the virtual methods that it contains is limited. It does not have any method that is invoked for every SignalR call. If you start a logging scope from the OnCircuitOpenedAsync, the logging scope effectively ends any future events and rerenders will be in a different async call stack (related to how AsyncLocal works).
Describe the solution you'd like
The current solution I'm using involves having a base component class that all of my components inherit from that overrides OnParametersSet() and OnAfterRender() and to check if the logging scope has started yet for the current SignalR call. This seems horribly inefficient because I'm checking AsyncLocal data for each render and for each component. It's also not 100% reliable.
I think I need something similar to IHubFilter
/CircuitHandler
except it can hook into any event that runs on the RendererStynchronizationContext
/CircuitHost
to provide a place that is completely reliable for adding logging scoped data from the circuit's scoped services.
Example of what that might look like:
builder.Services.AddScoped<IRendererListener, MyRendererListener>();
class MyRendererListener : IRendererListener
{
// scope is the Blazor circuit's service scope
public void OnRenderEvent(IServiceProvider scope)
{
scope.GetRequiredService<ILogger<MyRendererListener>>().BeginScope(scope.GetRequiredService<MyScopedLoggingData>())
}
}
Additional context
I've been looking everywhere for a solution for this. I've explored using ASP.NET Core middleware, CircuitHandler, IHubFilter, custom component base classes, custom logger types. I haven't been able to find a good solution for this. I've looked up and down the call stacks at various points to try to figure out how I can hook in some code where I'd need to, but I haven't been able to find it. I've asked AI chat bots various questions.
Including scoped logging data like this, such as including the current URL, seems like something that should be well supported and documented. I'd appreciate any help or improvements in this area.