Expand Blazor logging (#11919)

This commit is contained in:
Steve Sanderson 2019-07-08 13:50:19 +01:00 committed by GitHub
parent 0049c5899c
commit 6534bcff32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 322 additions and 53 deletions

View File

@ -58,7 +58,7 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
{ {
public partial class WebAssemblyRenderer : Microsoft.AspNetCore.Components.Rendering.Renderer public partial class WebAssemblyRenderer : Microsoft.AspNetCore.Components.Rendering.Renderer
{ {
public WebAssemblyRenderer(System.IServiceProvider serviceProvider) : base (default(System.IServiceProvider)) { } public WebAssemblyRenderer(System.IServiceProvider serviceProvider, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) : base (default(System.IServiceProvider), default(Microsoft.Extensions.Logging.ILoggerFactory)) { }
public System.Threading.Tasks.Task AddComponentAsync(System.Type componentType, string domElementSelector) { throw null; } public System.Threading.Tasks.Task AddComponentAsync(System.Type componentType, string domElementSelector) { throw null; }
public System.Threading.Tasks.Task AddComponentAsync<TComponent>(string domElementSelector) where TComponent : Microsoft.AspNetCore.Components.IComponent { throw null; } public System.Threading.Tasks.Task AddComponentAsync<TComponent>(string domElementSelector) where TComponent : Microsoft.AspNetCore.Components.IComponent { throw null; }
public override System.Threading.Tasks.Task DispatchEventAsync(int eventHandlerId, Microsoft.AspNetCore.Components.Rendering.EventFieldInfo eventFieldInfo, Microsoft.AspNetCore.Components.UIEventArgs eventArgs) { throw null; } public override System.Threading.Tasks.Task DispatchEventAsync(int eventHandlerId, Microsoft.AspNetCore.Components.Rendering.EventFieldInfo eventFieldInfo, Microsoft.AspNetCore.Components.UIEventArgs eventArgs) { throw null; }

View File

@ -6,6 +6,8 @@ using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Blazor.Rendering; using Microsoft.AspNetCore.Blazor.Rendering;
using Microsoft.AspNetCore.Components.Builder; using Microsoft.AspNetCore.Components.Builder;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
namespace Microsoft.AspNetCore.Blazor.Hosting namespace Microsoft.AspNetCore.Blazor.Hosting
{ {
@ -38,7 +40,8 @@ namespace Microsoft.AspNetCore.Blazor.Hosting
public async Task<WebAssemblyRenderer> CreateRendererAsync() public async Task<WebAssemblyRenderer> CreateRendererAsync()
{ {
var renderer = new WebAssemblyRenderer(Services); var loggerFactory = (ILoggerFactory)Services.GetService(typeof(ILoggerFactory));
var renderer = new WebAssemblyRenderer(Services, loggerFactory);
for (var i = 0; i < Entries.Count; i++) for (var i = 0; i < Entries.Count; i++)
{ {
var (componentType, domElementSelector) = Entries[i]; var (componentType, domElementSelector) = Entries[i];

View File

@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Blazor.Services;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Blazor.Rendering namespace Microsoft.AspNetCore.Blazor.Rendering
{ {
@ -26,8 +27,9 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
/// Constructs an instance of <see cref="WebAssemblyRenderer"/>. /// Constructs an instance of <see cref="WebAssemblyRenderer"/>.
/// </summary> /// </summary>
/// <param name="serviceProvider">The <see cref="IServiceProvider"/> to use when initializing components.</param> /// <param name="serviceProvider">The <see cref="IServiceProvider"/> to use when initializing components.</param>
public WebAssemblyRenderer(IServiceProvider serviceProvider) /// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
: base(serviceProvider) public WebAssemblyRenderer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory)
: base(serviceProvider, loggerFactory)
{ {
// The browser renderer registers and unregisters itself with the static // The browser renderer registers and unregisters itself with the static
// registry. This works well with the WebAssembly runtime, and is simple for the // registry. This works well with the WebAssembly runtime, and is simple for the

View File

@ -20,6 +20,7 @@ using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor;
using Microsoft.Extensions.Logging.Abstractions;
using Xunit; using Xunit;
using Xunit.Abstractions; using Xunit.Abstractions;
using Xunit.Sdk; using Xunit.Sdk;
@ -441,7 +442,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
protected class TestRenderer : Renderer protected class TestRenderer : Renderer
{ {
public TestRenderer() : base(new TestServiceProvider(), CreateDefaultDispatcher()) public TestRenderer() : base(new TestServiceProvider(), NullLoggerFactory.Instance, CreateDefaultDispatcher())
{ {
} }

View File

@ -6,6 +6,7 @@ using System.Threading.Tasks;
using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.AspNetCore.Components.RenderTree;
using Microsoft.Extensions.Logging.Abstractions;
namespace Microsoft.AspNetCore.Components.Performance namespace Microsoft.AspNetCore.Components.Performance
{ {
@ -87,7 +88,7 @@ namespace Microsoft.AspNetCore.Components.Performance
private class FakeRenderer : Renderer private class FakeRenderer : Renderer
{ {
public FakeRenderer() public FakeRenderer()
: base(new TestServiceProvider(), new RendererSynchronizationContext()) : base(new TestServiceProvider(), NullLoggerFactory.Instance, new RendererSynchronizationContext())
{ {
} }

View File

@ -674,7 +674,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
} }
public partial class HtmlRenderer : Microsoft.AspNetCore.Components.Rendering.Renderer public partial class HtmlRenderer : Microsoft.AspNetCore.Components.Rendering.Renderer
{ {
public HtmlRenderer(System.IServiceProvider serviceProvider, System.Func<string, string> htmlEncoder, Microsoft.AspNetCore.Components.IDispatcher dispatcher) : base (default(System.IServiceProvider)) { } public HtmlRenderer(System.IServiceProvider serviceProvider, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.AspNetCore.Components.IDispatcher dispatcher, System.Func<string, string> htmlEncoder) : base (default(System.IServiceProvider), default(Microsoft.Extensions.Logging.ILoggerFactory)) { }
protected override void HandleException(System.Exception exception) { } protected override void HandleException(System.Exception exception) { }
[System.Diagnostics.DebuggerStepThroughAttribute] [System.Diagnostics.DebuggerStepThroughAttribute]
public System.Threading.Tasks.Task<Microsoft.AspNetCore.Components.Rendering.ComponentRenderedText> RenderComponentAsync(System.Type componentType, Microsoft.AspNetCore.Components.ParameterCollection initialParameters) { throw null; } public System.Threading.Tasks.Task<Microsoft.AspNetCore.Components.Rendering.ComponentRenderedText> RenderComponentAsync(System.Type componentType, Microsoft.AspNetCore.Components.ParameterCollection initialParameters) { throw null; }
@ -692,8 +692,8 @@ namespace Microsoft.AspNetCore.Components.Rendering
} }
public abstract partial class Renderer : System.IDisposable public abstract partial class Renderer : System.IDisposable
{ {
public Renderer(System.IServiceProvider serviceProvider) { } public Renderer(System.IServiceProvider serviceProvider, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) { }
public Renderer(System.IServiceProvider serviceProvider, Microsoft.AspNetCore.Components.IDispatcher dispatcher) { } public Renderer(System.IServiceProvider serviceProvider, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.AspNetCore.Components.IDispatcher dispatcher) { }
public event System.UnhandledExceptionEventHandler UnhandledSynchronizationException { add { } remove { } } public event System.UnhandledExceptionEventHandler UnhandledSynchronizationException { add { } remove { } }
protected internal virtual void AddToRenderQueue(int componentId, Microsoft.AspNetCore.Components.RenderFragment renderFragment) { } protected internal virtual void AddToRenderQueue(int componentId, Microsoft.AspNetCore.Components.RenderFragment renderFragment) { }
protected internal int AssignRootComponentId(Microsoft.AspNetCore.Components.IComponent component) { throw null; } protected internal int AssignRootComponentId(Microsoft.AspNetCore.Components.IComponent component) { throw null; }

View File

@ -7,6 +7,7 @@ using System.Diagnostics;
using System.Runtime.ExceptionServices; using System.Runtime.ExceptionServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.AspNetCore.Components.RenderTree;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Components.Rendering namespace Microsoft.AspNetCore.Components.Rendering
{ {
@ -26,10 +27,11 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// Initializes a new instance of <see cref="HtmlRenderer"/>. /// Initializes a new instance of <see cref="HtmlRenderer"/>.
/// </summary> /// </summary>
/// <param name="serviceProvider">The <see cref="IServiceProvider"/> to use to instantiate components.</param> /// <param name="serviceProvider">The <see cref="IServiceProvider"/> to use to instantiate components.</param>
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
/// <param name="dispatcher">The <see cref="IDispatcher"/> to be for invoking user actions into the <see cref="Renderer"/> context.</param>
/// <param name="htmlEncoder">A <see cref="Func{T, TResult}"/> that will HTML encode the given string.</param> /// <param name="htmlEncoder">A <see cref="Func{T, TResult}"/> that will HTML encode the given string.</param>
/// <param name="dispatcher"></param> public HtmlRenderer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory, IDispatcher dispatcher, Func<string, string> htmlEncoder)
public HtmlRenderer(IServiceProvider serviceProvider, Func<string, string> htmlEncoder, IDispatcher dispatcher) : base(serviceProvider, loggerFactory, dispatcher)
: base(serviceProvider, dispatcher)
{ {
_htmlEncoder = htmlEncoder; _htmlEncoder = htmlEncoder;
} }

View File

@ -0,0 +1,65 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Components.Rendering
{
public abstract partial class Renderer
{
internal static class Log
{
private static readonly Action<ILogger, int, Type, int, Type, Exception> _initializingChildComponent =
LoggerMessage.Define<int, Type, int, Type>(LogLevel.Debug, new EventId(1, "InitializingChildComponent"), "Initializing component {ComponentId} ({ComponentType}) as child of {ParentComponentId} ({ParentComponentId})");
private static readonly Action<ILogger, int, Type, Exception> _initializingRootComponent =
LoggerMessage.Define<int, Type>(LogLevel.Debug, new EventId(2, "InitializingRootComponent"), "Initializing root component {ComponentId} ({ComponentType})");
private static readonly Action<ILogger, int, Type, Exception> _renderingComponent =
LoggerMessage.Define<int, Type>(LogLevel.Debug, new EventId(3, "RenderingComponent"), "Rendering component {ComponentId} of type {ComponentType}");
private static readonly Action<ILogger, int, Type, Exception> _disposingComponent =
LoggerMessage.Define<int, Type>(LogLevel.Debug, new EventId(4, "DisposingComponent"), "Disposing component {ComponentId} of type {ComponentType}");
private static readonly Action<ILogger, int, string, Exception> _handlingEvent =
LoggerMessage.Define<int, string>(LogLevel.Debug, new EventId(5, "HandlingEvent"), "Handling event {EventId} of type '{EventType}'");
public static void InitializingComponent(ILogger logger, ComponentState componentState, ComponentState parentComponentState)
{
if (logger.IsEnabled(LogLevel.Debug)) // This is almost always false, so skip the evaluations
{
if (parentComponentState == null)
{
_initializingRootComponent(logger, componentState.ComponentId, componentState.Component.GetType(), null);
}
else
{
_initializingChildComponent(logger, componentState.ComponentId, componentState.Component.GetType(), parentComponentState.ComponentId, parentComponentState.Component.GetType(), null);
}
}
}
public static void RenderingComponent(ILogger logger, ComponentState componentState)
{
if (logger.IsEnabled(LogLevel.Debug)) // This is almost always false, so skip the evaluations
{
_renderingComponent(logger, componentState.ComponentId, componentState.Component.GetType(), null);
}
}
internal static void DisposingComponent(ILogger<Renderer> logger, ComponentState componentState)
{
if (logger.IsEnabled(LogLevel.Debug)) // This is almost always false, so skip the evaluations
{
_disposingComponent(logger, componentState.ComponentId, componentState.Component.GetType(), null);
}
}
internal static void HandlingEvent(ILogger<Renderer> logger, int eventHandlerId, UIEventArgs eventArgs)
{
_handlingEvent(logger, eventHandlerId, eventArgs?.Type ?? "null", null);
}
}
}
}

View File

@ -7,6 +7,7 @@ using System.Diagnostics;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.AspNetCore.Components.RenderTree;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Components.Rendering namespace Microsoft.AspNetCore.Components.Rendering
{ {
@ -14,7 +15,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// Provides mechanisms for rendering hierarchies of <see cref="IComponent"/> instances, /// Provides mechanisms for rendering hierarchies of <see cref="IComponent"/> instances,
/// dispatching events to them, and notifying when the user interface is being updated. /// dispatching events to them, and notifying when the user interface is being updated.
/// </summary> /// </summary>
public abstract class Renderer : IDisposable public abstract partial class Renderer : IDisposable
{ {
private readonly ComponentFactory _componentFactory; private readonly ComponentFactory _componentFactory;
private readonly Dictionary<int, ComponentState> _componentStateById = new Dictionary<int, ComponentState>(); private readonly Dictionary<int, ComponentState> _componentStateById = new Dictionary<int, ComponentState>();
@ -22,6 +23,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
private readonly Dictionary<int, EventCallback> _eventBindings = new Dictionary<int, EventCallback>(); private readonly Dictionary<int, EventCallback> _eventBindings = new Dictionary<int, EventCallback>();
private readonly Dictionary<int, int> _eventHandlerIdReplacements = new Dictionary<int, int>(); private readonly Dictionary<int, int> _eventHandlerIdReplacements = new Dictionary<int, int>();
private readonly IDispatcher _dispatcher; private readonly IDispatcher _dispatcher;
private readonly ILogger<Renderer> _logger;
private int _nextComponentId = 0; // TODO: change to 'long' when Mono .NET->JS interop supports it private int _nextComponentId = 0; // TODO: change to 'long' when Mono .NET->JS interop supports it
private bool _isBatchInProgress; private bool _isBatchInProgress;
@ -55,19 +57,33 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// Constructs an instance of <see cref="Renderer"/>. /// Constructs an instance of <see cref="Renderer"/>.
/// </summary> /// </summary>
/// <param name="serviceProvider">The <see cref="IServiceProvider"/> to be used when initializing components.</param> /// <param name="serviceProvider">The <see cref="IServiceProvider"/> to be used when initializing components.</param>
public Renderer(IServiceProvider serviceProvider) /// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
public Renderer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory)
{ {
if (serviceProvider is null)
{
throw new ArgumentNullException(nameof(serviceProvider));
}
if (loggerFactory is null)
{
throw new ArgumentNullException(nameof(loggerFactory));
}
_componentFactory = new ComponentFactory(serviceProvider); _componentFactory = new ComponentFactory(serviceProvider);
_logger = loggerFactory.CreateLogger<Renderer>();
} }
/// <summary> /// <summary>
/// Constructs an instance of <see cref="Renderer"/>. /// Constructs an instance of <see cref="Renderer"/>.
/// </summary> /// </summary>
/// <param name="serviceProvider">The <see cref="IServiceProvider"/> to be used when initializing components.</param> /// <param name="serviceProvider">The <see cref="IServiceProvider"/> to be used when initializing components.</param>
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
/// <param name="dispatcher">The <see cref="IDispatcher"/> to be for invoking user actions into the <see cref="Renderer"/> context.</param> /// <param name="dispatcher">The <see cref="IDispatcher"/> to be for invoking user actions into the <see cref="Renderer"/> context.</param>
public Renderer(IServiceProvider serviceProvider, IDispatcher dispatcher) : this(serviceProvider) public Renderer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory, IDispatcher dispatcher)
: this(serviceProvider, loggerFactory)
{ {
_dispatcher = dispatcher; _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
} }
/// <summary> /// <summary>
@ -189,6 +205,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
var componentId = _nextComponentId++; var componentId = _nextComponentId++;
var parentComponentState = GetOptionalComponentState(parentComponentId); var parentComponentState = GetOptionalComponentState(parentComponentId);
var componentState = new ComponentState(this, componentId, component, parentComponentState); var componentState = new ComponentState(this, componentId, component, parentComponentState);
Log.InitializingComponent(_logger, componentState, parentComponentState);
_componentStateById.Add(componentId, componentState); _componentStateById.Add(componentId, componentState);
component.Configure(new RenderHandle(this, componentId)); component.Configure(new RenderHandle(this, componentId));
return componentState; return componentState;
@ -220,6 +237,8 @@ namespace Microsoft.AspNetCore.Components.Rendering
throw new ArgumentException($"There is no event handler with ID {eventHandlerId}"); throw new ArgumentException($"There is no event handler with ID {eventHandlerId}");
} }
Log.HandlingEvent(_logger, eventHandlerId, eventArgs);
if (fieldInfo != null) if (fieldInfo != null)
{ {
var latestEquivalentEventHandlerId = FindLatestEventHandlerIdInChain(eventHandlerId); var latestEquivalentEventHandlerId = FindLatestEventHandlerIdInChain(eventHandlerId);
@ -613,14 +632,17 @@ namespace Microsoft.AspNetCore.Components.Rendering
private void RenderInExistingBatch(RenderQueueEntry renderQueueEntry) private void RenderInExistingBatch(RenderQueueEntry renderQueueEntry)
{ {
renderQueueEntry.ComponentState var componentState = renderQueueEntry.ComponentState;
.RenderIntoBatch(_batchBuilder, renderQueueEntry.RenderFragment); Log.RenderingComponent(_logger, componentState);
componentState.RenderIntoBatch(_batchBuilder, renderQueueEntry.RenderFragment);
// Process disposal queue now in case it causes further component renders to be enqueued // Process disposal queue now in case it causes further component renders to be enqueued
while (_batchBuilder.ComponentDisposalQueue.Count > 0) while (_batchBuilder.ComponentDisposalQueue.Count > 0)
{ {
var disposeComponentId = _batchBuilder.ComponentDisposalQueue.Dequeue(); var disposeComponentId = _batchBuilder.ComponentDisposalQueue.Dequeue();
GetRequiredComponentState(disposeComponentId).DisposeInBatch(_batchBuilder); var disposeComponentState = GetRequiredComponentState(disposeComponentId);
Log.DisposingComponent(_logger, disposeComponentState);
disposeComponentState.DisposeInBatch(_batchBuilder);
_componentStateById.Remove(disposeComponentId); _componentStateById.Remove(disposeComponentId);
_batchBuilder.DisposedComponentIds.Append(disposeComponentId); _batchBuilder.DisposedComponentIds.Append(disposeComponentId);
} }
@ -710,6 +732,8 @@ namespace Microsoft.AspNetCore.Components.Rendering
{ {
foreach (var componentState in _componentStateById.Values) foreach (var componentState in _componentStateById.Values)
{ {
Log.DisposingComponent(_logger, componentState);
if (componentState.Component is IDisposable disposable) if (componentState.Component is IDisposable disposable)
{ {
try try

View File

@ -5,8 +5,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Layouts;
using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.AspNetCore.Components.RenderTree;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
namespace Microsoft.AspNetCore.Components.Routing namespace Microsoft.AspNetCore.Components.Routing
{ {
@ -22,6 +23,7 @@ namespace Microsoft.AspNetCore.Components.Routing
string _baseUri; string _baseUri;
string _locationAbsolute; string _locationAbsolute;
bool _navigationInterceptionEnabled; bool _navigationInterceptionEnabled;
ILogger<Router> _logger;
[Inject] private IUriHelper UriHelper { get; set; } [Inject] private IUriHelper UriHelper { get; set; }
@ -29,6 +31,8 @@ namespace Microsoft.AspNetCore.Components.Routing
[Inject] private IComponentContext ComponentContext { get; set; } [Inject] private IComponentContext ComponentContext { get; set; }
[Inject] private ILoggerFactory LoggerFactory { get; set; }
/// <summary> /// <summary>
/// Gets or sets the assembly that should be searched, along with its referenced /// Gets or sets the assembly that should be searched, along with its referenced
/// assemblies, for components matching the URI. /// assemblies, for components matching the URI.
@ -55,6 +59,7 @@ namespace Microsoft.AspNetCore.Components.Routing
/// <inheritdoc /> /// <inheritdoc />
public void Configure(RenderHandle renderHandle) public void Configure(RenderHandle renderHandle)
{ {
_logger = LoggerFactory.CreateLogger<Router>();
_renderHandle = renderHandle; _renderHandle = renderHandle;
_baseUri = UriHelper.GetBaseUri(); _baseUri = UriHelper.GetBaseUri();
_locationAbsolute = UriHelper.GetAbsoluteUri(); _locationAbsolute = UriHelper.GetAbsoluteUri();
@ -111,12 +116,16 @@ namespace Microsoft.AspNetCore.Components.Routing
$"does not implement {typeof(IComponent).FullName}."); $"does not implement {typeof(IComponent).FullName}.");
} }
Log.NavigatingToComponent(_logger, context.Handler, locationPath, _baseUri);
_renderHandle.Render(builder => Render(builder, context.Handler, context.Parameters)); _renderHandle.Render(builder => Render(builder, context.Handler, context.Parameters));
} }
else else
{ {
if (!isNavigationIntercepted && NotFoundContent != null) if (!isNavigationIntercepted && NotFoundContent != null)
{ {
Log.DisplayingNotFoundContent(_logger, locationPath, _baseUri);
// We did not find a Component that matches the route. // We did not find a Component that matches the route.
// Only show the NotFoundContent if the application developer programatically got us here i.e we did not // Only show the NotFoundContent if the application developer programatically got us here i.e we did not
// intercept the navigation. In all other cases, force a browser navigation since this could be non-Blazor content. // intercept the navigation. In all other cases, force a browser navigation since this could be non-Blazor content.
@ -124,6 +133,7 @@ namespace Microsoft.AspNetCore.Components.Routing
} }
else else
{ {
Log.NavigatingToExternalUri(_logger, _locationAbsolute, locationPath, _baseUri);
UriHelper.NavigateTo(_locationAbsolute, forceLoad: true); UriHelper.NavigateTo(_locationAbsolute, forceLoad: true);
} }
} }
@ -148,5 +158,32 @@ namespace Microsoft.AspNetCore.Components.Routing
return Task.CompletedTask; return Task.CompletedTask;
} }
private static class Log
{
private static readonly Action<ILogger, string, string, Exception> _displayingNotFoundContent =
LoggerMessage.Define<string, string>(LogLevel.Debug, new EventId(1, "DisplayingNotFoundContent"), $"Displaying {nameof(NotFoundContent)} because path '{{Path}}' with base URI '{{BaseUri}}' does not match any component route");
private static readonly Action<ILogger, Type, string, string, Exception> _navigatingToComponent =
LoggerMessage.Define<Type, string, string>(LogLevel.Debug, new EventId(2, "NavigatingToComponent"), "Navigating to component {ComponentType} in response to path '{Path}' with base URI '{BaseUri}'");
private static readonly Action<ILogger, string, string, string, Exception> _navigatingToExternalUri =
LoggerMessage.Define<string, string, string>(LogLevel.Debug, new EventId(3, "NavigatingToExternalUri"), "Navigating to non-component URI '{ExternalUri}' in response to path '{Path}' with base URI '{BaseUri}'");
internal static void DisplayingNotFoundContent(ILogger logger, string path, string baseUri)
{
_displayingNotFoundContent(logger, path, baseUri, null);
}
internal static void NavigatingToComponent(ILogger logger, Type componentType, string path, string baseUri)
{
_navigatingToComponent(logger, componentType, path, baseUri, null);
}
internal static void NavigatingToExternalUri(ILogger logger, string externalUri, string path, string baseUri)
{
_navigatingToExternalUri(logger, externalUri, path, baseUri, null);
}
}
} }
} }

View File

@ -8,6 +8,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.AspNetCore.Components.RenderTree;
using Microsoft.AspNetCore.Components.Test.Helpers; using Microsoft.AspNetCore.Components.Test.Helpers;
using Microsoft.Extensions.Logging.Abstractions;
using Moq; using Moq;
using Xunit; using Xunit;
@ -1794,7 +1795,7 @@ namespace Microsoft.AspNetCore.Components.Test
private class TestRenderer : Renderer private class TestRenderer : Renderer
{ {
public TestRenderer() : base(new TestServiceProvider(), new RendererSynchronizationContext()) public TestRenderer() : base(new TestServiceProvider(), NullLoggerFactory.Instance, new RendererSynchronizationContext())
{ {
} }

View File

@ -8,6 +8,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.AspNetCore.Components.RenderTree;
using Microsoft.AspNetCore.Components.Test.Helpers; using Microsoft.AspNetCore.Components.Test.Helpers;
using Microsoft.Extensions.Logging.Abstractions;
using Xunit; using Xunit;
namespace Microsoft.AspNetCore.Components.Test namespace Microsoft.AspNetCore.Components.Test
@ -2207,7 +2208,7 @@ namespace Microsoft.AspNetCore.Components.Test
private class FakeRenderer : Renderer private class FakeRenderer : Renderer
{ {
public FakeRenderer() : base(new TestServiceProvider(), new RendererSynchronizationContext()) public FakeRenderer() : base(new TestServiceProvider(), NullLoggerFactory.Instance, new RendererSynchronizationContext())
{ {
} }

View File

@ -14,6 +14,7 @@ using Microsoft.AspNetCore.Components.RenderTree;
using Microsoft.AspNetCore.Components.Test.Helpers; using Microsoft.AspNetCore.Components.Test.Helpers;
using Microsoft.AspNetCore.Testing; using Microsoft.AspNetCore.Testing;
using Microsoft.AspNetCore.Testing.xunit; using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.Logging.Abstractions;
using Xunit; using Xunit;
namespace Microsoft.AspNetCore.Components.Test namespace Microsoft.AspNetCore.Components.Test
@ -3372,7 +3373,7 @@ namespace Microsoft.AspNetCore.Components.Test
private class NoOpRenderer : Renderer private class NoOpRenderer : Renderer
{ {
public NoOpRenderer() : base(new TestServiceProvider(), new RendererSynchronizationContext()) public NoOpRenderer() : base(new TestServiceProvider(), NullLoggerFactory.Instance, new RendererSynchronizationContext())
{ {
} }

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using Microsoft.Extensions.Logging.Abstractions;
namespace Microsoft.AspNetCore.Components.Rendering namespace Microsoft.AspNetCore.Components.Rendering
{ {
@ -9,7 +10,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
{ {
protected override HtmlRenderer GetHtmlRenderer(IServiceProvider serviceProvider) protected override HtmlRenderer GetHtmlRenderer(IServiceProvider serviceProvider)
{ {
return new HtmlRenderer(serviceProvider, _encoder, Dispatcher); return new HtmlRenderer(serviceProvider, NullLoggerFactory.Instance, Dispatcher, _encoder);
} }
} }
} }

View File

@ -351,7 +351,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
"Unhandled error invoking circuit handler type {handlerType}.{handlerMethod}: {Message}"); "Unhandled error invoking circuit handler type {handlerType}.{handlerMethod}: {Message}");
_disposingCircuit = LoggerMessage.Define<string>( _disposingCircuit = LoggerMessage.Define<string>(
LogLevel.Trace, LogLevel.Debug,
EventIds.DisposingCircuit, EventIds.DisposingCircuit,
"Disposing circuit with identifier {CircuitId}"); "Disposing circuit with identifier {CircuitId}");

View File

@ -340,7 +340,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
"Unhandled exception disposing circuit host: {Message}"); "Unhandled exception disposing circuit host: {Message}");
_unhandledExceptionDisposingTokenSource = LoggerMessage.Define<string>( _unhandledExceptionDisposingTokenSource = LoggerMessage.Define<string>(
LogLevel.Trace, LogLevel.Debug,
EventIds.ExceptionDisposingTokenSource, EventIds.ExceptionDisposingTokenSource,
"Exception thrown when disposing token source: {Message}"); "Exception thrown when disposing token source: {Message}");

View File

@ -21,6 +21,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
{ {
private readonly IServiceScopeFactory _scopeFactory; private readonly IServiceScopeFactory _scopeFactory;
private readonly ILoggerFactory _loggerFactory; private readonly ILoggerFactory _loggerFactory;
private readonly ILogger _logger;
private readonly CircuitIdFactory _circuitIdFactory; private readonly CircuitIdFactory _circuitIdFactory;
public DefaultCircuitFactory( public DefaultCircuitFactory(
@ -30,6 +31,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
{ {
_scopeFactory = scopeFactory ?? throw new ArgumentNullException(nameof(scopeFactory)); _scopeFactory = scopeFactory ?? throw new ArgumentNullException(nameof(scopeFactory));
_loggerFactory = loggerFactory; _loggerFactory = loggerFactory;
_logger = _loggerFactory.CreateLogger<CircuitFactory>();
_circuitIdFactory = circuitIdFactory ?? throw new ArgumentNullException(nameof(circuitIdFactory)); _circuitIdFactory = circuitIdFactory ?? throw new ArgumentNullException(nameof(circuitIdFactory));
} }
@ -72,6 +74,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
var dispatcher = Renderer.CreateDefaultDispatcher(); var dispatcher = Renderer.CreateDefaultDispatcher();
var renderer = new RemoteRenderer( var renderer = new RemoteRenderer(
scope.ServiceProvider, scope.ServiceProvider,
_loggerFactory,
rendererRegistry, rendererRegistry,
jsRuntime, jsRuntime,
client, client,
@ -94,6 +97,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
jsRuntime, jsRuntime,
circuitHandlers, circuitHandlers,
_loggerFactory.CreateLogger<CircuitHost>()); _loggerFactory.CreateLogger<CircuitHost>());
Log.CreatedCircuit(_logger, circuitHost);
// Initialize per - circuit data that services need // Initialize per - circuit data that services need
(circuitHost.Services.GetRequiredService<ICircuitAccessor>() as DefaultCircuitAccessor).Circuit = circuitHost.Circuit; (circuitHost.Services.GetRequiredService<ICircuitAccessor>() as DefaultCircuitAccessor).Circuit = circuitHost.Circuit;
@ -124,5 +128,26 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
return componentsMetadata; return componentsMetadata;
} }
} }
private static class Log
{
private static readonly Action<ILogger, string, string, Exception> _createdConnectedCircuit =
LoggerMessage.Define<string, string>(LogLevel.Debug, new EventId(1, "CreatedConnectedCircuit"), "Created circuit {CircuitId} for connection {ConnectionId}");
private static readonly Action<ILogger, string, Exception> _createdDisconnectedCircuit =
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(2, "CreatedDisconnectedCircuit"), "Created circuit {CircuitId} for disconnected client");
internal static void CreatedCircuit(ILogger logger, CircuitHost circuitHost)
{
if (circuitHost.Client.Connected)
{
_createdConnectedCircuit(logger, circuitHost.CircuitId, circuitHost.Client.ConnectionId, null);
}
else
{
_createdDisconnectedCircuit(logger, circuitHost.CircuitId, null);
}
}
}
} }
} }

View File

@ -37,13 +37,14 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering
/// </summary> /// </summary>
public RemoteRenderer( public RemoteRenderer(
IServiceProvider serviceProvider, IServiceProvider serviceProvider,
ILoggerFactory loggerFactory,
RendererRegistry rendererRegistry, RendererRegistry rendererRegistry,
IJSRuntime jsRuntime, IJSRuntime jsRuntime,
CircuitClientProxy client, CircuitClientProxy client,
IDispatcher dispatcher, IDispatcher dispatcher,
HtmlEncoder encoder, HtmlEncoder encoder,
ILogger logger) ILogger logger)
: base(serviceProvider, encoder.Encode, dispatcher) : base(serviceProvider, loggerFactory, dispatcher, encoder.Encode)
{ {
_rendererRegistry = rendererRegistry; _rendererRegistry = rendererRegistry;
_jsRuntime = jsRuntime; _jsRuntime = jsRuntime;
@ -179,7 +180,7 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering
return; return;
} }
Log.BeginUpdateDisplayAsync(_logger, _client.ConnectionId); Log.BeginUpdateDisplayAsync(_logger, _client.ConnectionId, pending.BatchId, pending.Data.Length);
await _client.SendAsync("JS.RenderBatch", Id, pending.BatchId, pending.Data); await _client.SendAsync("JS.RenderBatch", Id, pending.BatchId, pending.Data);
} }
catch (Exception e) catch (Exception e)
@ -212,10 +213,15 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering
} }
else else
{ {
var message = $"Completing batch {entry.BatchId} " + if (errorMessageOrNull == null)
(errorMessageOrNull == null ? "without error." : "with error."); {
Log.CompletingBatchWithoutError(_logger, entry.BatchId);
}
else
{
Log.CompletingBatchWithError(_logger, entry.BatchId, errorMessageOrNull);
}
_logger.LogDebug(message);
CompleteRender(entry.CompletionSource, errorMessageOrNull); CompleteRender(entry.CompletionSource, errorMessageOrNull);
} }
} }
@ -260,9 +266,11 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering
private static class Log private static class Log
{ {
private static readonly Action<ILogger, string, Exception> _unhandledExceptionRenderingComponent; private static readonly Action<ILogger, string, Exception> _unhandledExceptionRenderingComponent;
private static readonly Action<ILogger, string, Exception> _beginUpdateDisplayAsync; private static readonly Action<ILogger, long, int, string, Exception> _beginUpdateDisplayAsync;
private static readonly Action<ILogger, string, Exception> _bufferingRenderDisconnectedClient; private static readonly Action<ILogger, string, Exception> _bufferingRenderDisconnectedClient;
private static readonly Action<ILogger, string, Exception> _sendBatchDataFailed; private static readonly Action<ILogger, string, Exception> _sendBatchDataFailed;
private static readonly Action<ILogger, long, string, Exception> _completingBatchWithError;
private static readonly Action<ILogger, long, Exception> _completingBatchWithoutError;
private static class EventIds private static class EventIds
{ {
@ -270,6 +278,8 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering
public static readonly EventId BeginUpdateDisplayAsync = new EventId(101, "BeginUpdateDisplayAsync"); public static readonly EventId BeginUpdateDisplayAsync = new EventId(101, "BeginUpdateDisplayAsync");
public static readonly EventId SkipUpdateDisplayAsync = new EventId(102, "SkipUpdateDisplayAsync"); public static readonly EventId SkipUpdateDisplayAsync = new EventId(102, "SkipUpdateDisplayAsync");
public static readonly EventId SendBatchDataFailed = new EventId(103, "SendBatchDataFailed"); public static readonly EventId SendBatchDataFailed = new EventId(103, "SendBatchDataFailed");
public static readonly EventId CompletingBatchWithError = new EventId(104, "CompletingBatchWithError");
public static readonly EventId CompletingBatchWithoutError = new EventId(105, "CompletingBatchWithoutError");
} }
static Log() static Log()
@ -279,13 +289,13 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering
EventIds.UnhandledExceptionRenderingComponent, EventIds.UnhandledExceptionRenderingComponent,
"Unhandled exception rendering component: {Message}"); "Unhandled exception rendering component: {Message}");
_beginUpdateDisplayAsync = LoggerMessage.Define<string>( _beginUpdateDisplayAsync = LoggerMessage.Define<long, int, string>(
LogLevel.Trace, LogLevel.Debug,
EventIds.BeginUpdateDisplayAsync, EventIds.BeginUpdateDisplayAsync,
"Begin remote rendering of components on client {ConnectionId}."); "Sending render batch {BatchId} of size {DataLength} bytes to client {ConnectionId}.");
_bufferingRenderDisconnectedClient = LoggerMessage.Define<string>( _bufferingRenderDisconnectedClient = LoggerMessage.Define<string>(
LogLevel.Trace, LogLevel.Debug,
EventIds.SkipUpdateDisplayAsync, EventIds.SkipUpdateDisplayAsync,
"Buffering remote render because the client on connection {ConnectionId} is disconnected."); "Buffering remote render because the client on connection {ConnectionId} is disconnected.");
@ -293,6 +303,16 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering
LogLevel.Information, LogLevel.Information,
EventIds.SendBatchDataFailed, EventIds.SendBatchDataFailed,
"Sending data for batch failed: {Message}"); "Sending data for batch failed: {Message}");
_completingBatchWithError = LoggerMessage.Define<long, string>(
LogLevel.Debug,
EventIds.CompletingBatchWithError,
"Completing batch {BatchId} with error: {ErrorMessage}");
_completingBatchWithoutError = LoggerMessage.Define<long>(
LogLevel.Debug,
EventIds.CompletingBatchWithoutError,
"Completing batch {BatchId} without error");
} }
public static void SendBatchDataFailed(ILogger logger, Exception exception) public static void SendBatchDataFailed(ILogger logger, Exception exception)
@ -308,10 +328,12 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering
exception); exception);
} }
public static void BeginUpdateDisplayAsync(ILogger logger, string connectionId) public static void BeginUpdateDisplayAsync(ILogger logger, string connectionId, long batchId, int dataLength)
{ {
_beginUpdateDisplayAsync( _beginUpdateDisplayAsync(
logger, logger,
batchId,
dataLength,
connectionId, connectionId,
null); null);
} }
@ -323,6 +345,23 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering
connectionId, connectionId,
null); null);
} }
public static void CompletingBatchWithError(ILogger logger, long batchId, string errorMessage)
{
_completingBatchWithError(
logger,
batchId,
errorMessage,
null);
}
public static void CompletingBatchWithoutError(ILogger logger, long batchId)
{
_completingBatchWithoutError(
logger,
batchId,
null);
}
} }
} }
} }

