上一篇博文中说到Prometheus有四种指标类型:Counter(计数器)、Gauge(仪表盘)、Histogram(直方图)、Summary(摘要),并且我们做了一个Counter的Demo,接下来看看Gauge。

2、Gauge:仪表盘,有增有减

  这个指标非常像汽车的车速表,指针是在一定范围内有增有减的。下面我们接着上一篇博文的Sample来说,现在需要实时监控处在下“单完成”,“支付完成”,“发货完成”的单据数据,和各三种状态的占比;我们知道一个订单在一个时刻只能是一种状态,我们可以在下单时增加计数order的指标,但当订单从order转到pay状态后,pay指标会增加,同时order指标会减少,这个场景就会用上了Gauge了。

  有了这个思路,我们可以上手代码了,BusinessController的代码不变(因为我们实现了业务逻辑代码和监控数据指标采集分离),这里我们需要在MetricsHub.cs中添加Gauge类型的指标收集集合:

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

  因为在上面分析中,我们一个动作,比如pay时,会触发两个指标的改变,order指标减少,pay指标增加,所以Gauge是一个Dictionary<string, Dictionary<string, Gauge>>类型,内部的字典存放减少和增加的Gauge的监控指标对象。

  接下来就要在BusinessMetricsMiddleware的中间件中添加处理Gauge指标增加减少的代码了:

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)
{
//获取到Counter
var counter = metricsHub.GetCounter(context.Request.Path);
if (counter != null)
{
//计数
counter.Inc();
} var gauges = metricsHub.GetGauge(context.Request.Path);
if (gauges != null)
{
//存在增加指标+就Inc
if (gauges.ContainsKey("+"))
{
gauges["+"].Inc();
}
//存在减少指标-就Dec
if (gauges.ContainsKey("-"))
{
gauges["-"].Dec();
}
}
}
}
}
}
finally
{
context.Response.Body = originalBody;
} }
}
}

  再就是在Starsup中配置对应url的Gauge参数了:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;
using Prometheus;
using PrometheusSample.Middlewares;
using PrometheusSample.Services;
using System.Collections.Generic;
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 =>
{
//映射监控地址为 /metrics
endpoints.MapMetrics();
endpoints.MapControllers();
});
}
/// <summary>
/// 处理监控事项
/// </summary>
/// <param name="services"></param>
void MetricsHandle(IServiceCollection services)
{
var metricsHub = new MetricsHub();
//counter
metricsHub.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", "发货总数。")); //gauge
var orderGauge = Metrics.CreateGauge("business_order_count", "当前下单数量。");
var payGauge = Metrics.CreateGauge("business_pay_count", "当前支付数量。");
var shipGauge = Metrics.CreateGauge("business_ship_count", "当前发货数据。");
metricsHub.AddGauge("/order", new Dictionary<string, Gauge> {
{ "+", orderGauge}
});
metricsHub.AddGauge("/pay", new Dictionary<string, Gauge> {
{"-",orderGauge},
{"+",payGauge}
});
metricsHub.AddGauge("/ship", new Dictionary<string, Gauge> {
{"+",shipGauge},
{"-",payGauge}
});
services.AddSingleton(metricsHub);
}
}
}

  最后一步,就是打开Grafana来配置展示图表了

  订单状态数据仪表盘

  订单状态比例图

  最终的展示结果

  上一篇中我们说过自定义业务计数器类型的步骤,其实仪盘的步骤也一样

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

  2、定义指标收集器

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

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

  想要更快更方便的了解相关知识,可以关注微信公众号 
 

