ASP.NET Core日志系统完全指南:基于practical-aspnetcore的6个场景

ASP.NET Core日志系统完全指南:基于practical-aspnetcore的6个场景

【免费下载链接】practical-aspnetcore 该项目提供了关于ASP.NET Core实际应用开发的一系列教程和示例,涵盖了从基础知识到高级主题,是一个实用的学习资源库。适合于想要掌握ASP.NET Core技术栈的开发者进行学习和参考。 【免费下载链接】practical-aspnetcore 项目地址: https://gitcode.com/gh_mirrors/pr/practical-aspnetcore

你是否还在为ASP.NET Core应用中的日志配置感到困惑?本文将通过practical-aspnetcore项目中的6个实战场景,带你从入门到精通日志系统的配置与优化。读完本文,你将掌握基础日志记录、日志过滤、结构化日志输出、高性能日志API、静态日志缓存以及分布式日志收集等核心技能。

场景一:基础日志级别配置

基础日志记录是ASP.NET Core应用开发的必备技能。在practical-aspnetcore项目logging-1示例中,展示了如何配置不同日志级别并输出日志信息。

ASP.NET Core定义了6个日志级别,按严重程度从低到高依次为:

  • Trace (0):最详细的调试信息
  • Debug (1):开发环境调试信息
  • Information (2):运行时正常信息
  • Warning (3):不影响运行的异常情况
  • Error (4):功能异常但不终止应用
  • Critical (5):严重错误可能导致应用终止

以下代码演示了如何设置全局最小日志级别并输出不同级别的日志:

var builder = WebApplication.CreateBuilder();
builder.Logging.SetMinimumLevel(LogLevel.Warning);
builder.Logging.AddConsole();

var app = builder.Build();

app.Run(context =>
{
    var log = app.Logger;
    log.LogTrace("Trace message");    // 不会显示,级别低于Warning
    log.LogDebug("Debug message");    // 不会显示,级别低于Warning
    log.LogInformation("Information message"); // 不会显示,级别低于Warning
    log.LogWarning("Warning message");  // 显示
    log.LogError("Error message");    // 显示
    log.LogCritical("Critical message"); // 显示
    return context.Response.WriteAsync("Hello world.");
});
app.Run();

通过调整SetMinimumLevel参数,可以控制应用输出的日志详细程度。在开发环境通常使用较低级别(如Debug),生产环境则使用较高级别(如Warning)以减少性能开销。

场景二:日志过滤规则设置

当日志量过大时,我们需要对日志进行过滤,只保留关键信息。logging-2示例展示了如何基于日志类别设置不同的过滤规则。

日志过滤可以通过代码或配置文件实现。以下代码演示了如何对不同命名空间的日志设置不同级别:

var builder = WebApplication.CreateBuilder();
// 对Microsoft命名空间的日志只显示Warning及以上级别
builder.Logging.AddFilter("Microsoft", LogLevel.Warning);
// 对AppLogger命名空间的日志显示所有级别
builder.Logging.AddFilter("AppLogger", LogLevel.Trace);
builder.Logging.AddConsole();

var app = builder.Build();
// ...

除了代码方式,还可以通过配置文件进行过滤设置。在appSettings.json中添加日志配置:

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning",
      "Microsoft": "Error",
      "AppLogger": "Information"
    }
  }
}

日志过滤功能可以帮助我们:

  • 减少第三方库的日志干扰
  • 针对不同模块设置不同详细程度
  • 在生产环境隐藏敏感信息
  • 提高日志系统性能

场景三:JSON结构化日志输出

在日志分析和处理时,结构化日志比纯文本日志更具优势。logging-3示例展示了如何配置JSON格式的控制台日志输出。

通过添加JSON控制台日志提供器,可以将日志输出为结构化的JSON格式,便于日志聚合工具(如ELK、Splunk)进行解析和分析:

using System.Text.Json;

var builder = WebApplication.CreateBuilder();
builder.Logging.AddFilter("Microsoft", LogLevel.Warning);
builder.Logging.AddFilter("AppLogger", LogLevel.Trace);
builder.Logging.AddJsonConsole(options =>
{
    options.JsonWriterOptions = new JsonWriterOptions { Indented = true }; 
});

var app = builder.Build();
// ...

配置后,控制台将输出如下格式的JSON日志:

{
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "Program",
  "Message": "This is a information message",
  "State": {
    "Message": "This is a information message"
  }
}

JSON结构化日志的优势在于:

  • 包含丰富的元数据(日志级别、类别、事件ID等)
  • 便于机器解析和自动化处理
  • 支持自定义字段扩展
  • 可配置的输出格式

场景四:高性能日志API生成

对于高性能要求的应用,使用LoggerMessageAttribute可以显著提升日志性能。logging-4示例展示了如何通过源代码生成创建高性能日志API。

传统的LogInformation等方法会带来一定的性能开销,而使用LoggerMessageAttribute可以在编译时生成高效的日志方法,避免运行时字符串格式化开销:

public static partial class EvenOddLogs
{
    [LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = "input number is even!: {number}")]
    public static partial void LogInformationWhenInputNumberIsEven(this ILogger logger, long number);

    [LoggerMessage(EventId = 2, Level = LogLevel.Information, Message = "input number is odd!: {number}")]
    public static partial void LogInformationWhenInputNumberIsOdd(this ILogger logger, long number);
}