View File

@ -59,8 +59,6 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
Interop.ListenForNavigationEvents, Interop.ListenForNavigationEvents,
typeof(RemoteUriHelper).Assembly.GetName().Name, typeof(RemoteUriHelper).Assembly.GetName().Name,
nameof(NotifyLocationChanged)); nameof(NotifyLocationChanged));
_logger.LogDebug($"{nameof(RemoteUriHelper)} initialized.");
} }
/// <summary> /// <summary>
@ -75,18 +73,18 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
var message = $"{nameof(NotifyLocationChanged)} called without a circuit."; var message = $"{nameof(NotifyLocationChanged)} called without a circuit.";
throw new InvalidOperationException(message); throw new InvalidOperationException(message);
} }
var uriHelper = (RemoteUriHelper)circuit.Services.GetRequiredService<IUriHelper>(); var uriHelper = (RemoteUriHelper)circuit.Services.GetRequiredService<IUriHelper>();
Log.ReceivedLocationChangedNotification(uriHelper._logger, uriAbsolute, isInterceptedLink);
uriHelper.SetAbsoluteUri(uriAbsolute); uriHelper.SetAbsoluteUri(uriAbsolute);
uriHelper._logger.LogDebug($"Location changed to '{uriAbsolute}'.");
uriHelper.TriggerOnLocationChanged(isInterceptedLink); uriHelper.TriggerOnLocationChanged(isInterceptedLink);
} }
/// <inheritdoc /> /// <inheritdoc />
protected override void NavigateToCore(string uri, bool forceLoad) protected override void NavigateToCore(string uri, bool forceLoad)
{ {
_logger.LogDebug($"{uri} force load {forceLoad}."); Log.RequestingNavigation(_logger, uri, forceLoad);
if (_jsRuntime == null) if (_jsRuntime == null)
{ {
@ -94,5 +92,24 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
} }
_jsRuntime.InvokeAsync<object>(Interop.NavigateTo, uri, forceLoad); _jsRuntime.InvokeAsync<object>(Interop.NavigateTo, uri, forceLoad);
} }
private static class Log
{
private static readonly Action<ILogger, string, bool, Exception> _requestingNavigation =
LoggerMessage.Define<string, bool>(LogLevel.Debug, new EventId(1, "RequestingNavigation"), "Requesting navigation to URI {Uri} with forceLoad={ForceLoad}");
private static readonly Action<ILogger, string, bool, Exception> _receivedLocationChangedNotification =
LoggerMessage.Define<string, bool>(LogLevel.Debug, new EventId(2, "ReceivedLocationChangedNotification"), "Received notification that the URI has changed to {Uri} with isIntercepted={IsIntercepted}");
public static void RequestingNavigation(ILogger logger, string uri, bool forceLoad)
{
_requestingNavigation(logger, uri, forceLoad, null);
}
public static void ReceivedLocationChangedNotification(ILogger logger, string uri, bool isIntercepted)
{
_receivedLocationChangedNotification(logger, uri, isIntercepted, null);
}
}
} }
} }