asp.net core监控—引入Prometheus(三)的更多相关文章

  1. Pro ASP.NET Core MVC 6th 第三章

    第三章 MVC 模式,项目和约定 在深入了解ASP.NET Core MVC的细节之前,我想确保您熟悉MVC设计模式背后的思路以及将其转换为ASP.NET Core MVC项目的方式. 您可能已经了解 ...

  2. 探索 ASP.Net Core 3.0系列三:ASP.Net Core 3.0中的Service provider validation

    前言:在本文中,我将描述ASP.NET Core 3.0中新的“validate on build”功能. 这可以用来检测您的DI service provider是否配置错误. 具体而言,该功能可检 ...

  3. 从零开始一个个人博客 by asp.net core and angular(三)

    这是第三篇了,第一篇只是介绍,第二篇介绍了api项目的运行和启动,如果api项目没什么问题了,调试都正常了,那基本上就没什么事了,由于这一篇是讲前端项目的,所以需要运行angular项目了,由于前端项 ...

  4. 022年9月12日 学习ASP.NET Core Blazor编程系列三——实体

    学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应用程序(上) 学习ASP.NET Core Blazor编程系 ...

  5. ASP.NET Core 简单引入教程

    0.简介 开源.跨平台 1.环境安装 参考官方教程   Core 官方文档 2.向世界问个好 sheel/cmd 下: dotnet --help // 查看帮助 dotnet new *     / ...

  6. ASP.NET Core 基础知识(三) Program.cs类

    ASP.NET Framework应用程序是严重依赖于IIS的,System.Web 中有很多方法都是直接调用的 IIS API,并且它还是驻留在IIS进程中的.而 ASP.NET Core 的运行则 ...

  7. ASP.NET Core 学习笔记 第三篇 依赖注入框架的使用

    前言 首先感谢小可爱门的支持,写了这个系列的第二篇后,得到了好多人的鼓励,也更加坚定我把这个系列写完的决心,也能更好的督促自己的学习,分享自己的学习成果.还记得上篇文章中最后提及到,假如服务越来越多怎 ...

  8. 学习ASP.NET Core Razor 编程系列三——创建数据表及创建项目基本页面

    一.创建脚本工具并执行初始迁移 在本节中,您将使用包管理控制台(PMC)来更新数据库: •添加VisualStudio Web代码生成包.这个包是运行脚本引擎所必需的. • 执行Add-Migrati ...

  9. ASP.NET Core Authentication系列(三)Cookie选项

    前言 在本系列第一篇文章介绍了ASP.NET时代如何认证,并且介绍了如何通过web.config文件来配置Auth Cookie的选项. 第二篇文章介绍了如何使用Cookie认证,本文介绍几个常见的C ...

随机推荐

  1. 1131 - Just Two Functions

    1131 - Just Two Functions    PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 ...

  2. Sentry 开发者贡献指南 - SDK 开发(事件负载)

    内容整理自官方开发文档 系列 Docker Compose 部署与故障排除详解 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentr ...

  3. 第二十八个知识点:什么是公钥密码学的IND-CCA安全定义?

    第二十八个知识点:什么是公钥密码学的IND-CCA安全定义? 我们将在这篇博客中讨论公钥加密的IND-CCA安全. IND-CCA安全代表选择明文的不可伪造性.这样的安全方案的思想就是给定一个密文,攻 ...

  4. Scalable Rule-Based Representation Learning for Interpretable Classification

    目录 概 主要内容 Wang Z., Zhang W., Liu N. and Wang J. Scalable rule-based representation learning for inte ...

  5. ApkToolBoxGUI 0.0.8发布了!!

    https://github.com/jiangxincode/ApkToolBoxGUI APKToolBoxGUI是一个程序员常用的小工具合集,有个比较友好的交互界面.主要包含编码转换,时间戳转换 ...

  6. Selenium_截图(16)

    selenium截图有两种方式 截取全屏 get_screenshot_as_file(filename):将截图转化成文件保存到本地,filename为保存的文件路径 get_screenshot_ ...

  7. alias 中使用 awk

    alias hehistory10='history |awk "{print \$2}"|sort|uniq -c|sort -rn|head -10' alias lv='ls ...

  8. java邮件打包在linux备份数据库练习

    注:图片如果损坏,点击文章链接:https://www.toutiao.com/i6812982512256549387/ 承接上一篇文档<Java实现163邮箱发送邮件到QQ邮箱> 主方 ...

  9. vue js 格式化时间

    常用于iview日期组件时间处理 /** * @param {Number} num 数值 * @returns {String} 处理后的字符串 * @description 如果传入的数值小于10 ...

  10. SYCOJ4972的幂次方

    题目- 2的幂次方 (shiyancang.cn) 递归题 #include<bits/stdc++.h> using namespace std; int k; void f(int n ...