asp.net core监控—引入Prometheus(二)

上一篇博文中,说明了怎么引进Prometheus到asp.net core项目中,因为是Demo,所以Prometheus和Grafana都是windows版本,本地执行的,生产环境上这些服务可以根据的公司的架构,放到适合的环境内,现在这些服务都支持跨平台化和容器化。并且在上篇博客中展示的是http请求的基础信息模板,本篇博客介绍自定义Prometheusr指标类型。

Prometheus有四种指标类型:Counter(计数器)、Gauge(仪表盘)、Histogram(直方图)、Summary(摘要),如果对业务的指标进行收集展示,在项目中是侵入式编程的,如果项目使用Prometheus.net进行对接Permetheus,是通过该包中的静态方法 Metrics.CreateCounter(),Metrics.CreateGauge(),Metrics.CreateSummary(),Metrics.CreateHistogram()来创建静态指标收集器,完成对业务指标收集的。

我们先来看具体Demo。

1、Counter:计数器,只增不减

先设置个业务场景:比如做一个商城,有用户注册(/register),下订单(/order),支付(/pay),发货(/ship)四个API,代码如下:

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using PrometheusSample.Models;
using PrometheusSample.Services;
using System;
using System.Threading.Tasks;namespace PrometheusSample.Controllers
{[ApiController][Route("[controller]")]public class BusinessController : ControllerBase{private readonly ILogger<BusinessController> _logger;private readonly IOrderService _orderService;public BusinessController(ILogger<BusinessController> logger, IOrderService orderService){_orderService = orderService;_logger = logger;}/// <summary>/// 注册/// </summary>/// <param name="username">用户名</param>/// <returns></returns>[HttpPost("/register")]public async Task<IActionResult> RegisterUser([FromBody] User user){try{_logger.LogInformation("用户注册");var result = await _orderService.Register(user.UserName);if (result){return new JsonResult(new { Result = true });}else{return new JsonResult(new { Result = false });}}catch (Exception exc){_logger.LogCritical(exc, exc.Message);return new JsonResult(new { Result = false, Message = exc.Message });}}[HttpGet("/order")]public IActionResult Order(string orderno){try{_logger.LogInformation("下单");             return new JsonResult(new { Result = true });}catch (Exception exc){_logger.LogCritical(exc, exc.Message);return new JsonResult(new{Result = false,Message = exc.Message});}}[HttpGet("/pay")]public IActionResult Pay(){try{_logger.LogInformation("支付");return new JsonResult(new { Result = true });}catch (Exception exc){_logger.LogCritical(exc, exc.Message);return new JsonResult(new { Result = false, Message = exc.Message });}}[HttpGet("/ship")]public IActionResult Ship(){try{_logger.LogInformation("发货");return new JsonResult(new { Result = true });}catch (Exception exc){_logger.LogCritical(exc, exc.Message);return new JsonResult(new { Result = false, Message = exc.Message });}}}
}

上面是基本的业务Controller,为了降低依赖,我们的业务指标收集统一到一个中间件中去收集,中间件根据请求的url,和返回的数据结果数据进行业务指标数据的收集,当然也可以引入action过滤器或MediatR等中介者模式的组件来隔离业务逻辑的开发与监控数据的采集。

本例是用中间件的方式,首先定义一个静态的指标收集器:

   public class MetricsHub{private static Dictionary<string, Counter> _counterDictionary = new Dictionary<string, Counter>();public Counter GetCounter(string key){if (_counterDictionary.ContainsKey(key)){return _counterDictionary[key];}else{return null;}}public void AddCounter(string key, Counter counter){_counterDictionary.Add(key, counter);}}

定义中间件BusinessMetricsMiddleware

using Microsoft.AspNetCore.Http;
using PrometheusSample.Models;
using System.IO;
using System.Threading.Tasks;namespace PrometheusSample.Middlewares
{/// <summary>/// 请求记录中间件/// </summary>public class BusinessMetricsMiddleware{private readonly RequestDelegate _next;public BusinessMetricsMiddleware(RequestDelegate next){_next = next;}public async Task InvokeAsync(HttpContext context, MetricsHub metricsHub){var originalBody = context.Response.Body;try{using (var memStream = new MemoryStream()){//从管理返回的Response中取出返回数据,根据返回值进行监控指标计数context.Response.Body = memStream;await _next(context);memStream.Position = 0;string responseBody = new StreamReader(memStream).ReadToEnd();memStream.Position = 0;await memStream.CopyToAsync(originalBody);if (metricsHub.GetCounter(context.Request.Path) != null || metricsHub.GetGauge(context.Request.Path) != null){//这里约定所有action返回值是一个APIResult类型var result = System.Text.Json.JsonSerializer.Deserialize<APIResult>(responseBody, new System.Text.Json.JsonSerializerOptions { PropertyNameCaseInsensitive = true });if (result != null && result.Result){//获取到Countervar counter = metricsHub.GetCounter(context.Request.Path);if (counter != null){//计数counter.Inc();}}}}}finally{context.Response.Body = originalBody;}}}
}

中间件中,只要action请求返回的Result为true,就会计数,这样做的前提条件是业务返回值有统一约定;但每个action返回不可能都一样的,如果有特例,可以用action过滤器或中介者模式组件来对应。

再看一下Starup中是怎么配置这个中间件的:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using Prometheus;
using PrometheusSample.Middlewares;
using PrometheusSample.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;namespace PrometheusSample
{public class Startup{public Startup(IConfiguration configuration){Configuration = configuration;}public IConfiguration Configuration { get; }public void ConfigureServices(IServiceCollection services){MetricsHandle(services);services.AddScoped<IOrderService, OrderService>();services.AddControllers();services.AddSwaggerGen(c =>{c.SwaggerDoc("v1", new OpenApiInfo { Title = "PrometheusSample", Version = "v1" });});}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();app.UseSwagger();app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "PrometheusSample v1"));}app.UseRouting();//http请求的中间件app.UseHttpMetrics();app.UseAuthorization();//自定义业务跟踪app.UseBusinessMetrics();app.UseEndpoints(endpoints =>{//映射监控地址为  /metricsendpoints.MapMetrics();endpoints.MapControllers();});}/// <summary>/// 处理监控事项/// </summary>/// <param name="services"></param>void MetricsHandle(IServiceCollection services){var metricsHub = new MetricsHub();//countermetricsHub.AddCounter("/register", Metrics.CreateCounter("business_register_user", "注册用户数。"));metricsHub.AddCounter("/order", Metrics.CreateCounter("business_order_total", "下单总数。"));metricsHub.AddCounter("/pay", Metrics.CreateCounter("business_pay_total", "支付总数。"));metricsHub.AddCounter("/ship", Metrics.CreateCounter("business_ship_total", "发货总数。"));services.AddSingleton(metricsHub);}}
}