View File

@ -73,7 +73,7 @@ namespace Microsoft.AspNetCore.Components.Server
var endpointFeature = Context.GetHttpContext().Features.Get<IEndpointFeature>(); var endpointFeature = Context.GetHttpContext().Features.Get<IEndpointFeature>();
var endpoint = endpointFeature?.Endpoint; var endpoint = endpointFeature?.Endpoint;
_logger.LogDebug($"No components registered in the current endpoint '{endpoint.DisplayName}'."); Log.NoComponentsRegisteredInEndpoint(_logger, endpoint.DisplayName);
// No components preregistered so return. This is totally normal if the components were prerendered. // No components preregistered so return. This is totally normal if the components were prerendered.
return null; return null;
@ -131,16 +131,18 @@ namespace Microsoft.AspNetCore.Components.Server
/// </summary> /// </summary>
public void OnRenderCompleted(long renderId, string errorMessageOrNull) public void OnRenderCompleted(long renderId, string errorMessageOrNull)
{ {
_logger.LogDebug($"Received confirmation for batch {renderId}."); Log.ReceivedConfirmationForBatch(_logger, renderId);
EnsureCircuitHost().Renderer.OnRenderCompleted(renderId, errorMessageOrNull); EnsureCircuitHost().Renderer.OnRenderCompleted(renderId, errorMessageOrNull);
} }
private async void CircuitHost_UnhandledException(object sender, UnhandledExceptionEventArgs e) private async void CircuitHost_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{ {
var circuitHost = (CircuitHost)sender; var circuitHost = (CircuitHost)sender;
var circuitId = circuitHost?.CircuitId;
try try
{ {
_logger.LogWarning((Exception)e.ExceptionObject, "Unhandled Server-Side exception"); Log.UnhandledExceptionInCircuit(_logger, circuitId, (Exception)e.ExceptionObject);
await circuitHost.Client.SendAsync("JS.Error", e.ExceptionObject); await circuitHost.Client.SendAsync("JS.Error", e.ExceptionObject);
// We generally can't abort the connection here since this is an async // We generally can't abort the connection here since this is an async
@ -149,7 +151,7 @@ namespace Microsoft.AspNetCore.Components.Server
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Failed to transmit exception to client"); Log.FailedToTransmitException(_logger, circuitId, ex);
} }
} }
@ -164,5 +166,40 @@ namespace Microsoft.AspNetCore.Components.Server
return circuitHost; return circuitHost;
} }
private static class Log
{
private static readonly Action<ILogger, string, Exception> _noComponentsRegisteredInEndpoint =
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(1, "NoComponentsRegisteredInEndpoint"), "No components registered in the current endpoint '{Endpoint}'");
private static readonly Action<ILogger, long, Exception> _receivedConfirmationForBatch =
LoggerMessage.Define<long>(LogLevel.Debug, new EventId(2, "ReceivedConfirmationForBatch"), "Received confirmation for batch {BatchId}");
private static readonly Action<ILogger, string, Exception> _unhandledExceptionInCircuit =
LoggerMessage.Define<string>(LogLevel.Warning, new EventId(3, "UnhandledExceptionInCircuit"), "Unhandled exception in circuit {CircuitId}");
private static readonly Action<ILogger, string, Exception> _failedToTransmitException =
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(4, "FailedToTransmitException"), "Failed to transmit exception to client in circuit {CircuitId}");
public static void NoComponentsRegisteredInEndpoint(ILogger logger, string endpointDisplayName)
{
_noComponentsRegisteredInEndpoint(logger, endpointDisplayName, null);
}
public static void ReceivedConfirmationForBatch(ILogger logger, long batchId)
{
_receivedConfirmationForBatch(logger, batchId, null);
}
public static void UnhandledExceptionInCircuit(ILogger logger, string circuitId, Exception exception)
{
_unhandledExceptionInCircuit(logger, circuitId, exception);
}
public static void FailedToTransmitException(ILogger logger, string circuitId, Exception transmissionException)
{
_failedToTransmitException(logger, circuitId, transmissionException);
}
}
} }
} }

