首页 > 编程语言 >ASP .NET Core 中的请求-响应日志记录

ASP .NET Core 中的请求-响应日志记录

时间:2024-12-13 10:01:38浏览次数:6  
标签:Core ASP string app 我们 loungeAccess new NET 日志

参考源码:https://download.csdn.net/download/hefeng_aspnet/90084914 

        记录 ASP .NET Core http 请求和响应是几乎每个 .NET 开发人员迟早都会面临的常见任务。长期以来,开发团队选择的最流行的方法似乎是编写自定义中间件。但是,既然 .NET 6 我们有一个Microsoft.AspNetCore.HttpLogging内置库。所以,亲爱的 .NET 海狸们,让我们看看微软给我们的日志吧!并且找到更好的。

我们的人工智能生成的吉祥物带有原木 

设置日志记录

我们将从 .NET 提供的最简单的设置开始,运行以下控制台命令 

dotnet new web 

        检查 http 请求的每个部分的日志记录非常重要,例如请求主体、查询字符串、错误和路径参数。因此默认Hello World端点不行。让我们创建一个具有 blackjack 查询和路由参数的方: 

app.MapPost("/parties/{partyId}/guests", (string partyId, [FromQuery] bool? loungeAccess, Guest visitor) => {
    if (loungeAccess == true && !visitor.Vip) 
        throw new NotEnoughLevelException();

    return new Ticket(
        PartyId: partyId,
        Receiver: visitor.Name,
        LoungeAccess: loungeAccess ?? false,
        Code: Guid.NewGuid().ToString()
    );
});

app.Run();

public record Guest(string Name, bool Vip);
public record Ticket(string PartyId, string Receiver, bool LoungeAccess, string Code);
public class NotEnoughLevelException : Exception;

        默认情况下,NotEnoughLevelExceptionASP .NET Core 将粗略地中断请求并返回InternalServerError。让我们改为返回一个错误对象。实现它的最简单方法可能是使用Nist.Errorsnuget 包。要安装它,我们将使用以下命令:

dotnet add package Nist.Errors

并将我们的异常映射到相应的错误:

app.UseErrorBody<Error>(ex => ex switch {
    NotEnoughLevelException _ => new (HttpStatusCode.BadRequest, "NotEnoughLevel"),
    _ => new (HttpStatusCode.InternalServerError, "Unknown")
}, showException: false);

现在,让我们开始记录请求和响应。最简单的启用方法包括 4 个步骤:

1. 注册http日志服务

builder.Services.AddHttpLogging(o => {});

2.附加http日志记录中间件

app.UseHttpLogging();

3. 删除appsettings.Development.json以尽量减少配置开销

4. 由于默认情况下的日志级别Microsoft.AspNetCore是Warning为 http 日志中间件指定专用的日志级别appsettings.json

"Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"

完成所有这些更改后,我们的完整版本Program.cs将如下所示:

using Microsoft.AspNetCore.Mvc;
using Nist.Errors;
using System.Net;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(o => {});

var app = builder.Build();

app.UseHttpLogging();

app.UseErrorBody<Error>(ex => ex switch {
    NotEnoughLevelException _ => new (HttpStatusCode.BadRequest, "NotEnoughLevel"),
    _ => new (HttpStatusCode.InternalServerError, "Unknown")
}, showException: false);

app.MapPost("/parties/{partyId}/guests", (string partyId, [FromQuery] bool? loungeAccess, Guest visitor) => {
    if (loungeAccess == true && !visitor.Vip) 
        throw new NotEnoughLevelException();

    return new Ticket(
        PartyId: partyId,
        Receiver: visitor.Name,
        LoungeAccess: loungeAccess ?? false,
        Code: Guid.NewGuid().ToString()
    );
});

app.Run();

public record Guest(string Name, bool Vip);
public record Ticket(string PartyId, string Receiver, bool LoungeAccess, string Code);
public class NotEnoughLevelException : Exception;


让我们测试一下,从一个正常请求开始:

POST http://localhost:5244/parties/new-year/guests?loungeAccess=true

{
    "name": "Paul",
    "vip" : true
}

以下是我们得到的日志:

现在让我们讨论一个“糟糕的”请求。

POST http://localhost:5244/parties/halloween/guests?loungeAccess=true

{
    "name": "John",
    "vip" : false
}

我们将获得:

配置日志记录
        如您所见,尽管我们记录了很多内容,但我们无法真正说出有关请求的很多信息。我们可能会找出哪个端点被击中以及我们的响应是否成功(如果我们使用 http 状态代码),但仅此而已。此外,在高负载环境中,匹配请求和响应可能是一个挑战,因为它们是分开记录的。所以让我们CombineLogs看看我们可以记录什么。以下是代码:

builder.Services.AddHttpLogging(o => {
    o.CombineLogs = true;

    o.LoggingFields = HttpLoggingFields.All | HttpLoggingFields.RequestQuery;
});

HttpLoggingFields.All有点撒谎,日志中也明确指出:“HttpRequest.QueryString 不包含在该标志中,因为它可能包含私人信息”。因此我们需要手动附加 RequestQuery

这就是我们现在得到的:

        这样就好多了,现在我们可以看到到底收到了什么、响应了什么,以及处理花了多少时间。然而,日志仍然让人感到不知所措——我们记录了很多标头,但似乎没有任何价值。让我们只留下我们需要的东西:

builder.Services.AddHttpLogging(o => {
    o.CombineLogs = true;

    o.LoggingFields = HttpLoggingFields.RequestQuery
        | HttpLoggingFields.RequestMethod
        | HttpLoggingFields.RequestPath
        | HttpLoggingFields.RequestBody
        | HttpLoggingFields.ResponseStatusCode
        | HttpLoggingFields.ResponseBody
        | HttpLoggingFields.Duration;
});

现在,我们将以更为紧凑的格式获得几乎相同数量的有用信息: 

使其变得更好
然而,我们现有的技术仍然存在一些问题:

        1、请注意,由于我们有路径变量,因此partyId字段的值path对于单个端点来说并不相同。这将阻止我们通过特定端点获取分析数据。

        2、请求响应日志与发生异常的日志之间没有任何联系。这会使查找失败响应的确切异常变得复杂。特别是当异常无法识别时。

        3、由于多种原因,日志仍然占用大量空间。首先,我们有无用的不可移除字段(RequestBodyStatus, PathBase)。其次,我们的格式非常“宽”,总共使用 4 行来表示方法、路径和查询字符串。

        幸运的是,我们有一个 nuget 包可以弥补内置库的盲点。我们来看看吧。首先,我们需要安装它:

dotnet add package Nist.Logging

然后只需更改三行:

using Nist.Logs;

// remove builder.Services.AddHttpLogging

app.UseHttpIOLogging(); // instead of app.UseHttpLogging();

我们得到了最少但功能齐全的日志:

        尽管仍然记录发生的异常,但我们不再需要依赖它,因为我们在日志中间件ExceptionHandlerMiddleware中记录了异常。您甚至可以ExceptionHandlerMiddleware在"Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware": "None"appsettings.json

回顾
最后,让我们看一下我们能够获得的最佳请求 - 响应日志: 

        尽管Microsoft.AspNetCore.NET 6 提供了广泛的开箱即用的 http 日志记录功能,但仍缺少一些功能。因此,我们使用了Nist.Logsnuget 包。下表总结了库的功能列表:

| Feature                   | Microsoft.AspNetCore.HttpLogging        | Nist.Logs |
|--------------------         |--------------------------------------|-----------     |
| Full Uri                    | ❌ - Only Path and Query Separately     | ✅         |
| Minimalism              | ❌ - Few unremovable redundant fields | ✅         |
| Exception attached | ❌                                                            | ✅         |
| Endpoint id              | ❌                                                            | ✅         |
| Single Line              | ✅                                                            | ✅         |
| Http Method            | ✅                                                            | ✅         |
| Request Body         | ✅                                                            | ✅         |
| Response Body      | ✅                                                            | ✅         |
| Response Code      | ✅                                                            | ✅         |
| Request Duration    | ✅                                                            | ✅         |

以下是最终版本,供快速参考Program.cs:

using Microsoft.AspNetCore.Mvc;
using Nist.Logs;
using Nist.Errors;
using System.Net;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseHttpIOLogging();
app.UseErrorBody<Error>(ex => ex switch {
    NotEnoughLevelException _ => new (HttpStatusCode.BadRequest, "NotEnoughLevel"),
    _ => new (HttpStatusCode.InternalServerError, "Unknown")
}, showException: false);
app.MapPost("/parties/{partyId}/guests", (string partyId, [FromQuery] bool? loungeAccess, Guest visitor) => {
    if (loungeAccess == true && !visitor.Vip) 
        throw new NotEnoughLevelException();
    return new Ticket(
        PartyId: partyId,
        Receiver: visitor.Name,
        LoungeAccess: loungeAccess ?? false,
        Code: Guid.NewGuid().ToString()
    );
});
app.Run();
public record Guest(string Name, bool Vip);
public record Ticket(string PartyId, string Receiver, bool LoungeAccess, string Code);
public class NotEnoughLevelException : Exception;

项目代码:https://download.csdn.net/download/hefeng_aspnet/90084914 

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。  

标签:Core,ASP,string,app,我们,loungeAccess,new,NET,日志
From: https://blog.csdn.net/hefeng_aspnet/article/details/144255338

相关文章

  • 如何在 ASP.NET Core 3.1 应用程序中使用 Log4Net
    介绍 日志记录是应用程序的核心。它对于调试和故障排除以及应用程序的流畅性非常重要。借助日志记录,我们可以对本地系统进行端到端的可视性,而对于基于云的系统,我们只能提供一小部分可视性。您可以将日志写入磁盘或数据库中的文件,并发送错误电子邮件。 为Log4Net......
  • .net 数组与字符串、集合之间互转
    1、数组与字符串互转stringstr="1,2,3,4,5,6,7";string[]strArray=str.Split(',');//字符串转数组str=string.Empty;str=string.Join(",",strArray);//数组转成字符串2、声明数组.第一种方法.声明并分配元素大小.int[]Myint=newint[30];Myint[0]=3......
  • 【.Net动态Web API】参数验证异常返回
    ​......
  • C#,.net 8 console call MessageBox of System.Windows.Forms, and via MessageBox of
    usingSystem.Runtime.InteropServices;namespaceConsoleApp6{internalclassProgram{//copyfrom,https://gist.github.com/6rube/34b561827f0805f73742541b8b8bb770[DllImport("user32.dll",CharSet=CharSet.Unicode)]......
  • [论文阅读] Radical Analysis Network for Zero-Shot Learning in Printed Chinese Ch
    Pretitle:RadicalAnalysisNetworkforZero-ShotLearninginPrintedChineseCharacterRecognitionaccepted:ICME2018paper:https://arxiv.org/abs/1711.01889code:https://github.com/JianshuZhang/RAN(onlyIDSdictionary)ref:RANforPrintedChineseCh......
  • NET components with PDF Crack
    .NETcomponentswithPDFCrack.NETcomponentswithPDFconversionfeaturesenableyoutotransformdocumentsintoformatsthataremoresuitableforspecifictasks.PDFconversionfunctionalityisaversatileandessentialtoolformanagingd......
  • Enhance .NET 9 Apps with Advanced Charting
    Enhance.NET9AppswithAdvancedCharting.netCHARTING10.7elevatesyourchartdatawithcutting-edgeperformanceandseamlessintegrationintothelatest.NETapplications..netCHARTINGisacomprehensivechartingsolutiondesignedforC#an......
  • .NET 模拟&编辑平滑曲线
    本文介绍不依赖贝塞尔曲线,如何绘制一条平滑曲线,用于解决无贝塞尔控制点的情况下绘制曲线、但数据点不在贝塞尔曲线的场景。在上一家公司我做过一个平滑曲线编辑工具,用于轮椅调整加减速曲线。基于几个用户可控制的点,生成一条平滑的曲线,控制点需要保持在曲线上。今天和小伙伴沟通,......
  • EtherNet/IP转profinet网模块应用在AB罗克韦尔PLC与西门子1500PLC通讯案例
        在工业自动化领域,不同品牌的PLC(可编程逻辑控制器)之间进行通讯往往是项目实施中面临的一个重要问题。本文将详细介绍如何利用EtherNet/IP转profinet网关模块(远创智控的YC-PN-EIP)实现罗克韦尔PLC与西门子1500PLC之间稳定、高效的通讯,帮助大家在类似的项目......
  • ubuntu网络配置工具netplan详解
     1.首先查看当前的 netplan配置文件:ls/etc/netplan/通常会有一个类似 01-netcfg.yaml 或 50-cloud-init.yaml 的文件。 2.编辑netplan配置文件firefly@firefly:~$vim/etc/netplan/01-netcfg.yamlnetwork:version:2renderer:networkdethernets:......