Blazor WebAssembly – Changing The Log Level At Runtime

With Blazor WebAssembly we are now able to create single-page applications (SPA) using C# and the ASP.NET Core Framework. When coming from ASP.NET Core MVC, you may ask yourself what .NET features are available, limited, or not available when running in the browser. One of them is logging, which is a basic means for debugging in both production environments and during development.

In diesem Artikel:

Blazor WebAssembly – Changing The Log Level At Runtime
Pawel Gerr ist Architekt und Consultant bei Thinktecture. Er hat sich auf .NET Core Backends spezialisiert und kennt Entity Framework von vorne bis hinten.

Log levels in production

In this article, I will be looking back at my post about changing the log level from 2017. But this time, it will not be a full-featured platform like .NET Core 3.1 – but rather a browser with Blazor WebAssembly and .NET Standard code. The reason I use this feature is still the same as in 2017: By default, my applications usually have a log level of Information. If there is an issue in my code, I want to know the reason for it and then I need to lower the log level to get more information without rebuilding or restarting the application – in other words. reload the SPA. The main reason a reload of the app is undesirable is that the issue (which may be hard to reproduce) may just disappear.

Available log levels when using the Microsoft logging framework:

				
					public enum LogLevel
{
  Trace,
  Debug,
  Information,
  Warning,
  Error,
  Critical,
  None
}
				
			

Version information

.NET Core SDK: 3.1.302
ASP.NET Core Blazor WebAssembly: 3.2.1

The mentioned blog post from 2017 is addressing two logging frameworks, the Microsoft.Extensions.Logging and Serilog. This article here focuses on Microsoft.Extensions.Logging for simplicity reasons.

Demo application

To get started right away, I use the demo application that comes with the SDK. For that, we create a new Blazor WebAssembly project and make sure it works properly.

				
					dotnet new blazorwasm -o BlazorApp1
cd BlazorApp1
dotnet run
				
			

For the verification of the feature, we are going to implement a means to create a few logs. Let us put a new button on the page Index.razor which creates logs on a click.

				
					@page "/"

@using Microsoft.Extensions.Logging
@inject ILogger<Index> Logger

<button @onclick="CreateLogs">Create logs</button>

@functions {
    private void CreateLogs()
    {
        var logLevels = Enum.GetValues(typeof(LogLevel)).Cast<LogLevel>();

        foreach (var logLevel in logLevels.Where(l => l != LogLevel.None))
        {
            Logger.Log(logLevel, logLevel.ToString());
        }
    }
}
				
			

After starting the app and performing a click on the button, we should see some logs in the browser console.

There are 2 interesting points worth mentioning:

  • The WebAssemblyHostBuilder in Blazor WebAssembly registers a logging provider (WebAssemblyConsoleLoggerProvider) which logs onto the browser console
  • The default log level is Information (otherwise we would see the logs Debug and Trace)

Binding the log level to IConfiguration (a precondition for what comes next)

By default, there is no other way to change the log level besides hard-coding it using the WebAssemblyHostBuilder.

				
					// Program.cs

public static async Task Main(string[] args)
{
   var builder = WebAssemblyHostBuilder.CreateDefault(args);
   
   builder.Logging.SetMinimumLevel(LogLevel.Debug);
   ...
}

				
			

But we won’t do that. Instead, we bind the logger to the IConfiguration using the extension method AddConfiguration from the Nuget package Microsoft.Extensions.Logging.Configuration.

				
					// Program.cs

public static async Task Main(string[] args)
{
   var builder = WebAssemblyHostBuilder.CreateDefault(args);

   ConfigureLogging(builder);
   ...
}

private static void ConfigureLogging(
  WebAssemblyHostBuilder builder,
  string section = "Logging")
{
   builder.Logging.AddConfiguration(builder.Configuration.GetSection(section));
} 
				
			

To verify the results, we create a new file appsettings.json in the folder wwwroot, which changes the log level to Debug.

				
					{
    "Logging": {
        "LogLevel": {
            "Default": "Debug"
        }
    }
}
				
			

By switching the log level to Debug, we see our logs as well as the ones from Blazor.

Changing log level at runtime

For changing the log level at runtime, we need an implementation of a ConfigurationProvider that adds/changes the configuration values in memory. To save our customers (and me) some time, I made a few Nuget packages that provide the required components. In our demo we need Thinktecture.Extensions.Logging.Configuration which is made for Microsoft.Extensions.Logging.

Furthermore, we have to register the LoggingConfiguration with the current configuration builder and add it to the dependency injection (DI).

				
					private static void ConfigureLogging(
  WebAssemblyHostBuilder builder,
  string section = "Logging")
{
   var loggingConfig = new LoggingConfiguration();
   builder.Services.AddSingleton<ILoggingConfiguration>(loggingConfig);
   builder.Configuration.AddLoggingConfiguration(loggingConfig, section);

   builder.Logging.AddConfiguration(builder.Configuration.GetSection(section));
}
				
			

After adding the LoggingConfiguration to DI, we can inject it anywhere in the app using the interface ILoggingConfiguration.

Next, we create a UI component to be able to change the log level at runtime. For that, we create a new file LogLevelOverride.razor in the folder Shared with the following content.

				
					@using Thinktecture.Extensions.Configuration
@using Microsoft.Extensions.Logging

@inject ILoggingConfiguration Config
@inject ILogger<LogLevelOverride> Logger

