# How Logging Is Implemented in ASP.NET Core: Architecture and Provider Deep Dive

> Explore ASP.NET Core logging architecture using Microsoft.Extensions.Logging. Understand the provider model and how ILoggerFactory creates ILogger instances for efficient message forwarding.

- Repository: [.NET Platform/aspnetcore](https://github.com/dotnet/aspnetcore)
- Tags: architecture
- Published: 2026-07-13

---

**ASP.NET Core implements logging through the Microsoft.Extensions.Logging abstraction, which uses a provider-based model where ILoggerFactory creates ILogger instances that forward messages to registered ILoggerProvider implementations configured via ILoggingBuilder during host startup.**

Logging in ASP.NET Core is built on a flexible, dependency injection-driven architecture defined in the **dotnet/aspnetcore** repository. The implementation centers on the `Microsoft.Extensions.Logging` namespace, where `ILoggerFactory` acts as a singleton composition root that aggregates multiple logging providers as implemented in [`src/Logging/LoggerFactory.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Logging/LoggerFactory.cs). This design allows applications to route log events to multiple destinations simultaneously while maintaining a unified programming model through constructor injection.

## Core Logging Abstractions

### ILogger and ILoggerFactory

The **`ILogger`** interface defines the minimal contract for writing log messages, exposing methods like `LogDebug`, `LogInformation`, and `LogError`. Application code typically receives an `ILogger<T>` via dependency injection, where the generic parameter represents the category name.

The **`ILoggerFactory`** implementation in [`src/Logging/LoggerFactory.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Logging/LoggerFactory.cs) serves as the central factory that creates `ILogger` instances and maintains the collection of registered providers. It is registered as a singleton in the DI container during host construction and caches logger instances by category name to optimize performance.

### ILoggerProvider and the Provider Model

Providers implement **`ILoggerProvider`** to supply concrete `ILogger` implementations for specific output destinations. The factory aggregates all registered providers and forwards each log event to every provider that has not filtered it out. Key built-in providers include:
- **`ConsoleLoggerProvider`** in [`src/Logging/Console/ConsoleLoggerProvider.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Logging/Console/ConsoleLoggerProvider.cs) for console output
- **`DebugLoggerProvider`** in [`src/Logging/Debug/DebugLoggerProvider.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Logging/Debug/DebugLoggerProvider.cs) for debugger output
- **Azure App Services integration** in [`src/Logging/AzureAppServices/AzureAppServicesLoggerFactoryExtensions.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Logging/AzureAppServices/AzureAppServicesLoggerFactoryExtensions.cs) for cloud diagnostics

### ILoggingBuilder Configuration

The **`ILoggingBuilder`** interface provides a fluent API for registering providers and configuring filters. The concrete implementation, **`LoggingBuilder`** in [`src/Components/WebAssembly/WebAssembly/src/Hosting/LoggingBuilder.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Components/WebAssembly/WebAssembly/src/Hosting/LoggingBuilder.cs) (lines 9-17), wraps the `IServiceCollection` and exposes extension methods like `AddConsole()` and `AddDebug()` defined in [`src/Logging/LoggingBuilderExtensions.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Logging/LoggingBuilderExtensions.cs).

## Host Integration and Service Wiring

### WebApplicationBuilder.Logging Property

In modern ASP.NET Core applications, the `WebApplicationBuilder` exposes a **`Logging`** property that returns an `ILoggingBuilder`. According to the source in [`src/DefaultBuilder/src/WebApplicationBuilder.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/DefaultBuilder/src/WebApplicationBuilder.cs) (lines 368-376), this property provides the primary entry point for configuring logging before the application starts.

### Host Builder Extensions

The **`WebHostBuilderExtensions`** class in [`src/Hosting/Hosting/src/WebHostBuilderExtensions.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Hosting/Hosting/src/WebHostBuilderExtensions.cs) (lines 20-28) provides the `ConfigureLogging` method, which allows programmatic configuration of the logging pipeline through `UseStartup` or direct builder configuration. These extensions forward any logging configuration supplied by the user to the DI container.

## Configuring Logging in Applications

Basic configuration in [`Program.cs`](https://github.com/dotnet/aspnetcore/blob/main/Program.cs) uses the `ILoggingBuilder` to add providers and set minimum levels:

```csharp
var builder = WebApplication.CreateBuilder(args);

// Register built-in providers via ILoggingBuilder
builder.Logging.AddConsole();          // Console output
builder.Logging.AddDebug();            // Debugger output  
builder.Logging.AddEventSourceLogger(); // EventSource for Azure diagnostics

// Set global minimum level
builder.Logging.SetMinimumLevel(LogLevel.Information);

var app = builder.Build();

app.MapGet("/", (ILogger<Program> logger) => 
{
    logger.LogInformation("Request received at {Time}", DateTime.Now);
    return "Check logs";
});

app.Run();

```

## Implementing Custom Logger Providers

Adding a custom provider requires implementing `ILoggerProvider` and creating an extension method for `ILoggingBuilder`:

```csharp
public class FileLoggerProvider : ILoggerProvider
{
    private readonly string _path;
    public FileLoggerProvider(string path) => _path = path;
    
    public ILogger CreateLogger(string category) => new FileLogger(_path, category);
    public void Dispose() { }
}

public static class FileLoggerExtensions
{
    public static ILoggingBuilder AddFile(this ILoggingBuilder builder, string path) =>
        builder.Services.AddSingleton<ILoggerProvider>(new FileLoggerProvider(path));
}

```

Usage follows the standard pattern exposed by `WebApplicationBuilder.Logging`:

```csharp
builder.Logging.AddFile("logs/app.log");

```

## Using Logger Scopes for Contextual Data

Scopes provide contextual information for grouped log operations using `ILogger.BeginScope`:

```csharp
using (_logger.BeginScope("Processing order {OrderId}", orderId))
{
    _logger.LogInformation("Validating payment");
    _logger.LogInformation("Updating inventory");
} // Scope ends here

```

All registered providers receive scope information. The console provider renders scope data as part of the message output, while other providers may serialize it differently according to their implementation.

## Summary

- **`ILoggerFactory`** in [`src/Logging/LoggerFactory.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Logging/LoggerFactory.cs) acts as the singleton composition root that aggregates providers and creates logger instances by category.
- **`ILoggingBuilder`** in [`src/Components/WebAssembly/WebAssembly/src/Hosting/LoggingBuilder.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Components/WebAssembly/WebAssembly/src/Hosting/LoggingBuilder.cs) wraps the service collection to enable fluent registration of providers like `ConsoleLoggerProvider` and `DebugLoggerProvider`.
- **`WebApplicationBuilder.Logging`** in [`src/DefaultBuilder/src/WebApplicationBuilder.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/DefaultBuilder/src/WebApplicationBuilder.cs) (lines 368-376) exposes the primary configuration entry point for minimal API applications.
- **Provider implementations** handle specific output destinations, with built-in support for console, debug, and Azure App Service diagnostics.
- The architecture supports hierarchical filtering (global, provider-specific, and category-specific) and scope propagation across all registered loggers.

## Frequently Asked Questions

### What is the difference between ILogger and ILoggerFactory in ASP.NET Core?

`ILogger` represents the writing surface that application code uses to emit log messages via methods like `LogInformation` and `LogDebug`. `ILoggerFactory` is the singleton factory responsible for creating `ILogger` instances and managing the collection of `ILoggerProvider` implementations. As implemented in [`src/Logging/LoggerFactory.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Logging/LoggerFactory.cs), the factory caches loggers by category and forwards each log event to all registered providers that accept the current log level.

### How do I add a custom logging provider to ASP.NET Core?

Implement `ILoggerProvider` to create loggers for your specific destination, then create an extension method on `ILoggingBuilder` that registers your provider with the service collection. The `LoggingBuilder` implementation in [`src/Components/WebAssembly/WebAssembly/src/Hosting/LoggingBuilder.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/Components/WebAssembly/WebAssembly/src/Hosting/LoggingBuilder.cs) demonstrates how these extensions wrap `IServiceCollection` to add providers to the DI container, making them available to the `ILoggerFactory` when the host builds the service provider.

### Where is the minimum log level configured in ASP.NET Core?

Minimum log levels can be configured globally via `ILoggingBuilder.SetMinimumLevel()` or per-provider using the `AddFilter` method. The `LoggerFactory` evaluates filters hierarchically: global minimums, provider-specific settings, and category-specific rules derived from the logger's category name all determine whether a message is written to a specific provider.

### How does logging work with dependency injection in ASP.NET Core?

The DI container resolves `ILogger<T>` by requesting it from the singleton `ILoggerFactory`, passing the fully qualified type name of `T` as the category. This occurs automatically when you include `ILogger<YourClass>` in your constructor, as wired through the host builder in [`src/DefaultBuilder/src/WebApplicationBuilder.cs`](https://github.com/dotnet/aspnetcore/blob/main/src/DefaultBuilder/src/WebApplicationBuilder.cs). The factory creates the logger instance and binds it to all registered providers configured via `builder.Logging`.