diff --git a/docs/core/enrichment/custom-enricher.md b/docs/core/enrichment/custom-enricher.md new file mode 100644 index 0000000000000..9631936a1b9aa --- /dev/null +++ b/docs/core/enrichment/custom-enricher.md @@ -0,0 +1,98 @@ +--- +title: Custom log enricher +description: Learn how to use the custom log enricher in .NET. +ms.date: 10/13/2025 +--- + +# Custom log enricher + +You can easily create a custom enricher by creating a class that implements the interface. +After the class is created, you register it with . +Once registered, the logging infrastructure automatically calls the `Enrich()` method on every registered enricher for each log message produced. + +## Install the package + +To get started, install the [📦 Microsoft.Extensions.Telemetry.Abstractions](https://www.nuget.org/packages/Microsoft.Extensions.Telemetry.Abstractions) NuGet package: + +### [.NET CLI](#tab/dotnet-cli) + +```dotnetcli +dotnet add package Microsoft.Extensions.Telemetry.Abstractions +``` + +Or, if you're using .NET 10+ SDK: + +```dotnetcli +dotnet package add Microsoft.Extensions.Telemetry.Abstractions +``` + +### [PackageReference](#tab/package-reference) + +```xml + +``` + +--- + +## Implementation + +Your custom enricher only needs to implement a single method. +During enrichment, this method is called and given an instance. The enricher then calls one of the overloads of +the method to record any properties it wants. + +> [!NOTE] +> If your custom log enricher calls , +> it is acceptable to send any type of argument to the `value` parameter as is, because it is parsed into the actual type and serialized internally +> to be sent further down the logging pipeline. + +```csharp +public class CustomEnricher : ILogEnricher +{ + // Your custom code + + public void Enrich(IEnrichmentTagCollector collector) + { + // Call Add to add all required key/value pair to enrich logs with. + foreach(var property in propertiesToEnrichWith) + { + collector.Add(propertyName, propertyValue); + } + } +} + +... + +var hostBuilder = new HostBuilder() + .ConfigureServices((_, serviceCollection) => + { + _ = serviceCollection.AddLogEnricher()); + }); +``` + +It's also possible to configure manual instantiation of custom enrichers: + +```csharp +public class AnotherEnricher : ILogEnricher() { } +... + +var hostBuilder = new HostBuilder() + .ConfigureServices((_, serviceCollection) => + { + _ = serviceCollection.AddLogEnricher(new AnotherEnricher())); + }); +``` + +Alternatively: + +```csharp +var hostApplicationBuilder = WebApplication.CreateBuilder(); +hostApplicationBuilder.Services.AddLogEnricher(); +``` + +and + +```csharp +var hostApplicationBuilder = WebApplication.CreateBuilder(); +hostApplicationBuilder.Services.AddLogEnricher(new AnotherEnricher())); +``` diff --git a/docs/core/enrichment/json-output-all-enabled.json b/docs/core/enrichment/json-output-all-enabled.json new file mode 100644 index 0000000000000..31cabf3e1e4ce --- /dev/null +++ b/docs/core/enrichment/json-output-all-enabled.json @@ -0,0 +1,12 @@ +{ + "EventId": 0, + "LogLevel": "Information", + "Category": "Enrichment.Program", + "Message": "This is a sample log message", + "State": { + "Message": "This is a sample log message", + "process.pid": "12924", + "thread.id": "2", + "{OriginalFormat}": "This is a sample log message" + } +} \ No newline at end of file diff --git a/docs/core/enrichment/json-output.json b/docs/core/enrichment/json-output.json new file mode 100644 index 0000000000000..afe2ae1f4b8de --- /dev/null +++ b/docs/core/enrichment/json-output.json @@ -0,0 +1,11 @@ +{ + "EventId": 0, + "LogLevel": "Information", + "Category": "Enrichment.Program", + "Message": "This is a sample log message", + "State": { + "Message": "This is a sample log message", + "process.pid": "10696", + "{OriginalFormat}": "This is a sample log message" + } +} \ No newline at end of file diff --git a/docs/core/enrichment/overview.md b/docs/core/enrichment/overview.md new file mode 100644 index 0000000000000..da87a80f56de4 --- /dev/null +++ b/docs/core/enrichment/overview.md @@ -0,0 +1,58 @@ +--- +title: Log enrichment overview +description: Learn about log enrichment in .NET and how to enhance your logs with contextual information. +ms.date: 10/13/2025 +--- + +# Overview + +Log enrichment is a powerful feature that automatically attaches contextual information to your application's logs. Instead of manually adding metadata to each log, enrichment provides a systematic way to inject relevant context automatically across your entire application. + +## What is enrichment? + +Enrichment augments telemetry objects with additional information that provides valuable context about the environment, application state, and execution context when the telemetry was generated. This contextual data helps with debugging, monitoring, performance analysis, and understanding application behavior in production environments. + +## How enrichment works + +The enrichment framework operates through a collection of enrichers that are registered with the dependency injection container. When telemetry is generated, all registered enrichers automatically contribute their contextual information to the telemetry payload. You just register the specific set of enrichers you want into +an instance. The enrichers run automatically without requiring changes to your application code. You simply configure which enrichers you want to use during application startup. + +## Dimension names and tags + +Enrichers add information to telemetry using standardized dimension names (also called tags or keys). + +## Setting up enrichment + +To use log enrichment in your application, you need to: + +1. **Enable enrichment** for logging +2. **Register specific enrichers** you want to use +3. **Configure options** for each enricher (optional) + +### Basic setup example + +Here's a simple example showing how to set up log enrichment with process information: + +:::code language="csharp" source="snippets/enrichment/Program.cs" range="3-34" highlight="13,14"::: + +This configuration: + +- Enables enrichment for logging via `EnableEnrichment()` +- Registers the process log enricher via `AddProcessLogEnricher()` +- Configures JSON console output to display the enriched data + +### Output example + +With enrichment enabled, your log output will automatically include additional contextual information: + +:::code language="json" source="json-output.json" highlight="8"::: + +## Available enrichers + +The .NET enrichment framework provides some built-in enrichers, like: + +- **[Process enricher](process-log-enricher.md)**: Process and thread information + +## Custom enrichers + +If the built-in enrichers don't meet your specific needs, you can create custom enrichers to add application-specific context. For more information, check [custom enrichment](custom-enricher.md). diff --git a/docs/core/enrichment/process-log-enricher.md b/docs/core/enrichment/process-log-enricher.md new file mode 100644 index 0000000000000..c2daba92fcc6d --- /dev/null +++ b/docs/core/enrichment/process-log-enricher.md @@ -0,0 +1,81 @@ +--- +title: Process log enricher +description: Learn how to use the process log enricher in .NET. +ms.date: 10/10/2025 +--- + +# Process log enricher + +The process enricher augments telemetry logs with process-specific information. + +You can register the enrichers in an IoC container. Then, all registered enrichers are picked up automatically by the respective telemetry instances, such as logs or metrics, where they enrich the telemetry information. + +## Install the package + +To get started, install the [📦 Microsoft.Extensions.Telemetry](https://www.nuget.org/packages/Microsoft.Extensions.Telemetry) NuGet package: + +### [.NET CLI](#tab/dotnet-cli) + +```dotnetcli +dotnet add package Microsoft.Extensions.Telemetry +``` + +Or, if you're using .NET 10+ SDK: + +```dotnetcli +dotnet package add Microsoft.Extensions.Telemetry +``` + +## Usage + +To be able to use the process log enricher, first you need to enable enrichment. Then you can add the with default properties, like this: + +:::code language="csharp" source="snippets/enrichment/Program.cs" range="3-34" highlight="13,14"::: + +Given this code sample, the output should be like this: + +:::code language="json" source="json-output.json" highlight="8"::: + +## `ProcessLogEnricherOptions` + +The class provides fine-grained control over which process-related properties are included in your log enrichment. This options class allows you to selectively enable or disable specific enrichment features such as process ID and thread ID information. Although default properties are supplied by the process enricher, you can customize them by initializing an instance of and providing it when registering the enricher. + +You can enable or disable individual options of the enricher using : + +```cs +serviceCollection.AddProcessLogEnricher(options => +{ + options.ThreadId = true; + options.ProcessId = true; +}); +``` + +You may also disable or enable individual options using `appsettings.json` file configuration, for example: + +```json +{ + "ProcessLogEnricherOptions": { + "ThreadId": true, + "ProcessId": true + } +} +``` + +and apply it accordingly using : + +```cs +serviceCollection.AddProcessLogEnricher(hostBuilder.Configuration.GetSection("ProcessLogEnricherOptions")); +``` + +The console output after enabling both options should look like this: + +:::code language="json" source="json-output-all-enabled.json" highlight="8,9"::: + +## Default configuration + +The default configuration for process log enrichment is: + +| Property | Default Value | Description | +| -----------| ----------------|--------------------------------------------------------------| +| `ProcessId` | true | If true, logs are enriched with the current process ID. | +| `ThreadId` | false | If true, logs are enriched with the current thread ID | diff --git a/docs/core/enrichment/snippets/enrichment/Enrichment.csproj b/docs/core/enrichment/snippets/enrichment/Enrichment.csproj new file mode 100644 index 0000000000000..3b0e57857694e --- /dev/null +++ b/docs/core/enrichment/snippets/enrichment/Enrichment.csproj @@ -0,0 +1,17 @@ + + + + Exe + net9.0 + enable + enable + + + + + + + + + + diff --git a/docs/core/enrichment/snippets/enrichment/Program.cs b/docs/core/enrichment/snippets/enrichment/Program.cs new file mode 100644 index 0000000000000..e2c636eea9efc --- /dev/null +++ b/docs/core/enrichment/snippets/enrichment/Program.cs @@ -0,0 +1,35 @@ +#define first +#if first +using System.Text.Json; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace Enrichment +{ + internal class Program + { + public static async Task Main() + { + var builder = Host.CreateApplicationBuilder(); + builder.Logging.EnableEnrichment(); + builder.Services.AddProcessLogEnricher(); + builder.Logging.AddJsonConsole(op => + { + op.JsonWriterOptions = new JsonWriterOptions + { + Indented = true + }; + }); + var hostBuilder = builder.Build(); + var logger = + hostBuilder.Services.GetRequiredService().CreateLogger(); + + logger.LogInformation("This is a sample log message"); + + await hostBuilder.RunAsync(); + + } + } +} +#endif diff --git a/docs/navigate/tools-diagnostics/toc.yml b/docs/navigate/tools-diagnostics/toc.yml index bd5206dcaaf63..6074077eebbdf 100644 --- a/docs/navigate/tools-diagnostics/toc.yml +++ b/docs/navigate/tools-diagnostics/toc.yml @@ -446,6 +446,14 @@ items: href: ../../core/diagnostics/distributed-tracing-collection-walkthroughs.md - name: Built-in activities href: ../../core/diagnostics/distributed-tracing-builtin-activities.md + - name: Enrichment + items: + - name: Overview + href: ../../core/enrichment/overview.md + - name: Process log enricher + href: ../../core/enrichment/process-log-enricher.md + - name: Custom enricher + href: ../../core/enrichment/custom-enricher.md - name: Specialized diagnostics items: - name: Overview