Skip to content

Commit e4b08ac

Browse files
authored
[docs-logging] Add a logging doc for showing how to set up a dedicated pipeline for specific logs (#5356)
1 parent 855e9c4 commit e4b08ac

8 files changed

+172
-0
lines changed

OpenTelemetry.sln

+7
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "resources", "resources", "{
340340
EndProject
341341
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "extending-the-sdk", "docs\resources\extending-the-sdk\extending-the-sdk.csproj", "{7BE494FC-4B0D-4340-A62A-9C9F3E7389FE}"
342342
EndProject
343+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dedicated-pipeline", "docs\logs\dedicated-pipeline\dedicated-pipeline.csproj", "{19545B37-8518-4BDD-AD49-00C031FB3C2A}"
344+
EndProject
343345
Global
344346
GlobalSection(SolutionConfigurationPlatforms) = preSolution
345347
Debug|Any CPU = Debug|Any CPU
@@ -626,6 +628,10 @@ Global
626628
{7BE494FC-4B0D-4340-A62A-9C9F3E7389FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
627629
{7BE494FC-4B0D-4340-A62A-9C9F3E7389FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
628630
{7BE494FC-4B0D-4340-A62A-9C9F3E7389FE}.Release|Any CPU.Build.0 = Release|Any CPU
631+
{19545B37-8518-4BDD-AD49-00C031FB3C2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
632+
{19545B37-8518-4BDD-AD49-00C031FB3C2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
633+
{19545B37-8518-4BDD-AD49-00C031FB3C2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
634+
{19545B37-8518-4BDD-AD49-00C031FB3C2A}.Release|Any CPU.Build.0 = Release|Any CPU
629635
EndGlobalSection
630636
GlobalSection(SolutionProperties) = preSolution
631637
HideSolutionNode = FALSE
@@ -680,6 +686,7 @@ Global
680686
{17A22B0E-6EC3-4A39-B955-0A486AD06699} = {52AF6D7D-9E66-4234-9A2C-5D16C6F22B40}
681687
{A115CE4C-71A8-4B95-96A5-C1DF46FD94C2} = {7C87CAF9-79D7-4C26-9FFB-F3F1FB6911F1}
682688
{7BE494FC-4B0D-4340-A62A-9C9F3E7389FE} = {A115CE4C-71A8-4B95-96A5-C1DF46FD94C2}
689+
{19545B37-8518-4BDD-AD49-00C031FB3C2A} = {3862190B-E2C5-418E-AFDC-DB281FB5C705}
683690
EndGlobalSection
684691
GlobalSection(ExtensibilityGlobals) = postSolution
685692
SolutionGuid = {55639B5C-0770-4A22-AB56-859604650521}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
using Microsoft.Extensions.DependencyInjection.Extensions;
5+
using OpenTelemetry.Logs;
6+
7+
namespace DedicatedLogging;
8+
9+
public static class DedicatedLoggingServiceCollectionExtensions
10+
{
11+
public static IServiceCollection AddDedicatedLogging(
12+
this IServiceCollection services,
13+
IConfiguration configuration,
14+
Action<OpenTelemetryLoggerOptions> configureOpenTelemetry)
15+
{
16+
ArgumentNullException.ThrowIfNull(configureOpenTelemetry);
17+
18+
services.TryAddSingleton(sp =>
19+
{
20+
var loggerFactory = LoggerFactory.Create(builder =>
21+
{
22+
builder.AddConfiguration(configuration);
23+
24+
builder.AddOpenTelemetry(configureOpenTelemetry);
25+
});
26+
27+
return new DedicatedLoggerFactory(loggerFactory);
28+
});
29+
30+
services.TryAdd(ServiceDescriptor.Singleton(typeof(IDedicatedLogger<>), typeof(DedicatedLogger<>)));
31+
32+
return services;
33+
}
34+
35+
private sealed class DedicatedLogger<T> : IDedicatedLogger<T>
36+
{
37+
private readonly ILogger innerLogger;
38+
39+
public DedicatedLogger(DedicatedLoggerFactory loggerFactory)
40+
{
41+
this.innerLogger = loggerFactory.CreateLogger(typeof(T).FullName!);
42+
}
43+
44+
public IDisposable? BeginScope<TState>(TState state)
45+
where TState : notnull
46+
=> this.innerLogger.BeginScope(state);
47+
48+
public bool IsEnabled(LogLevel logLevel)
49+
=> this.innerLogger.IsEnabled(logLevel);
50+
51+
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
52+
=> this.innerLogger.Log(logLevel, eventId, state, exception, formatter);
53+
}
54+
55+
private sealed class DedicatedLoggerFactory : ILoggerFactory
56+
{
57+
private readonly ILoggerFactory innerLoggerFactory;
58+
59+
public DedicatedLoggerFactory(ILoggerFactory loggerFactory)
60+
{
61+
this.innerLoggerFactory = loggerFactory;
62+
}
63+
64+
public void AddProvider(ILoggerProvider provider)
65+
=> this.innerLoggerFactory.AddProvider(provider);
66+
67+
public ILogger CreateLogger(string categoryName)
68+
=> this.innerLoggerFactory.CreateLogger(categoryName);
69+
70+
public void Dispose()
71+
=> this.innerLoggerFactory.Dispose();
72+
}
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
namespace DedicatedLogging;
5+
6+
public interface IDedicatedLogger : ILogger
7+
{
8+
}
9+
10+
public interface IDedicatedLogger<out TCategoryName> : IDedicatedLogger
11+
{
12+
}
+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
using DedicatedLogging;
5+
using OpenTelemetry.Logs;
6+
7+
var builder = WebApplication.CreateBuilder(args);
8+
9+
builder.Logging.ClearProviders();
10+
11+
builder.Logging.AddOpenTelemetry(options =>
12+
{
13+
// Set up primary pipeline for common app logs
14+
options.AddConsoleExporter();
15+
});
16+
17+
builder.Services.AddDedicatedLogging(
18+
builder.Configuration.GetSection("DedicatedLogging"), // Bind configuration for dedicated logging pipeline
19+
options =>
20+
{
21+
// Set up secondary pipeline for dedicated logs
22+
options.AddConsoleExporter();
23+
});
24+
25+
var app = builder.Build();
26+
27+
app.MapGet("/", (HttpContext context, ILogger<Program> logger, IDedicatedLogger<Program> dedicatedLogger) =>
28+
{
29+
// Standard log written
30+
logger.FoodPriceChanged("artichoke", 9.99);
31+
32+
// Dedicated log written
33+
dedicatedLogger.RequestInitiated(context.Connection.RemoteIpAddress?.ToString() ?? "unknown");
34+
35+
return "Hello from OpenTelemetry Logs!";
36+
});
37+
38+
app.Run();
39+
40+
internal static partial class LoggerExtensions
41+
{
42+
[LoggerMessage(LogLevel.Information, "Food `{name}` price changed to `{price}`.")]
43+
public static partial void FoodPriceChanged(this ILogger logger, string name, double price);
44+
45+
[LoggerMessage(LogLevel.Information, "Request initiated from `{ipAddress}`.")]
46+
public static partial void RequestInitiated(this IDedicatedLogger logger, string ipAddress);
47+
}
+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Dedicated pipeline
2+
3+
This example shows how to create a dedicated logging pipeline for specific logs
4+
which will be sent to a different location than normal application logs.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"DetailedErrors": true,
3+
"Logging": {
4+
"LogLevel": {
5+
"Default": "Information",
6+
"Microsoft.AspNetCore": "Warning"
7+
}
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning"
6+
}
7+
},
8+
"DedicatedLogging": {
9+
"LogLevel": {
10+
"Default": "Information"
11+
}
12+
},
13+
"AllowedHosts": "*"
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
<ItemGroup>
3+
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Console\OpenTelemetry.Exporter.Console.csproj" />
4+
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Extensions.Hosting\OpenTelemetry.Extensions.Hosting.csproj" />
5+
</ItemGroup>
6+
</Project>

0 commit comments

Comments
 (0)