一、基础准备

  1. 安装依赖
    这里可以通过nuget或使用命令行进行安装,具体需要安装的类库如下(注意版本):
Install-Package App.Metrics.AspNetCore.Mvc -Version 2.0.0


由于我们需要兼容Prometheus进行监控,所以我们还需要安装对应的格式化库,具体如下:

Install-Package App.Metrics.Formatters.Prometheus -Version 2.0.0


以上就是需要的类库,接下来我们开始进行其他初始化部分。

  1. 初始配置
    为了保证其能够正常工作,我们需要根据不同的环境设定对应的appsettings.json文件从而让度量指标可以根据不同的环境进行输出,这里考虑到实际情况尚未存在不同的配置可能性故统一配置即可,打开appsettings.json输入下配置项:
{
 “MetricsOptions”: {
 “DefaultContextLabel”: “MetricsApplication”,
 “Enabled”: true
 },
 “MetricsWebTrackingOptions”: {
 “ApdexTrackingEnabled”: true,
 “ApdexTSeconds”: 0.3,
 “IgnoredHttpStatusCodes”: [ 404 ],
 “IgnoreRoutesRegexPatterns”: [],
 “OAuth2TrackingEnabled”: false
 },
 “MetricEndpointsOptions”: {
 “MetricsEndpointEnabled”: true,
 “MetricsTextEndpointEnabled”: true,
 “EnvironmentInfoEndpointEnabled”: true
 }
 }


参数DefaultContextLabel可以设定为我们期望其他名称,这里建议采用项目的简写名称,保证项目之间不存在冲突即可。参数ApdexTSeconds用于设定应用的响应能力标准,其采用了当前流行的Apdex标准,这里使用者可以根据自身应用的实际情况调整对应的参数,其他相关参数建议默认即可。

  1. 启用度量指标
    因为我们的数据需要符合Promethues格式,所以后续教程我们会替换默认的格式采用符合的格式。首先我们需要Program.cs里输入以下内容:
public static IWebHost BuildWebHost(string[] args)
 {
     Metrics = AppMetrics.CreateDefaultBuilder()
         .OutputMetrics.AsPrometheusPlainText()
         .OutputMetrics.AsPrometheusProtobuf()
         .Build();

     return WebHost.CreateDefaultBuilder(args)
             .ConfigureMetrics(Metrics)
             .UseMetrics(options =>
             {
                 options.EndpointOptions = endpointsOptions =>
                 {
                     endpointsOptions.MetricsTextEndpointOutputFormatter = Metrics.OutputMetricsFormatters.OfType<MetricsPrometheusTextOutputFormatter>().First();
                     endpointsOptions.MetricsEndpointOutputFormatter = Metrics.OutputMetricsFormatters.OfType<MetricsPrometheusProtobufOutputFormatter>().First();
                 };
             })
             .UseStartup<Startup>()
             .Build();
 }

其中为了能够支持其他格式,我们需要手动实例化Metrics对象完成相关初始化然后将其注入到asp.net core中,其中相关格式的代码主要是由以下这几部分组成:

OutputMetrics.AsPrometheusPlainText()
 OutputMetrics.AsPrometheusProtobuf()endpointsOptions.MetricsTextEndpointOutputFormatter = Metrics.OutputMetricsFormatters.OfType().First();
 endpointsOptions.MetricsEndpointOutputFormatter = Metrics.OutputMetricsFormatters.OfType().First();


完成以上操作后,我们最后还需要进行其他配置,打开Startup.cs文件增加如下内容:

services.AddMvc().AddMetrics();


至此我们就完成了基本的初始化了,通过启动程序并访问localhost:5000/metrics-text即可查看最终的输出内容。

二、自定义指标
由于其内部已经默认提供了若干的指标,但是并不能符合实际业务的需求故以下将对常用的度量指标类型以及用法进行介绍,这里这里大家通过注入IMetrics接口对象即可访问,所以下面这部分代码不在阐述。

  1. 仪表盘(Gauge)
    最常见的类型,主要是用于直接反应当前的指标情况,比如我们常见的CPU和内存基本都是使用这种方式进行显示的,可以直观的看到当前的实际的状态情况。对于所有的指标我们都需要定义对应的Options,当然这可以完成携程静态变量供应用程序全局使用。

比如下面我们定义一个表示当前发生错误次数的指标:

GaugeOptions Errors = new GaugeOptions()
 {
 Name = “Errors”
 };


完成指标的定义后,我们就可以在需要使用的地方进行指标数据的修改,比如下面我们将错误数量设置为10:

metrics.Measure.Gauge.SetValue(MyMetricsRegistry.Errors, 10);


这样我们就完成了指标的设定,但是有时候我们还想却分具体的Error是那个层面发起的,这个时候我们需要使用到Tag了,下面我们在设定值的同时设定指标,当然也可以在新建指标的时候通过Tags变量,并且通用于其他所有指标:

var tags = new MetricTags(“fromt”, “db”);
 metrics.Measure.Gauge.SetValue(MyMetricsRegistry.Errors, tags, 10);


至此我们就完成了一个基本的指标,下面我们继续其他类型指标。

  1. 计数值(Counter)
    对于HTTP类型的网站来说,存在非常多的数量需要统计记录,所以计数值此时就特别适合这类情况,比如我们需要统计请求数量就可以利用这类指标类型,下面我们就以请求数来定义这个指标:
var requestCounter = new CounterOptions()
 {
 Name = “httpRequest”,
 MeasurementUnit = Unit.Calls
 };


以上我们定义了一个计数指标,其中我们可以看到我们这里使用了一个新变量MeasurementUnit主要是用于定义指标单位的,当然这个只是辅助信息会一同输出到结果,下面我们需要进行增加和减少,考虑到大多数情况都是减1和增1的情况:

metrics.Measure.Counter.Increment(requestCounter);


实际情况可能我们都是统计请求但是期望还能单独统计特定接口的请求,这个时候我们在原本调用方式基础上增加额外的参数:

metrics.Measure.Counter.Increment(requestCounter, “api”);


如果嫌每次增长1比较慢,我们通过其函数的重载形式填写我们希望增长的具体值。

  1. 计量值(Meter)
    有点类似于计数值但是相比来说,它可以提供更加丰富的信息,比如每1、5、15分钟的增长率等,所以对于一些需要通过增长率观察的数据特别时候,这里我们以请求的反应状态码进行记录来体现其用途:
var httpStatusMeter = new MeterOptions()
 {
 Name = “Http Status”,
 MeasurementUnit = Unit.Calls
 };


以上我们完成了一个指标的定义,下面我们开始使用其并且定义不同的状态的码的发生情况,具体如下:

metrics.Measure.Meter.Mark(httpStatusMeter, “200”);
 metrics.Measure.Meter.Mark(httpStatusMeter, “500”);
 metrics.Measure.Meter.Mark(httpStatusMeter, “401”);


当然如果希望增加的数量自定控制也可以使用其提供的重载形式进行。

  1. 柱状图(Histogram)
    顾名思义,主要反应数据的分布情况,所以这里不在重复阐述,大家对于这种数据表现形式还是比较了解的,所以下面就直接以实际代码的实列进行介绍,便于大家的理解:
var postAndPutRequestSize = new HistogramOptions()
 {
 Name = “Web Request Post & Put Size”,
 MeasurementUnit = Unit.Bytes
 };


以上我们定义一个体现Post和Put请求的数据尺寸的指标,下面我们利用随机数来进行数据的模拟对其进行数据填充,便于显示数据:

var rnd = new Random();
foreach (var i in Enumerable.Range(0, 50))
 {
 var t = rnd.Next(0, 10);
metrics.Measure.Histogram.Update(postAndPutRequestSize, t);


5. 时间线(Timer)
对应指标的监控闭然少不了对于时间的记录,特别对于HTTP来说,直接影响到用户的体验就是响应时间,素以我们也需要时刻关于这类指标的变化情况及时做出反应,下面我们就以数据库的响应时间的情况作为指标进行监控:

TimerOptions DatabaseTimer = new TimerOptions()
 {
 Name = “Database Timer”,
 MeasurementUnit = Unit.Items,
 DurationUnit = TimeUnit.Milliseconds,
 RateUnit = TimeUnit.Milliseconds
 };


上面我们通过特别的属性指定了改指标记录时间的单位,下面我们使用其指标进行数据的记录:

using(metrics.Measure.Timer.Time(DatabaseTimer))
 {
 //to do sonmething
 }


我们可以看到为了方便的记录请求的时间,我们使用using进行涵括,并将需要记录耗时的请求操作放入其中,在请求完成操作后就可以正确的记录其需要的时间。

  1. apdex
    采用了一种标准的性能指标计算方式,用法类似与上述,这里仅仅列举用法:
ApdexOptions SampleApdex = new ApdexOptions
 {
 Name = “Sample Apdex”
 };using(metrics.Measure.Apdex.Track(SampleApdex))
 {
 Thread.Sleep(100);
 }


三、高级指标

  1. 平均响应
    很多时候我们仅仅依靠一个指标很难完成一个实际的需求,是所以我们就需要将多个指标进行组合进行,比如我们期望得到请求次数,同时还有请求的总时间和平均响应时间等,为此我们可以特殊的指标将多个指标进行组合,具体操作如下:
var cacheHitRatioGauge = new GaugeOptions
 {
 Name = “Cache Gauge”,
 MeasurementUnit = Unit.Calls
 };var cacheHitsMeter = new MeterOptions
 {
 Name = “Cache Hits Meter”,
 MeasurementUnit = Unit.Calls
 };var databaseQueryTimer = new TimerOptions
 {
 Name = “Database Query Timer”,
 MeasurementUnit = Unit.Calls,
 DurationUnit = TimeUnit.Milliseconds,
 RateUnit = TimeUnit.Milliseconds
 };var cacheHits = metrics.Provider.Meter.Instance(cacheHitsMeter);
 var calls = metrics.Provider.Timer.Instance(databaseQueryTimer);var cacheHit = new Random().Next(0, 2) == 0;
using(calls.NewContext())
 {
 if (cacheHit)
 {
 cacheHits.Mark(5);
 }
Thread.Sleep(cacheHit ? 10 : 100);
metrics.Measure.Gauge.SetValue(cacheHitRatioGauge, () => new HitRatioGauge(cacheHits, calls, m => m.OneMinuteRate));
 Xamarin.Android -> Xamarin.IOS -> 混合 -> Xamarin.Forms