MetricsHandle中,我们添加了四个action,分别对应的四个计数器,这样,当这四个url有请求,并且返回值中的result=true时,就会往对应的计数器上计数。

这样数据收集好了,现在开始在Grafana中配置显示的图表了:

订单各状态总数配置:

订单各状态30秒内数量跟踪折线

最后的运行结果是:

总结实现自定义业务计数器步骤:

1、分析业务,规划好监控跟踪指标

2、定义指标收集器

3、侵入编程(尽量在开发时分离业务实现与监控指票的收集代码)收集指标

4、开发grafana展示模板,完成展示

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/307252.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASP.NET Core Blazor Webassembly 之 渐进式应用(PWA)

Blazor支持渐进式应用开发也就是PWA。使用PWA模式可以使得web应用有原生应用般的体验。什么是PWAPWA应用是指那些使用指定技术和标准模式来开发的web应用&#xff0c;这将同时赋予它们web应用和原生应用的特性。例如&#xff0c;web应用更加易于发现——相比于安装应用&#xf…

TCP三次握手(详解)

一&#xff1a;引出 客户端与服务器之间数据的发送和返回的过程当中需要创建一个叫TCP connection的东西&#xff1b;由于TCP不存在连接的概念&#xff0c;只存在请求和响应&#xff0c;请求和响应都是数据包&#xff0c;它们之间都是经过由TCP创建的一个从客户端发起&#xf…

