我们在构建WEBAPI项目时,通常需要构建一个全局的记录API 请求和返回 的功能,在WEBAPI框架下 我们通过自定义一个DelegateHandler来实现这个功能,

在.NET CORE框架下已经不存在DelegateHandler管道了,我们需要通过Middleware管道来实现。具体实现如下:

定义LoggingMiddleware

  1. public class GlobalApiLoggingMiddleware : IMiddleware
  2. {
  3. private readonly ILogger _logger;
  4.  
  5. public GlobalApiLoggingMiddleware(ILoggerFactory loggerFactory)
  6. {
  7. _logger = loggerFactory.CreateLogger("ApiLog");
  8. }
            public async Task InvokeAsync(HttpContext context, RequestDelegate next)
            {
            //在这里我们来拦截请求,收集日志
     await next.Invoke(context);
    }
  9. }

HttpContext的定义

可以看到里面的Request和Response对象 分别时 HttpRequest 和 HttpResponse,不再像在webapi框架下直接通过HttpRequestMessage、HttpResponseMessage来获取请求报文和返回报文。

这里需要花费一些技巧。

获取请求报文,

  1. //reuqest支持buff,否则body只能读取一次
  2. context.Request.EnableBuffering();
  3. //这里不要释放stream,否则后续读取request.body会报错
  4. var reader = new StreamReader(context.Request.Body, Encoding.UTF8);
  5. var requestStr = await reader.ReadToEndAsync();
                //var requestStr = reader.ReadToEnd(); 升级.net core 3.1后 会报 Synchronous operations are disallowed. 错误

首先类似于webapi框架下获取请求报文一样,需要先设置request buffer,这样request报文可以读取多次

其次获取报文的方式 是通过 stream获取,这里stream不要释放 不要释放 不要释放。重要的事情说三次。

获取返回报文 更加复杂一点

  1. Stream originalBody = context.Response.Body;
  2.  
  3. try
  4. {
  5. using (var memStream = new MemoryStream())
  6. {
  7. context.Response.Body = memStream;
  8. await next.Invoke(context);
  9.  
  10. var request = context.Request;
  11. var log = new ApiLogEntity()
  12. {
  13. Appkey = request.GetAppkey(),
  14. ClientIp = request.GetClientRealIp(),
  15. HttpMethod = request.Method,
  16. Request = requestStr,
  17. RequestId = request.GetRequestId(),
  18. RequestUrl = request.Path.Value,
  19. QueryString = request.QueryString.Value,
  20. ServerIp = request.Host.Value,
  21. StatusCode = context.Response.StatusCode
  22. };
  23.  
  24. memStream.Position = ;
  25. log.Response = await new StreamReader(memStream).ReadToEndAsync();
  26.  
  27. memStream.Position = ;
  28. await memStream.CopyToAsync(originalBody);
  29.  
  30. _logger.LogInformation(JsonConvert.SerializeObject(log));
  31. }
  32. }
  33. finally
  34. {
  35. //重新给response.body赋值,用于返回
  36. context.Response.Body = originalBody;
  37. }

这里HttpResponse的body是不允许读取的!!所以这里的策略是 先给body赋值一个新的stream,

执行完action得到返回值后,可以读取我们自己定义的stream拿到返回报文

最后把返回值stream copy给原来的body对象,并重新赋给context.Response.Body,这里客户端可以正确返回了。

OK,结束!