View File

@ -242,7 +242,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
private class TestRemoteRenderer : RemoteRenderer private class TestRemoteRenderer : RemoteRenderer
{ {
public TestRemoteRenderer(IServiceProvider serviceProvider, RendererRegistry rendererRegistry, IDispatcher dispatcher, IJSRuntime jsRuntime, IClientProxy client) public TestRemoteRenderer(IServiceProvider serviceProvider, RendererRegistry rendererRegistry, IDispatcher dispatcher, IJSRuntime jsRuntime, IClientProxy client)
: base(serviceProvider, rendererRegistry, jsRuntime, new CircuitClientProxy(client, "connection"), dispatcher, HtmlEncoder.Default, NullLogger.Instance) : base(serviceProvider, NullLoggerFactory.Instance, rendererRegistry, jsRuntime, new CircuitClientProxy(client, "connection"), dispatcher, HtmlEncoder.Default, NullLogger.Instance)
{ {
} }

View File

@ -264,6 +264,7 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering
return new RemoteRenderer( return new RemoteRenderer(
serviceProvider, serviceProvider,
NullLoggerFactory.Instance,
new RendererRegistry(), new RendererRegistry(),
jsRuntime.Object, jsRuntime.Object,
circuitClientProxy, circuitClientProxy,

View File

@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.AspNetCore.Components.RenderTree;
using Microsoft.AspNetCore.Components.Server.Circuits; using Microsoft.AspNetCore.Components.Server.Circuits;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging.Abstractions;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -375,7 +376,7 @@ namespace Microsoft.AspNetCore.Components.Server
class FakeRenderer : Renderer class FakeRenderer : Renderer
{ {
public FakeRenderer() public FakeRenderer()
: base(new ServiceCollection().BuildServiceProvider(), new RendererSynchronizationContext()) : base(new ServiceCollection().BuildServiceProvider(), NullLoggerFactory.Instance, new RendererSynchronizationContext())
{ {
} }

View File

@ -46,6 +46,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
{ {
remoteRenderer = new RemoteRenderer( remoteRenderer = new RemoteRenderer(
serviceScope.ServiceProvider ?? Mock.Of<IServiceProvider>(), serviceScope.ServiceProvider ?? Mock.Of<IServiceProvider>(),
NullLoggerFactory.Instance,
new RendererRegistry(), new RendererRegistry(),
jsRuntime, jsRuntime,
clientProxy, clientProxy,

View File

@ -7,6 +7,7 @@ using System.Linq;
using System.Runtime.ExceptionServices; using System.Runtime.ExceptionServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.Extensions.Logging.Abstractions;
using Xunit; using Xunit;
namespace Microsoft.AspNetCore.Components.Test.Helpers namespace Microsoft.AspNetCore.Components.Test.Helpers
@ -17,11 +18,11 @@ namespace Microsoft.AspNetCore.Components.Test.Helpers
{ {
} }
public TestRenderer(IDispatcher dispatcher) : base(new TestServiceProvider(), dispatcher) public TestRenderer(IDispatcher dispatcher) : base(new TestServiceProvider(), NullLoggerFactory.Instance, dispatcher)
{ {
} }
public TestRenderer(IServiceProvider serviceProvider) : base(serviceProvider, new RendererSynchronizationContext()) public TestRenderer(IServiceProvider serviceProvider) : base(serviceProvider, NullLoggerFactory.Instance, new RendererSynchronizationContext())
{ {
} }

View File

@ -6,11 +6,13 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Castle.Core.Logging;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.AspNetCore.Components.RenderTree;
using Microsoft.AspNetCore.Components.Server.Circuits; using Microsoft.AspNetCore.Components.Server.Circuits;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging.Abstractions;
using Xunit; using Xunit;
namespace Ignitor namespace Ignitor
@ -333,7 +335,7 @@ namespace Ignitor
class FakeRenderer : Renderer class FakeRenderer : Renderer
{ {
public FakeRenderer() public FakeRenderer()
: base(new ServiceCollection().BuildServiceProvider(), new RendererSynchronizationContext()) : base(new ServiceCollection().BuildServiceProvider(), NullLoggerFactory.Instance, new RendererSynchronizationContext())
{ {
} }

View File

@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.AspNetCore.Components.RenderTree;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging.Abstractions;
namespace Ignitor namespace Ignitor
{ {
@ -288,7 +289,7 @@ namespace Ignitor
public class FakeRenderer : Renderer public class FakeRenderer : Renderer
{ {
public FakeRenderer() public FakeRenderer()
: base(new ServiceCollection().BuildServiceProvider(), new RendererSynchronizationContext()) : base(new ServiceCollection().BuildServiceProvider(), NullLoggerFactory.Instance, new RendererSynchronizationContext())
{ {
} }

View File

@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Mvc.ViewFeatures.RazorComponents namespace Microsoft.AspNetCore.Mvc.ViewFeatures.RazorComponents
{ {
@ -32,7 +33,8 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.RazorComponents
var dispatcher = Renderer.CreateDefaultDispatcher(); var dispatcher = Renderer.CreateDefaultDispatcher();
InitializeUriHelper(httpContext); InitializeUriHelper(httpContext);
using (var htmlRenderer = new HtmlRenderer(httpContext.RequestServices, _encoder.Encode, dispatcher)) var loggerFactory = (ILoggerFactory)httpContext.RequestServices.GetService(typeof (ILoggerFactory));
using (var htmlRenderer = new HtmlRenderer(httpContext.RequestServices, loggerFactory, dispatcher, _encoder.Encode))
{ {
ComponentRenderedText result = default; ComponentRenderedText result = default;
try try

View File

@ -13,6 +13,8 @@ using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures.RazorComponents; using Microsoft.AspNetCore.Mvc.ViewFeatures.RazorComponents;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.JSInterop; using Microsoft.JSInterop;
using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
using Moq; using Moq;
@ -224,6 +226,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Test
services.AddSingleton<IJSRuntime,UnsupportedJavaScriptRuntime>(); services.AddSingleton<IJSRuntime,UnsupportedJavaScriptRuntime>();
services.AddSingleton<IUriHelper,HttpUriHelper>(); services.AddSingleton<IUriHelper,HttpUriHelper>();
services.AddSingleton<StaticComponentRenderer>(); services.AddSingleton<StaticComponentRenderer>();
services.AddSingleton<ILoggerFactory, NullLoggerFactory>();
configureServices?.Invoke(services); configureServices?.Invoke(services);