进击吧! Blazor !第五期 安全

Blazor 是一个 Web UI 框架&#xff0c;可通过 WebAssembly 在任意浏览器中运行 .Net 。Blazor 旨在简化快速的单页面 .Net 浏览器应用的构建过程&#xff0c;它虽然使用了诸如 CSS 和 HTML 之类的 Web 技术&#xff0c;但它使用 C&#xff03;语言和 Razor 语法代替 JavaScrip…

有一种无耻叫 “我是为你着想”

这是头哥侃码的第221篇原创十一之后&#xff0c;我的状态一直不好&#xff0c;总感觉胸口有东西堵着&#xff0c;时不时还会觉得呼吸困难。上周末&#xff0c;我咨询了几位有医学背景的朋友&#xff0c;有说是因为季节转换而造成的身体不适&#xff0c;不用在意&#xff0c;但也…

asp.net core监控—引入Prometheus(四)

上一篇博文中说到Prometheus有四种指标类型&#xff1a;Counter&#xff08;计数器&#xff09;、Gauge&#xff08;仪表盘&#xff09;、Histogram&#xff08;直方图&#xff09;、Summary&#xff08;摘要&#xff09;&#xff0c;并且我们做了一个Counter的Demo&#xff0c…

[开源] .Net ORM FreeSql 1.10.0 稳步向前

写在开头FreeSql 是 .NET 开源生态下的 ORM 轮子&#xff0c;转眼快两年了&#xff0c;说真的开源不容易&#xff08;只有经历过才明白&#xff09;。今天带点干货和湿货给大家&#xff0c;先说下湿货。认识我的人&#xff0c;知道 CSRedisCore 是我写的另外一个开源组件&#…

CAP-微服务间通信实践

微服务间通信常见的两种方式由于微服务架构慢慢被更多人使用后&#xff0c;迎面而来的问题是如何做好微服务间通信的方案。我们先分析下目前最常用的两种服务间通信方案。gRPC&#xff08;rpc远程调用&#xff09;gRPC-微服务间通信实践场景&#xff1a;A服务主动发起请求到B服…

软件构造学习笔记-第二周

本周课程把第六章测试的内容提前讲了一部分&#xff0c;主要为实验1服务&#xff0c;讲了有关测试的概念、作用和基本方法。“测试优先”的思想是非常重要的&#xff0c;根据spec写出简单而全面的测试&#xff0c;在方法/类完成后第一时间对其进行测试&#xff0c;保证每个方法…

T-SQL | 你需要了解的执行计划

【T-SQL】| 作者 / Edison Zhou这是EdisonTalk的第297篇学习分享T-SQL是ANSI和ISO SQL标准的MS SQL扩展&#xff0c;其正式名称为Transact-SQL&#xff0c;但一般程序员都称其为T-SQL。本文是我学习《T-SQL查询》一书的读书笔记&#xff0c;为你讲解执行计划是个什么鬼。1关于执…

软件构造学习笔记-实验1

记录一下做实验1时遇到的问题。 准备工作 1.GitHub的注册和配置 由于之前没有接触过GitHub&#xff0c;所以碰到了一些问题。GitHub是什么&#xff1f;怎么建立GitHub远程仓库与本地仓库的连接&#xff1f;怎么在GitHub上传和下载文件&#xff1f; 实验完成后我可以简单回答上…

好的自我介绍,面试成功一大半