<div>
    <label>
        Log Level override:
        <select @onchange="ChangeLogLevel">
            <option> - </option>

            @foreach (var logLevel in Enum.GetValues(typeof(LogLevel)))
            {
                <option value="@logLevel">@logLevel</option>
            }
        </select>
    </label>
</div>

@code{
    private void ChangeLogLevel(ChangeEventArgs obj)
    {
        if (Enum.TryParse(obj.Value?.ToString(), out LogLevel logLevel))
        {
            Config.SetLevel(logLevel);
        }
        else
        {
            Config.ResetLevel();
        }
    }
}
				
			

The last step is to finally add the component to the page Index.razor and to try it out.

				
					@page "/"

@using Microsoft.Extensions.Logging
@inject ILogger<Index> Logger

<LogLevelOverride />

<button @onclick="CreateLogs">Create logs</button>
...
				
			

Now we can set and reset (to default specified in appsettings.json) the log level at any time.

Summary

In this article, we saw how to change the log level of a Blazor WebAssembly application at runtime to get more (or less) information out of the application. A temporal change of the log level for debugging purposes is just one step in making the software development and maintenance easier. The next step could be a diagnostics page with more tools and statistics to get even more data out of the SPA.

Kostenloser
Newsletter

Aktuelle Artikel, Screencasts, Webinare und Interviews unserer Experten für Sie

Verpassen Sie keine Inhalte zu Angular, .NET Core, Blazor, Azure und Kubernetes und melden Sie sich zu unserem kostenlosen monatlichen Dev-Newsletter an.

Diese Artikel könnten Sie interessieren
ASP.NET Core
Architektur-Modernisierung: Migration von WCF zu gRPC mit ASP.NET Core – ein pragmatischer Ansatz

Architektur-Modernisierung: Migration von WCF zu gRPC mit ASP.NET Core – ein pragmatischer Ansatz

Viele Projekte mit verteilten Anwendungen in der .NET-Welt basieren noch auf der Windows Communication Foundation (WCF). Doch wie kommt man weg von der "Altlast" und wie stellt man seinen Code auf sowohl moderne als auch zukunftssichere Beine? Eine mögliche Lösung ist gRPC.

13.04.2023
ASP.NET Core
gRPC Code-First mit ASP.NET Core 7 und Blazor WebAssembly

gRPC Code-First mit ASP.NET Core 7 und Blazor WebAssembly

Wie in allen anderen browserbasierten Single-Page-Application (SPA) Frameworks, ist Blazor WebAssembly JSON-over-HTTP (über Web- oder REST-APIs) die bei weitem häufigste Methode, um Daten auszutauschen und serverseitige Vorgänge auszulösen. Der Client sendet eine HTTP-Anfrage mit JSON-Daten an eine URL, mitunter über unterschiedliche HTTP-Verben. Anschließend führt der Server eine Operation aus und antwortet mit einem HTTP-Statuscode und den resultierenden JSON-Daten. Warum sollte man das ändern? Nun, es gibt Gründe - vor allem wenn man in einem geschlossenen System ist und .NET sowohl im Frontend als auch im Backend einsetzt.
30.03.2023
ASP.NET Core
Blazor WebAssembly in .NET 7: UI-Performance-Optimierung auf Komponentenebene

Blazor WebAssembly in .NET 7: UI-Performance-Optimierung auf Komponentenebene

Stockende UI, keine Reaktion nach dem Klick auf einen Button oder einer Eingabe in einem Feld - dies sind nur wenige Beispiele alltäglicher Probleme, die der Nutzung von Client-Anwendungen im Allgemeinen, und bei Webanwendungen im Speziellen, immer wieder auftreten können. In diesem Artikel schauen wir uns an, wie wir komponentenbasierte UIs in Blazor WebAssembly optimieren können, um dadurch eine für die Benutzer zufriedenstellende Geschwindigkeit und ein flüssiges UI zu bekommen.
29.03.2023
.NET
Understanding and Controlling the Blazor WebAssembly Startup Process

Understanding and Controlling the Blazor WebAssembly Startup Process

There are a lot of things going on in the background, when a Blazor WebAssembly application is being started. In some cases you might want to take a bit more control over that process. One example might be the wish to display a loading screen for applications that take some time for initial preparation, or when users are on a slow internet connection. However, in order to control something, we need to understand what is happening first. This article takes you down the rabbit hole of how a Blazor WASM application starts up.
07.03.2023
.NET
Adding Superpowers to your Blazor WebAssembly App with Project Fugu APIs

Adding Superpowers to your Blazor WebAssembly App with Project Fugu APIs

Blazor WebAssembly is a powerful framework for building web applications that run on the client-side. With Project Fugu APIs, you can extend the capabilities of these apps to access new device features and provide an enhanced user experience. In this article, learn about the benefits of using Project Fugu APIs, the wrapper packages that are available for Blazor WebAssembly, and how to use them in your application.

Whether you're a seasoned Blazor developer or just getting started, this article will help you add superpowers to your Blazor WebAssembly app.
28.02.2023
.NET
Blazor WebAssembly in Practice: Maturity, Success Factors, Showstoppers

Blazor WebAssembly in Practice: Maturity, Success Factors, Showstoppers

ASP.NET Core Blazor is Microsoft's framework for implementing web-based applications, aimed at developers with knowledge of .NET and C#. It exists alongside other frameworks such as ASP.NET Core MVC. About two and a half years after the release of Blazor WebAssembly and based on our experiences from many customer projects at Thinktecture, we want to have a close look at the following questions: What is the current state of the framework? How can you successfully use Blazor? And where does it have limitations?
24.11.2022