设置专用日志记录管道

了解如何为特定日志设置专用日志记录管道

本指南演示了如何为需要发送到与常规应用程序日志不同的目标地的特定日志创建专用日志记录管道。

为什么要使用专用管道?

在许多情况下,您可能需要使用专用日志记录管道

  1. 安全日志:将与安全相关的日志发送到专门的安全信息和事件管理(SIEM)系统。
  2. 审计日志:将审计日志发送到合规的存储系统。
  3. 访问日志:将用户访问日志与应用程序日志分开。
  4. 调试:在故障排除期间将详细的调试日志发送到单独的目的地。

除其他外,专用管道允许您

  • 对特定日志应用不同的处理器和导出器。
  • 独立控制日志保留策略。
  • 单独管理访问权限。
  • 通过仅将相关日志发送到每个系统来优化性能。

创建专用日志记录管道

要创建专用日志记录管道,您需要

  1. 创建专用日志记录器接口。
  2. 为此接口实现日志记录器提供程序。
  3. 为此提供程序配置 OpenTelemetry。
  4. 注册专用日志记录服务。

让我们通过一个完整的示例进行讲解

第一步:定义专用日志记录器接口

首先,为您的专用日志记录器创建一个接口

namespace DedicatedLogging
{
    // Marker interface to distinguish dedicated loggers
    public interface IDedicatedLogger
    {
    }

    // Generic dedicated logger (follows the same pattern as ILogger<T>)
    public interface IDedicatedLogger<T> : IDedicatedLogger, ILogger<T>
    {
    }
}

第二步:实现日志记录器提供程序

接下来,创建您的专用日志记录器的实现

namespace DedicatedLogging
{
    internal class DedicatedLogger<T> : IDedicatedLogger<T>
    {
        private readonly ILogger<T> _logger;

        public DedicatedLogger(ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger<T>();
        }

        // ILogger implementation methods
        public IDisposable? BeginScope<TState>(TState state) where TState : notnull => _logger.BeginScope(state);
        public bool IsEnabled(LogLevel logLevel) => _logger.IsEnabled(logLevel);
        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
            => _logger.Log(logLevel, eventId, state, exception, formatter);
    }
}

第三步:创建用于配置的扩展方法

创建扩展方法以注册您的专用日志记录服务

namespace DedicatedLogging
{
    public static class DedicatedLoggingExtensions
    {
        public static IServiceCollection AddDedicatedLogging(
            this IServiceCollection services,
            IConfiguration? configuration = null,
            Action<OpenTelemetryLoggerOptions>? configure = null)
        {
            // Create a dedicated LoggerFactory for the dedicated logging pipeline
            services.AddSingleton<ILoggerFactory>(sp =>
            {
                var factory = LoggerFactory.Create(builder =>
                {
                    // Add OpenTelemetry as the logging provider
                    builder.AddOpenTelemetry(options =>
                    {
                        // Apply configuration if provided
                        if (configuration != null)
                        {
                            options.SetResourceBuilder(
                                ResourceBuilder.CreateDefault()
                                    .AddService(configuration["ServiceName"] ?? "dedicated-logging-service"));
                        }

                        // Apply custom configuration if provided
                        configure?.Invoke(options);
                    });
                });

                return factory;
            });

            // Register the dedicated logger
            services.AddTransient(typeof(IDedicatedLogger<>), typeof(DedicatedLogger<>));

            return services;
        }
    }
}

第四步:在应用程序中使用专用日志记录器

现在,您可以在 ASP.NET Core 应用程序中使用您的专用日志记录器

using DedicatedLogging;
using OpenTelemetry.Logs;

var builder = WebApplication.CreateBuilder(args);

// Set up primary pipeline for common app logs
builder.Services.AddOpenTelemetry()
    .WithLogging(logging =>
    {
        logging.AddConsoleExporter();
        // Configure for your primary logging destination
    });

// Set up secondary pipeline for dedicated logs
builder.Services.AddDedicatedLogging(
    builder.Configuration.GetSection("DedicatedLogging"),
    logging =>
    {
        logging.AddConsoleExporter();
        // Configure differently for your dedicated logging destination
        // For example:
        // logging.AddOtlpExporter(o => o.Endpoint = new Uri("https://security-logs.example.com"));
    });

var app = builder.Build();

app.MapGet("/", (HttpContext context, ILogger<Program> logger, IDedicatedLogger<Program> dedicatedLogger) =>
{
    // Standard log written to primary pipeline
    logger.LogInformation("Standard application log");

    // Dedicated log written to dedicated pipeline
    dedicatedLogger.LogInformation("Request initiated from {IpAddress}",
        context.Connection.RemoteIpAddress?.ToString() ?? "unknown");

    return "Hello from OpenTelemetry Logs!";
});

app.Run();

第五步:使用源生成的日志记录方法

为了获得更好的性能,您可以使用 LoggerMessage 属性来生成日志记录方法

internal static partial class LoggerExtensions
{
    [LoggerMessage(LogLevel.Information, "Food `{name}` price changed to `{price}`.")]
    public static partial void FoodPriceChanged(this ILogger logger, string name, double price);

    [LoggerMessage(LogLevel.Information, "Request initiated from `{ipAddress}`.")]
    public static partial void RequestInitiated(this IDedicatedLogger logger, string ipAddress);
}

配置

您可以通过 appsettings.json 配置专用日志记录管道

{
  "DedicatedLogging": {
    "ServiceName": "security-logs",
    "ExportEndpoint": "https://security-logs.example.com",
    "BatchSize": 512
  }
}

然后在您的启动代码中绑定此配置

builder.Services.AddDedicatedLogging(
    builder.Configuration.GetSection("DedicatedLogging"),
    logging =>
    {
        var config = builder.Configuration.GetSection("DedicatedLogging");
        var endpoint = config["ExportEndpoint"];

        if (!string.IsNullOrEmpty(endpoint))
        {
            logging.AddOtlpExporter(o =>
            {
                o.Endpoint = new Uri(endpoint);
            });
        }
    });

了解更多