大家好&#xff0c;我是Z哥。关于面试时的自我介绍&#xff0c;我想大家遇到的情况都差不多&#xff0c;大部分面试的第一个环节基本都是这个。每个人也都知道留下好的第一印象很重要&#xff0c;但我估计很多人对这件事的解决方式&#xff0c;也就在网上找个自我介绍的模版就完…

软件构造学习笔记-第三周

本周介绍了软件开发的几种模型&#xff0c;并重点介绍了Git。Git是分布式版本控制系统&#xff0c;可以通过SSH key建立远程与本地的连接&#xff0c;通过Git Bash中的命令进行文件的上传和下载。对于这门课程&#xff0c;Git的主要作用就是向TA提交实验代码。 软件开发生命周…

log4net直切ElasticSearch,小步快跑首选

很多小步快跑的公司&#xff0c;开发人员可能就3-4个&#xff0c;面对巨大业务压力&#xff0c;日连夜的赶着上线&#xff0c;快速试错&#xff0c;自然就没时间搭建一些基础设施&#xff0c;比如说logCenter&#xff0c;但初期项目不稳定&#xff0c;bug又多&#xff0c;每次都…

软件构造学习笔记-第四周

本周重点介绍了mutable和immutable的概念&#xff0c;有些抽象。对于immutable的数据类型来说&#xff0c;想修改其引用指向的值&#xff0c;必须使其指向新的内存区域&#xff0c;而不能在原有的内存区域做修改。mutable数据类型相反&#xff0c;可以在原来指向的内存区域进行…

壹佰文章总结| 关于ASP.NETCore的分享之路

公众号不让放外网链接&#xff0c;点击【阅读原文】&#xff0c;去我的博客园&#xff0c;可以看对应的详细文章。&#xff08;关于学习ASP.NET Core需要了解和掌握的知识点图&#xff09;一言不合就来图&#xff0c;各位博客园小伙伴大家好&#xff0c;感觉好久没有写文章了&a…

软件构造学习笔记-第五周

本周讲了AF、RI、Safety from rep exposure、spec等概念。这些是辅助程序设计的重要部分&#xff0c;需要在代码中以注释的形式体现&#xff0c;可以显著提高代码可读性&#xff0c;明确设计的目的。必须要养成写的习惯&#xff01;&#xff01;&#xff01; 设计规约 1.规约…

EFCore之SQL扩展组件BeetleX.EFCore.Extension

EFCore是.NETCore团队开发的一个ORM组件&#xff0c;但这个组件在执行传统SQL的时候并不方便&#xff0c;因此BeetleX.EFCore.Extension的设计目的是让EFCore执行传统SQL更简单方便。引用在使用组件之前需要引用它&#xff0c;可以通过以下地址获取最新版本https://www.nuget.o…

软件构造学习笔记-第六周

这周的重点是重载和重写。重载要求两方法的签名必须不同&#xff0c;而重写则要求两方法的签名必须相同。重载可以发生在同一个类中&#xff0c;也可以发生在父类和子类中&#xff1b;重写必须发生在父类和子类中。接口/抽象类不具有构造方法&#xff0c;只有将内部的抽象方法全…

云原生时代,.NET5必将称王!

“ 随着互联网持续高歌猛进&#xff0c;相关技术名词也是层出不穷。微服务、容器化、DevOps、ServerLess、FaaS&#xff0c;这两年最火的&#xff0c;当属云原生Cloud Native&#xff01;当下大部分企业还在追逐微服务架构落地&#xff0c;而下一代的架构云原生已如火如荼。程序…

软件构造学习笔记-实验2

P1 1.设计目标 首先对图的ADT进行两种实现&#xff08;从边和顶点出发&#xff09;&#xff0c;然后选择一种实现的ADT&#xff0c;根据输入的文件构建语料库&#xff0c;再利用构建的语料库&#xff0c;对输入字符串进行插入操作&#xff0c;并返回修改后的字符串。 2.有关AF…