使用生成的日志方法:

app.MapGet("/log-it", ([FromQuery] int number) =>
{
    var log = app.Logger;
    
    if (number % 2 == 0)
        log.LogInformationWhenInputNumberIsEven(number);
    else
        log.LogInformationWhenInputNumberIsOdd(number);
        
    return Results.Content("Check terminal for logs.");
});

高性能日志API的优势:

  • 编译时检查日志参数类型
  • 减少内存分配和GC压力
  • 支持结构化日志属性
  • 提高应用吞吐量,尤其在高频日志场景

场景五:静态日志缓存实现

在大型应用中,频繁创建日志器(ILogger)会带来性能开销。logging-5示例展示了如何实现静态日志缓存,优化日志器的创建和使用。

通过创建静态日志工厂类,可以缓存日志器实例,避免重复创建:

public static class Log
{
    static ILoggerFactory _loggerFactory;
    static readonly ConcurrentDictionary<string, ILogger> _loggers = new();
    
    public static void Configure(ILoggerFactory loggerFactory)
    {
        _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
    }
    
    public static ILogger CreateLogger<T>() => 
        _loggers.GetOrAdd(typeof(T).FullName, _ => _loggerFactory.CreateLogger<T>());
    
    public static ILogger CreateLogger(string categoryName) => 
        _loggers.GetOrAdd(categoryName, _ => _loggerFactory.CreateLogger(categoryName));
}

在应用启动时配置日志工厂:

var app = builder.Build();
Log.Configure(app.Services.GetRequiredService<ILoggerFactory>());  

使用静态日志器:

app.Run(context =>
{
    var log = Log.CreateLogger("main");
    log.LogWarning("Warning message");
    // ...
    return context.Response.WriteAsync("Hello world.");
});

静态日志缓存的优势:

  • 减少内存分配和对象创建开销
  • 简化日志器的获取方式
  • 统一日志配置和管理
  • 提高应用性能,尤其在高频日志场景

场景六:Grafana Loki分布式日志收集

对于分布式应用,集中式日志收集至关重要。logging-Loki示例展示了如何将ASP.NET Core日志发送到Grafana Loki进行集中管理和分析。

Loki是Grafana Labs开发的水平可扩展、高可用性的日志聚合系统,专为容器和微服务环境设计。以下代码演示了如何配置Loki日志提供器:

using LokiLoggingProvider.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Logging.AddLoki(configure =>
{
    configure.Client = PushClient.Grpc;
    configure.StaticLabels.JobName = "LokiWebApplication";
});

var app = builder.Build();

app.MapGet("/test", (ILoggerFactory loggerFactory) =>
{
    var logger = loggerFactory.CreateLogger("Start");
    logger.LogTrace("Trace message");
    logger.LogDebug("Debug message");
    logger.LogInformation("Information message");
    logger.LogWarning("Warning message");
    logger.LogError("Error message");
    logger.LogCritical("Critical message");
    return "OK";
});

app.Run();

为了简化Loki的部署和配置,示例中提供了docker-compose.yml文件,可以一键启动Loki和Grafana服务:

version: "3"

services:
  loki:
    image: grafana/loki:latest
    ports:
      - "3100:3100"
    command: -config.file=/etc/loki/local-config.yaml

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    volumes:
      - ./grafana-data:/var/lib/grafana
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=secret

使用Loki进行分布式日志收集的优势:

  • 集中管理多个服务实例的日志
  • 支持日志标签和高效查询
  • 与Grafana无缝集成,提供可视化分析
  • 适合云原生和微服务架构

总结与最佳实践

通过practical-aspnetcore项目的6个日志场景实践,我们系统学习了ASP.NET Core日志系统的核心功能和高级用法。以下是一些最佳实践建议:

  1. 环境差异化配置:开发环境使用详细日志级别,生产环境使用高级别日志
  2. 合理使用日志级别:根据信息重要性选择适当的日志级别
  3. 结构化日志优先:尽量使用结构化日志,便于后续分析和处理
  4. 性能优化:对高频日志场景使用LoggerMessageAttribute和静态日志缓存
  5. 集中式收集:在分布式系统中使用Loki等工具进行日志集中管理
  6. 敏感信息保护:避免在日志中记录密码、令牌等敏感信息

更多日志相关示例和详细代码,请参考practical-aspnetcore项目的logging目录。掌握日志系统不仅能帮助我们更好地调试应用,还能为系统监控、性能优化和问题排查提供关键支持。

希望本文对你理解和使用ASP.NET Core日志系统有所帮助。如果有任何问题或建议,欢迎在项目仓库中提交issue或PR。

【免费下载链接】practical-aspnetcore 该项目提供了关于ASP.NET Core实际应用开发的一系列教程和示例,涵盖了从基础知识到高级主题,是一个实用的学习资源库。适合于想要掌握ASP.NET Core技术栈的开发者进行学习和参考。 【免费下载链接】practical-aspnetcore 项目地址: https://gitcode.com/gh_mirrors/pr/practical-aspnetcore

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值