Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/list-of-diagnostics.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ You may continue using obsolete APIs in your application, but we advise explorin
| Diagnostic ID | Description |
| :---------------- | :---------- |
| `EXTOBS0001` | This API is obsolete and will be removed in a future version. Consider using [Resource Monitoring observable instruments](https://learn.microsoft.com/dotnet/core/diagnostics/built-in-metrics-diagnostics#microsoftextensionsdiagnosticsresourcemonitoring). |
| `EXTOBS0002` | This API is obsolete and will be removed in a future version. Instead of the AddServiceLogEnricher() methods, consider using the respective AddApplicationLogEnricher() methods. |

# LoggerMessage

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Diagnostics.Enrichment;
using Microsoft.Shared.DiagnosticIds;
using Microsoft.Shared.Diagnostics;

namespace Microsoft.Extensions.DependencyInjection;
Expand All @@ -19,22 +21,65 @@ public static class ApplicationEnricherServiceCollectionExtensions
/// <param name="services">The <see cref="IServiceCollection"/> to add the service enricher to.</param>
/// <returns>The value of <paramref name="services"/>.</returns>
/// <exception cref="ArgumentNullException"><paramref name="services"/> is <see langword="null"/>.</exception>
public static IServiceCollection AddServiceLogEnricher(this IServiceCollection services)
[Obsolete(
DiagnosticIds.Obsoletions.ObsoleteTelemetryApiMessage,
DiagnosticId = DiagnosticIds.Obsoletions.ObsoleteTelemetryApiDiagId,
UrlFormat = DiagnosticIds.UrlFormat)]
public static IServiceCollection AddServiceLogEnricher(this IServiceCollection services) =>
services.AddApplicationLogEnricher(_ => { });

/// <summary>
/// Adds an instance of the service enricher to the <see cref="IServiceCollection"/>.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> to add the service enricher to.</param>
/// <param name="configure">The <see cref="ApplicationLogEnricherOptions"/> configuration delegate.</param>
/// <returns>The value of <paramref name="services"/>.</returns>
/// <exception cref="ArgumentNullException">Any of the arguments is <see langword="null"/>.</exception>
[Obsolete(
DiagnosticIds.Obsoletions.ObsoleteTelemetryApiMessage,
DiagnosticId = DiagnosticIds.Obsoletions.ObsoleteTelemetryApiDiagId,
UrlFormat = DiagnosticIds.UrlFormat)]
public static IServiceCollection AddServiceLogEnricher(this IServiceCollection services, Action<ApplicationLogEnricherOptions> configure) =>
services.AddApplicationLogEnricher(configure);

/// <summary>
/// Adds an instance of the service enricher to the <see cref="IServiceCollection"/>.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> to add the service enricher to.</param>
/// <param name="section">The <see cref="IConfigurationSection"/> to use for configuring <see cref="ApplicationLogEnricherOptions"/> in the service enricher.</param>
/// <returns>The value of <paramref name="services"/>.</returns>
/// <exception cref="ArgumentNullException">Any of the arguments is <see langword="null"/>.</exception>
[Obsolete(
DiagnosticIds.Obsoletions.ObsoleteTelemetryApiMessage,
DiagnosticId = DiagnosticIds.Obsoletions.ObsoleteTelemetryApiDiagId,
UrlFormat = DiagnosticIds.UrlFormat)]
public static IServiceCollection AddServiceLogEnricher(this IServiceCollection services, IConfigurationSection section) =>
services.AddApplicationLogEnricher(section);

/// <summary>
/// Adds an instance of the application enricher to the <see cref="IServiceCollection"/>.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> to add application enricher to.</param>
/// <returns>The value of <paramref name="services"/>.</returns>
/// <exception cref="ArgumentNullException"><paramref name="services"/> is <see langword="null"/>.</exception>
[Experimental(diagnosticId: DiagnosticIds.Experiments.Telemetry, UrlFormat = DiagnosticIds.UrlFormat)]
public static IServiceCollection AddApplicationLogEnricher(this IServiceCollection services)
{
_ = Throw.IfNull(services);

return services
.AddServiceLogEnricher(_ => { });
.AddApplicationLogEnricher(_ => { });
}

/// <summary>
/// Adds an instance of the service enricher to the <see cref="IServiceCollection"/>.
/// Adds an instance of the application enricher to the <see cref="IServiceCollection"/>.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> to add the service enricher to.</param>
/// <param name="services">The <see cref="IServiceCollection"/> to add the application enricher to.</param>
/// <param name="configure">The <see cref="ApplicationLogEnricherOptions"/> configuration delegate.</param>
/// <returns>The value of <paramref name="services"/>.</returns>
/// <exception cref="ArgumentNullException">Any of the arguments is <see langword="null"/>.</exception>
public static IServiceCollection AddServiceLogEnricher(this IServiceCollection services, Action<ApplicationLogEnricherOptions> configure)
[Experimental(diagnosticId: DiagnosticIds.Experiments.Telemetry, UrlFormat = DiagnosticIds.UrlFormat)]
public static IServiceCollection AddApplicationLogEnricher(this IServiceCollection services, Action<ApplicationLogEnricherOptions> configure)
{
_ = Throw.IfNull(services);
_ = Throw.IfNull(configure);
Expand All @@ -45,13 +90,14 @@ public static IServiceCollection AddServiceLogEnricher(this IServiceCollection s
}

/// <summary>
/// Adds an instance of the service enricher to the <see cref="IServiceCollection"/>.
/// Adds an instance of the application enricher to the <see cref="IServiceCollection"/>.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> to add the service enricher to.</param>
/// <param name="services">The <see cref="IServiceCollection"/> to add the application enricher to.</param>
/// <param name="section">The <see cref="IConfigurationSection"/> to use for configuring <see cref="ApplicationLogEnricherOptions"/> in the service enricher.</param>
/// <returns>The value of <paramref name="services"/>.</returns>
/// <exception cref="ArgumentNullException">Any of the arguments is <see langword="null"/>.</exception>
public static IServiceCollection AddServiceLogEnricher(this IServiceCollection services, IConfigurationSection section)
[Experimental(diagnosticId: DiagnosticIds.Experiments.Telemetry, UrlFormat = DiagnosticIds.UrlFormat)]
public static IServiceCollection AddApplicationLogEnricher(this IServiceCollection services, IConfigurationSection section)
{
_ = Throw.IfNull(services);
_ = Throw.IfNull(section);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
namespace Microsoft.Extensions.Diagnostics.Enrichment;

/// <summary>
/// Options for the service log enricher.
/// Options for the application log enricher.
/// </summary>
public class ApplicationLogEnricherOptions
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<RootNamespace>Microsoft.Extensions.Diagnostics</RootNamespace>
<Description>Provides canonical implementations of telemetry abstractions.</Description>
<Workstream>Telemetry</Workstream>
<NoWarn Condition="'$(TargetFramework)' == 'net462'">$(NoWarn);CS0436</NoWarn>
</PropertyGroup>

<PropertyGroup>
Expand All @@ -17,6 +18,7 @@
<InjectSharedNumericExtensions>true</InjectSharedNumericExtensions>
<InjectSharedPools>true</InjectSharedPools>
<InjectSharedRentedSpan>true</InjectSharedRentedSpan>
<InjectObsoleteAttributeOnLegacy>true</InjectObsoleteAttributeOnLegacy>
<EnableConfigurationBindingGenerator>true</EnableConfigurationBindingGenerator>
<UseLoggingGenerator>true</UseLoggingGenerator>
</PropertyGroup>
Expand Down
10 changes: 5 additions & 5 deletions src/Libraries/Microsoft.Extensions.Telemetry/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,16 +126,16 @@ revisited in future. Namely, this library uses `Microsoft.Extensions.Logging.Abs
- `Microsoft.Extensions.Logging.Abstractions.BufferedLogRecord.ManagedThreadId`
- `Microsoft.Extensions.Logging.Abstractions.BufferedLogRecord.MessageTemplate`

### Service Log Enrichment
### Application Log Enrichment

Enriches logs with application-specific information based on `ApplicationMetadata` information. The bellow calls will add the service log enricher to the service collection.
Enriches logs with application-specific information based on `ApplicationMetadata` information. The bellow calls will add the application log enricher to the service collection.

```csharp
// Add service log enricher with default settings
builder.Services.AddServiceLogEnricher();
builder.Services.AddApplicationLogEnricher();

// Or configure with options
builder.Services.AddServiceLogEnricher(options =>
builder.Services.AddApplicationLogEnricher(options =>
{
options.ApplicationName = true;
options.BuildVersion = true;
Expand Down Expand Up @@ -197,7 +197,7 @@ builder.Logging.EnableEnrichment(options =>
options.UseFileInfoForStackTraces = true;
});

builder.Services.AddServiceLogEnricher(); // <- This call is required in order for the enricher to be added into the service collection.
builder.Services.AddApplicationLogEnricher(); // <- This call is required in order for the enricher to be added into the service collection.
// Enable log redaction
builder.Logging.EnableRedaction(options =>
Expand Down
6 changes: 5 additions & 1 deletion src/Shared/DiagnosticIds/DiagnosticIds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,11 @@ internal static class AuditReports
internal static class Obsoletions
{
internal const string NonObservableResourceMonitoringApiDiagId = "EXTOBS0001";
internal const string NonObservableResourceMonitoringApiMessage = "This API is obsolete and will be removed in a future version. Consider using Resource Monitoring observable instruments.";
internal const string ObsoleteTelemetryApiDiagId = "EXTOBS0002";
internal const string NonObservableResourceMonitoringApiMessage =
"This API is obsolete and will be removed in a future version. Consider using Resource Monitoring observable instruments.";
internal const string ObsoleteTelemetryApiMessage =
"This API is obsolete and will be removed in a future version. Instead of the AddServiceLogEnricher() methods, consider using the respective AddApplicationLogEnricher() methods.";
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,24 @@ public class ApplicationEnricherExtensionsTests
public void ServiceLogEnricher_GivenAnyNullArgument_Throws()
{
Assert.Throws<ArgumentNullException>(() =>
((IServiceCollection)null!).AddServiceLogEnricher());
((IServiceCollection)null!).AddApplicationLogEnricher());

Assert.Throws<ArgumentNullException>(() =>
((IServiceCollection)null!).AddServiceLogEnricher(_ => { }));
((IServiceCollection)null!).AddApplicationLogEnricher(_ => { }));

Assert.Throws<ArgumentNullException>(() =>
((IServiceCollection)null!).AddServiceLogEnricher(Mock.Of<IConfigurationSection>()));
((IServiceCollection)null!).AddApplicationLogEnricher(Mock.Of<IConfigurationSection>()));

Assert.Throws<ArgumentNullException>(() =>
new ServiceCollection().AddServiceLogEnricher((IConfigurationSection)null!));
new ServiceCollection().AddApplicationLogEnricher((IConfigurationSection)null!));
}

[Fact]
public void ServiceLogEnricher_GivenNoArguments_RegistersInDI()
{
// Arrange & Act
using var host = FakeHost.CreateBuilder()
.ConfigureServices(services => services.AddServiceLogEnricher())
.ConfigureServices(services => services.AddApplicationLogEnricher())
.Build();

// Assert
Expand All @@ -48,7 +48,7 @@ public void HostLogEnricher_GivenOptions_RegistersInDI()
// Arrange & Act
using var host = FakeHost.CreateBuilder()
.ConfigureLogging(builder => builder
.Services.AddServiceLogEnricher(e =>
.Services.AddApplicationLogEnricher(e =>
{
e.ApplicationName = false;
e.EnvironmentName = false;
Expand All @@ -68,17 +68,17 @@ public void HostLogEnricher_GivenOptions_RegistersInDI()
}

[Fact]
public void ServiceLogEnricher_GivenConfiguration_RegistersInDI()
public void ApplicationLogEnricher_GivenConfiguration_RegistersInDI()
{
// Arrange & Act
using var host = FakeHost.CreateBuilder()
.ConfigureAppConfiguration(
("Serviceenrichersection:ApplicationName", "true"),
("Serviceenrichersection:EnvironmentName", "false"),
("Serviceenrichersection:BuildVersion", "true"),
("Serviceenrichersection:DeploymentRing", "true"))
("Applicationenrichersection:ApplicationName", "true"),
("Applicationenrichersection:EnvironmentName", "false"),
("Applicationenrichersection:BuildVersion", "true"),
("Applicationenrichersection:DeploymentRing", "true"))
.ConfigureServices((context, services) => services
.AddServiceLogEnricher(context.Configuration.GetSection("Serviceenrichersection")))
.AddApplicationLogEnricher(context.Configuration.GetSection("Applicationenrichersection")))
.Build();

// Assert
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Microsoft.Extensions.Diagnostics.Enrichment.Test;
public class ApplicationEnricherOptionsTests
{
[Fact]
public void ServiceLogEnricherOptions_EnsureDefaultValues()
public void ApplicationLogEnricherOptions_EnsureDefaultValues()
{
var options = new ApplicationLogEnricherOptions();
options.EnvironmentName.Should().BeTrue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,20 @@ public void HostLogEnricher_GivenInvalidArguments_Throws()
var optionsNull = new Mock<IOptions<ApplicationLogEnricherOptions>>();
optionsNull.Setup(o => o.Value).Returns<IOptions<ApplicationLogEnricherOptions>>(null!);

var serviceOptionsNull = new Mock<IOptions<ApplicationMetadata>>();
serviceOptionsNull.Setup(o => o.Value).Returns<IOptions<ApplicationMetadata>>(null!);
var applicationOptionsNull = new Mock<IOptions<ApplicationMetadata>>();
applicationOptionsNull.Setup(o => o.Value).Returns<IOptions<ApplicationMetadata>>(null!);

// Act & Assert
Assert.Throws<ArgumentException>(() => new ApplicationLogEnricher(optionsNull.Object, null!));
Assert.Throws<ArgumentException>(() => new ApplicationLogEnricher(options, serviceOptionsNull.Object));
Assert.Throws<ArgumentException>(() => new ApplicationLogEnricher(options, applicationOptionsNull.Object));
}

[Theory]
[InlineData(true, true, true, true, null, null)]
[InlineData(true, true, true, true, BuildVersion, DeploymentRing)]
[InlineData(false, false, false, false, null, null)]
[InlineData(false, false, false, false, BuildVersion, DeploymentRing)]
public void ServiceLogEnricher_Options(bool appName, bool envName, bool buildVer, bool depRing, string? buildVersion, string? deploymentRing)
public void ApplicationLogEnricher_Options(bool appName, bool envName, bool buildVer, bool depRing, string? buildVersion, string? deploymentRing)
{
// Arrange
var options = new ApplicationLogEnricherOptions
Expand All @@ -63,15 +63,15 @@ public void ServiceLogEnricher_Options(bool appName, bool envName, bool buildVer
DeploymentRing = depRing,
};

var serviceOptions = new ApplicationMetadata
var metadata = new ApplicationMetadata
{
BuildVersion = buildVersion,
DeploymentRing = deploymentRing,
ApplicationName = _hostMock.Object.ApplicationName,
EnvironmentName = _hostMock.Object.EnvironmentName
};

var enricher = new ApplicationLogEnricher(options.ToOptions(), serviceOptions.ToOptions());
var enricher = new ApplicationLogEnricher(options.ToOptions(), metadata.ToOptions());
var enrichedProperties = new TestLogEnrichmentTagCollector();

// Act
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Hosting.Testing;
using Microsoft.Extensions.Options;
using Moq;
using Xunit;

namespace Microsoft.Extensions.Diagnostics.Enrichment.Test;

[Obsolete("Testing obsolete API")]
public class ServiceEnricherExtensionsTests
{
[Fact]
public void ServiceLogEnricher_GivenAnyNullArgument_Throws()
{
Assert.Throws<ArgumentNullException>(() =>
((IServiceCollection)null!).AddServiceLogEnricher());

Assert.Throws<ArgumentNullException>(() =>
((IServiceCollection)null!).AddServiceLogEnricher(_ => { }));

Assert.Throws<ArgumentNullException>(() =>
((IServiceCollection)null!).AddServiceLogEnricher(Mock.Of<IConfigurationSection>()));

Assert.Throws<ArgumentNullException>(() =>
new ServiceCollection().AddServiceLogEnricher((IConfigurationSection)null!));
}

[Fact]
public void ServiceLogEnricher_GivenNoArguments_RegistersInDI()
{
// Arrange & Act
using var host = FakeHost.CreateBuilder()
.ConfigureServices(services => services.AddServiceLogEnricher())
.Build();

// Assert
Assert.NotNull(host.Services.GetRequiredService<IStaticLogEnricher>());
}

[Fact]
public void ServiceLogEnricher_GivenOptions_RegistersInDI()
{
// Arrange & Act
using var host = FakeHost.CreateBuilder()
.ConfigureLogging(builder => builder
.Services.AddServiceLogEnricher(e =>
{
e.ApplicationName = false;
e.EnvironmentName = false;
e.BuildVersion = false;
e.DeploymentRing = false;
}))
.Build();

// Assert
Assert.NotNull(host.Services.GetRequiredService<IStaticLogEnricher>());
var options = host.Services.GetRequiredService<IOptions<ApplicationLogEnricherOptions>>().Value;
Assert.NotNull(options);
Assert.False(options.ApplicationName);
Assert.False(options.EnvironmentName);
Assert.False(options.BuildVersion);
Assert.False(options.DeploymentRing);
}

[Fact]
public void ServiceLogEnricher_GivenConfiguration_RegistersInDI()
{
// Arrange & Act
using var host = FakeHost.CreateBuilder()
.ConfigureAppConfiguration(
("Serviceenrichersection:ApplicationName", "true"),
("Serviceenrichersection:EnvironmentName", "false"),
("Serviceenrichersection:BuildVersion", "true"),
("Serviceenrichersection:DeploymentRing", "true"))
.ConfigureServices((context, services) => services
.AddServiceLogEnricher(context.Configuration.GetSection("Serviceenrichersection")))
.Build();

// Assert
var enricher = host.Services.GetRequiredService<IStaticLogEnricher>();
Assert.NotNull(enricher);
Assert.IsType<ApplicationLogEnricher>(enricher);
var options = host.Services.GetRequiredService<IOptions<ApplicationLogEnricherOptions>>().Value;
Assert.NotNull(options);
Assert.True(options.ApplicationName);
Assert.False(options.EnvironmentName);
Assert.True(options.BuildVersion);
Assert.True(options.DeploymentRing);
}
}
Loading
Loading