.NET CORE之API日志收集的更多相关文章

  1. C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志

    C#实现多级子目录Zip压缩解压实例 参考 https://blog.csdn.net/lki_suidongdong/article/details/20942977 重点: 实现多级子目录的压缩, ...

  2. 在.NET Core中使用Exceptionless分布式日志收集框架

    一.Exceptionless简介 Exceptionless 是一个开源的实时的日志收集框架,它可以应用在基于 ASP.NET,ASP.NET Core,Web Api,Web Forms,WPF, ...

  3. asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程

    最近在学习张善友老师的NanoFabric 框架的时了解到Exceptionless : https://exceptionless.com/ !因此学习了一下这个开源框架!下面对Exceptionl ...

  4. Net Core免费开源分布式异常日志收集框架Exceptionless

    asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 https://www.cnblogs.com/yilezhu/p/9193723.htm ...

  5. 【转】asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程

    最近在学习张善友老师的NanoFabric 框架的时了解到Exceptionless : https://exceptionless.com/ !因此学习了一下这个开源框架!下面对Exceptionl ...

  6. 一套标准的ASP.NET Core容器化应用日志收集分析方案

    讲故事 关注我公众号的朋友,应该知道我写了一些云原生应用收集和分析相关的文章,其中内容大多聚焦某个具体的组件: 超级有用的TraceId,快点用起来吧! 如何利用NLog输出结构化日志,并在Kiban ...

  7. 微服务日志之.NET Core使用NLog通过Kafka实现日志收集

    一.前言 NET Core越来越受欢迎,因为它具有在多个平台上运行的原始.NET Framework的强大功能.Kafka正迅速成为软件行业的标准消息传递技术.这篇文章简单介绍了如何使用.NET(Co ...

  8. 循序渐进学.Net Core Web Api开发系列【10】:使用日志

    系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.本篇概述 本篇介 ...

  9. .NET Core使用NLog通过Kafka实现日志收集

    微服务日志之.NET Core使用NLog通过Kafka实现日志收集 https://www.cnblogs.com/maxzhang1985/p/9522017.html 一.前言 NET Core ...

随机推荐

  1. ubuntu 用shell脚本实现将当前文件夹下全部文件夹中的某一类文件复制到同一文件夹下

    当前文件夹下有一些文件和文件夹,当中每一个文件夹里都有若干.txt文件. 如今要求在当前文件夹创建一个新文件夹all,且将那些文件夹全部.txt文件 都复制到文件夹all.在ubuntu12.04的s ...

  2. sed 修连接文件,有坑

    -bash-4.1# ll /etc/rc.local  lrwxrwxrwx. 1 root root 13 Aug 15  2014 /etc/rc.local -> rc.d/rc.loc ...

  3. npm的安装和更新

    https://nodejs.org官网下载软件安装 验证是否安装,进入命令行 输入npm -v 这个是安装node自动带的工具 npm install npm@xxx 自动更新自己,后边跟版本号 n ...

  4. mac下配置eclipse的maven环境

    转自:http://www.cnblogs.com/yqskj/archive/2013/03/30/2990292.html 1.下载maven的bin包,解压,配置到环境变量里面去 1). 首先到 ...

  5. Finally语句块的运行

    一.finally语句块是否一定运行? Java中异常捕获机制try...catch...finally块中的finally语句是不是一定会被运行?非常多人都说不是.当然他们的回答是正确的,经过试验. ...

  6. 如何查看Java进程并获取进程ID?

    1. 在 LINUX 命令平台输入 1-2 个字符后按 Tab 键会自动补全后面的部分(前提是要有这个东西,例如在装了 tomcat 的前提下, 输入 tomcat 的 to 按 tab).2. ps ...

  7. ln mv 发挥一个物体的元作用

    # tar xf ~/tools/mongodb-linux-x86_64-3.4.0.tgz -C /usr/local/; ln -sf /usr/local/mongodb-linux-x86_ ...

  8. 定时任务Timer

    一.Timer介绍 java.util.Timer java.util.TimerTask Timer是一个定时器类,通过该类可以为指定的定时任务进行配置.TimerTask类是一个定时任务类,该类实 ...

  9. 20170224 SE11删除数据

    目的,批量删除错误条目.1.SE11 通过条件找到目标数据,并选中: 2./H 进入debug,回车,更改值 OK_CODE  =  DEL5 F8 运行则出现删除框,

  10. 使用SVPullToRefresh实现下拉刷新和下拉加载

    移动端开发中,“下拉刷新”和“上拉加载更多”早已在各大App中随处可见.也非常容易就能找到直接可供使用的第三方资源.譬如EGOTableViewPullRefresh(下拉刷新)和LoadMoreTa ...