diff --git a/src/content/docs/accesstokenmanagement/advanced/logging.md b/src/content/docs/accesstokenmanagement/advanced/logging.md new file mode 100644 index 000000000..5f12dd386 --- /dev/null +++ b/src/content/docs/accesstokenmanagement/advanced/logging.md @@ -0,0 +1,30 @@ +--- +title: "Logging" +description: "Documentation for logging configuration and usage in Duende Access Token Management, including log levels and Serilog setup" +date: 2026-01-19 +sidebar: + order: 50 +--- + +Duende Access Token Management uses the standard logging facilities provided by ASP.NET Core. You generally do not need to perform any extra configuration, as it will use the logging provider you have already configured for your application. + +For general information on how to configure logging, setting up Serilog, and understanding log levels in Duende products, see our [Logging Fundamentals](/general/logging.md) guide. + +The Microsoft [documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging) has a good introduction and description of the built-in logging providers. + +## Log Levels + +You can control the log output for Duende Access Token Management specifically by configuring the `Duende.AccessTokenManagement` namespace in your logging configuration. +For example, to enable debug logging for Access Token Management while keeping other logs at a higher level, you can modify your `appsettings.json`: + +```json +// appsettings.json +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Duende.AccessTokenManagement": "Debug" + } + } +} +``` \ No newline at end of file diff --git a/src/content/docs/bff/diagnostics/index.md b/src/content/docs/bff/diagnostics/index.md index bfd69a825..527038a33 100644 --- a/src/content/docs/bff/diagnostics/index.md +++ b/src/content/docs/bff/diagnostics/index.md @@ -14,10 +14,28 @@ provided by ASP.NET Core, so you don't need to do any extra configuration to ben including support for multiple logging providers. See the Microsoft [documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging) for a good introduction on logging. BFF follows the standard logging levels defined by the .NET logging framework, and uses the Microsoft guidelines for -when certain log levels are used, similar to [how Duende IdentityServer uses log levels](/identityserver/diagnostics/logging.md). +when certain log levels are used. + +For general information on how to configure logging in Duende products, see our [Logging Fundamentals](/general/logging.md) guide. + +### Configuration Logs are typically written under the `Duende.Bff` category, with more concrete categories for specific components. +To get detailed logs from the BFF middleware with the `Microsoft.Extensions.Logging` framework, you can configure your `appsettings.json` to enable `Debug` level logs for the `Duende.Bff` namespace: + +```json +// appsettings.json +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Duende.Bff": "Debug" + } + } +} +``` + :::note[Multiple frontends] When using [multiple frontends and the `FrontendSelectionMiddleware`](/bff/architecture/multi-frontend.md), log messages are written in a log scope that contains a `frontend` property with the name of the frontend for which the diff --git a/src/content/docs/general/logging.md b/src/content/docs/general/logging.md new file mode 100644 index 000000000..160765f35 --- /dev/null +++ b/src/content/docs/general/logging.md @@ -0,0 +1,126 @@ +--- +title: "Logging Fundamentals" +description: "General guidance on configuring logging for Duende Software products using Microsoft.Extensions.Logging and Serilog." +date: 2026-01-19 +sidebar: + order: 10 +--- + +All Duende Software products (IdentityServer, Backend for Frontend (BFF), Access Token Management, etc.) use the standard logging facilities provided by ASP.NET Core (`Microsoft.Extensions.Logging`). +This means they integrate seamlessly with whatever logging provider you choose for your application. + +This guide provides general instructions for setting up logging that apply to all our products. + +## Log Levels + +We adhere to the standard Microsoft guidelines for log levels. Understanding these levels helps you configure the appropriate verbosity for your environment. + +* **`Trace`** + * **Usage:** Extremely detailed information for troubleshooting complex issues. + * **Production:** **Do not enable** in production unless specifically instructed for diagnostics. May contain sensitive data (e.g., token hashes, PII). +* **`Debug`** + * **Usage:** Internal flow details, useful for understanding _why_ a decision was made (e.g., policy evaluation, token validation steps). + * **Production:** Generally disabled in production, but safe to enable temporarily for deeper investigation. +* **`Information`** + * **Usage:** High-level events tracking the general flow (e.g., "Request started", "Token issued"). + * **Production:** Often the default level for production. +* **`Warning`** + * **Usage:** Unexpected events that didn't stop the application but might require investigation (e.g., "Invalid client configuration detected"). +* **`Error`** + * **Usage:** Exceptions and errors that cannot be handled gracefully. +* **`Critical`** + * **Usage:** Failures that require immediate attention (e.g., "Signing key not found"). + +## Setup for Microsoft.Extensions.Logging + +This is the default logging provider for ASP.NET Core. If you haven't configured a third-party logger, this is what you are using. + +You can configure log levels in your `appsettings.json` file. To get detailed logs from Duende products, you often want to set the `Duende` namespace (or specific sub-namespaces) to `Debug`. + +```json +// appsettings.json +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information", + // Enable Debug logs for all Duende products + "Duende": "Debug" + } + } +} +``` + +## Setup for Serilog + +[Serilog](https://serilog.net) is a popular structured logging library for .NET. We highly recommend it for its flexibility and rich sink ecosystem (Console, File, Seq, Elasticsearch, etc.). + +### 1. Installation + +Install the necessary packages: + +```bash +dotnet add package Serilog.AspNetCore +``` + +### 2. Configuration In `Program.cs` + +Configure Serilog early in your application startup to capture all logs, including startup errors. + +```csharp +// Program.cs +using Serilog; + +var builder = WebApplication.CreateBuilder(args); + +// Configure Serilog +builder.Host.UseSerilog((ctx, lc) => lc + .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}") + .Enrich.FromLogContext() + .ReadFrom.Configuration(ctx.Configuration)); + +var app = builder.Build(); + +app.UseSerilogRequestLogging(); // Optional: cleaner HTTP request logging + +// ... rest of your pipeline +``` + +### 3. Configuration In `appsettings.json` + +You can then control log levels via `appsettings.json`. This approach allows you to change log levels without recompiling your code. + +```json +{ + "Serilog": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information", + "System": "Warning", + // Enable detailed logging for Duende products + "Duende": "Debug" + } + } + } +} +``` + +## Troubleshooting Specific Products + +If you are debugging a specific component, you can target its namespace to reduce noise. + +| Product | Namespace | +|-----------------------------|--------------------------------| +| **IdentityServer** | `Duende.IdentityServer` | +| **BFF** | `Duende.Bff` | +| **Access Token Management** | `Duende.AccessTokenManagement` | + +Example `appsettings.json` for debugging only BFF interactions: + +```json +"Duende.Bff": "Debug", +"Duende.IdentityServer": "Information" +``` diff --git a/src/content/docs/identitymodel-oidcclient/logging.md b/src/content/docs/identitymodel-oidcclient/logging.md index 7f48d51b3..980f0305a 100644 --- a/src/content/docs/identitymodel-oidcclient/logging.md +++ b/src/content/docs/identitymodel-oidcclient/logging.md @@ -11,7 +11,11 @@ redirect_from: `OidcClient` logs errors, warnings, and diagnostic information using `Microsoft.Extensions.Logging.ILogger`, the standard .NET logging library. -```csharp +You can use any logging provider to store your logs however you like, +by setting the `LoggerFactory` property on `OidcClientOptions`: + +```csharp {9,17} +// Program.cs using Duende.IdentityModel; using Duende.IdentityModel.OidcClient; @@ -36,20 +40,9 @@ var app = builder.Build(); var client = app.Services.GetService(); ``` -You can use any logging provider to store your logs however you like, by setting the `LoggerFactory` property on `OidcClientOptions`. - -For example, you could configure -[Serilog](https://github.com/serilog/serilog-extensions-hosting) like this: +Using this approach, you can use other logging frameworks, like [Serilog](https://github.com/serilog/serilog-extensions-hosting) for example. -```csharp -var serilog = new LoggerConfiguration() - .MinimumLevel.Verbose() - .Enrich.FromLogContext() - .WriteTo.LiterateConsole(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message}{NewLine}{Exception}{NewLine}") - .CreateLogger(); - -options.LoggerFactory.AddSerilog(serilog); -``` +For general information on how to configure logging in .NET applications, see our [Logging Fundamentals](/general/logging.md) guide. ## Log Levels @@ -63,6 +56,7 @@ The `OidcClient` logs at the following levels: You can set the log level in your `appsettings.json` by modifying the following snippet. ```json +// appsettings.json { "Logging": { "LogLevel": { diff --git a/src/content/docs/identityserver/diagnostics/logging.md b/src/content/docs/identityserver/diagnostics/logging.md index 72b4749a8..c99c81829 100644 --- a/src/content/docs/identityserver/diagnostics/logging.md +++ b/src/content/docs/identityserver/diagnostics/logging.md @@ -10,11 +10,13 @@ redirect_from: - /identityserver/v7/diagnostics/logging/ --- -Duende IdentityServer uses the standard logging facilities provided by ASP.NET Core. You don't need to do any extra -configuration. +Duende IdentityServer uses the standard logging facilities provided by ASP.NET Core. You don't need to do any extra configuration to benefit from rich logging functionality. -The Microsoft [documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging) has a good intro and a -description of the built-in logging providers. +For general information on how to configure logging, setting up Serilog, and understanding log levels in Duende products, see our [Logging Fundamentals](/general/logging.md) guide. + +## Configuration + +Logs are typically written under the `Duende.IdentityServer` category. We are roughly following the Microsoft guidelines for usage of log levels: @@ -45,165 +47,25 @@ We are roughly following the Microsoft guidelines for usage of log levels: For failures that require immediate attention. Examples: missing store implementation, invalid key material... -:::note -In production, logging might produce too much data. It is recommended you either turn it off, or default to the -`Warning` level. Have a look at [events](/identityserver/diagnostics/events.md) for more high-level production -instrumentation. -::: - -### Setup for Microsoft.Extensions.Logging - -.NET provides a logging abstraction interface found in the -[`Microsoft.Extensions.Logging`](https://www.nuget.org/packages/Microsoft.Extensions.Logging) package and is the default logging provider for ASP.NET Core. - -If you prefer to use Microsoft's logging option, -you can remove references to Serilog and fall back to the default logging implementation. -Duende IdentityServer already uses the `ILogger` interface, -and will use any implementation registered with the services collection. - -Below you will find a modified version of the in-memory Duende IdentityServer sample. -You can use it as a guide to adapt your own instance of Duende IdentityServer to use Microsoft's logging implementation.. - -```csharp -using System.Globalization; -using System.Text; -using Duende.IdentityServer.Licensing; - -// App1 contains WebApplicationBuilder extension methods -// update according to your application's namespace -using App1; - -var builder = WebApplication.CreateBuilder(args); - -var app = builder - // WebApplicationBuilder extension methods - .ConfigureServices() - .ConfigurePipeline(); - -try -{ - app.Logger.LogInformation("Starting up"); - - if (app.Environment.IsDevelopment()) - { - app.Lifetime.ApplicationStopping.Register(() => - { - var usage = app.Services.GetRequiredService(); - - app.Logger.LogInformation(Summary(usage)); - }); - } - - app.Run(); -} -catch (Exception ex) when (ex is not HostAbortedException) -{ - app.Logger.LogCritical(ex, "Host terminated unexpectedly"); -} -finally -{ - app.Logger.LogInformation("Shut down complete"); -} - -static string Summary(LicenseUsageSummary usage) -{ - var sb = new StringBuilder(); - sb.AppendLine("IdentityServer Usage Summary:"); - sb.AppendLine(CultureInfo.InvariantCulture, $" License: {usage.LicenseEdition}"); - var features = usage.FeaturesUsed.Count > 0 ? string.Join(", ", usage.FeaturesUsed) : "None"; - sb.AppendLine(CultureInfo.InvariantCulture, $" Business and Enterprise Edition Features Used: {features}"); - sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.ClientsUsed.Count} Client Id(s) Used"); - sb.AppendLine(CultureInfo.InvariantCulture, $" {usage.IssuersUsed.Count} Issuer(s) Used"); - - return sb.ToString(); -} -``` - -You will also need to modify the `appSettings.json` file to include the `Logging` section: +To get detailed logs from IdentityServer, you can configure your `appsettings.json` to enable `Debug` or `Information` level logs for the `Duende.IdentityServer` namespace: ```json +// appsettings.json { "Logging": { "LogLevel": { "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information", "Duende.IdentityServer": "Information" } - }, - "AllowedHosts": "*" -} -``` - -Learn more about configuring logging in .NET applications by reading the [Microsoft documentation on logging fundamentals](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-9.0#configure-logging). As you'll see in the Microsoft documentation, configuring logging can be very involved and target different log levels, which can be useful for troubleshooting. - -### Setup For Serilog - -[Serilog](https://serilog.net) is a trusted and popular logging library for .NET applications. -It is highly configurable, -and at Duende, we think it is a **great alternative** to the default logging -implementation, -especially for .NET developers looking for more control over their logging configuration. -Additionally, -ASP.NET Core developers can use the [Serilog.AspNetCore](https://github.com/serilog/serilog-aspnetcore) for -better integration with ASP.NET Core applications. - -```csharp -// Program.cs -Activity.DefaultIdFormat = ActivityIdFormat.W3C; - -Log.Logger = new LoggerConfiguration() - .MinimumLevel.Debug() - .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) - .MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Information) - .MinimumLevel.Override("System", LogEventLevel.Warning) - .MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information) - .Enrich.FromLogContext() - .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Code) - .CreateLogger(); - -builder.Logging.AddSeriLog(); -``` - -You can also use ASP.NET Core's configuration pattern to configure Serilog using `appsettings.json` and other configuration sources. -To do so, you first need to tell Serilog to read its configuration from the `IConfiguration` root: - -```csharp {11} -// Program.cs - -var builder = WebApplication.CreateBuilder(args); - -builder.Services.AddSerilog(lc => lc - .WriteTo.Console( - outputTemplate: - "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", - formatProvider: CultureInfo.InvariantCulture) - .Enrich.FromLogContext() - .ReadFrom.Configuration(builder.Configuration)); -``` - -Then, in your `appsettings.json` file, you can set the default minimum log level and log level overrides like so: - -```json {12} -// appsettings.json - -{ - "Serilog": { - "MinimumLevel": { - "Default": "Debug", - "Override": { - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information", - "Microsoft.AspNetCore.Authentication": "Debug", - "System": "Warning", - "Duende": "Verbose" // As an example, we've enabled more verbose logging for the Duende.* namespace - } - } } } ``` -## Filtering Exceptions +:::note +In production, logging might produce too much data. It is recommended you either turn it off, or default to the `Warning` level. Have a look at [events](/identityserver/diagnostics/events.md) for more high-level production instrumentation. +::: + +### Filtering Exceptions The `LoggingOptions` class allows developers to filter out any exceptions that could potentially lead to log bloat. For example, in a web application, developers @@ -231,7 +93,7 @@ var isBuilder = builder.Services.AddIdentityServer(options => { options.Logging.UnhandledExceptionLoggingFilter = (ctx, ex) => { - if (ctx.User is { Identity.Name: "Jeff" }) + if (ctx.User is { Identity.Name: "Jeff" }) { // Oh Jeff... return false;