Metrics.NET实践(1)

时间:2022-09-23 12:02:31

起因:对应用的监控和测量是WEB应用的一个重要话题,尤其在监控错误率,并发量,以及框架库中的动态值。于是,在性能优化的时候找到了metrics.net。

  • 简介
  • 开始使用
  • 度量
  • Gauges
  • Counters
  • Meters
  • Histograms
  • Timers

1. 簡介

Metrics.NET - a .NET Port, with lots of additional functionality, of the awesome Java metrics library by Coda Hale.

2. Getting Started

Install-Package Metrics.NET
Install-Package Metrics.NET.ElasticSearch -Version 0.5.0 # with ES
Install-Package Metrics.NET.Graphite -Version 0.5.0 #with Graphite

other:

  • Metrics.NET.RabbitMQ
  • Metrics.NET.InfluxDB
  • Metrics.NET.SignalFX
  • Metrics.NET.InfluxDbReporting
  • Metrics.NET.CloudWatch

Application_Start:

using Metrics;

Metric.Config
.WithHttpEndpoint("http://localhost:1234/")
.WithAllCounters();

访问:http://localhost:1234/ 即可看到效果。

3. 度量

  • Meters record the rate at which an event occurs。某事件发生的比率
  • Histograms measure the distribution of values in a stream of data。数据流的分布
  • Timers keep a histogram of the duration of a type of event and a meter of the rate of its occurrence。Meters和Histograms的结合。
  • Counters 64 bit integers that can be incremented or decremented。64位计数器
  • Gauges instantaneous values。简单值

3.1 Gauges

最简单的度量方式。代表一个瞬时值。

代码片段:

// gauge from Func<double>
Metric.Gauge("MyValue", () => ComputeMagicValue(), Unit.Items); // gauge that reads its value from a performance counter
Metric.PerformanceCounter("CPU Usage", "Processor", "% Processor Time",
"_Total", Unit.Custom("%")); // gauge that transforms the value of another gauge
Metric.Advanced.Gauge("Kbytes gauge",
() => new DerivedGauge(gaugeReturningValueInBytes, v => v / 1024.0 ),
Unit.KiloBytes); Metric.Context("[LogPool]").Gauge("dict.Count_Gauge",
() => { return dict.Count; }, Unit.Custom("個"), "log");

3.2 Counters

代表可以增減的64位整數。

代碼片段——緩存的數量

public class Cache
{
private static readonly Counter counter =
Metric.Counter("ItemsInCache", Unit.Items); private void AddItems(object[] items)
{
counter.Increment(items.Length);
} private void AddItem(object item)
{
counter.Increment();
} private void RemoveItem(object item)
{
counter.Decrement();
}
}

Counter提供分组计数的能力,针对标记接口可以实现:

public class SetCounterSample
{
private readonly Counter commandCounter =
Metric.Counter("Command Counter", Unit.Custom("Commands")); public interface Command { }
public class SendEmail : Command { }
public class ShipProduct : Command { }
public class BillCustomer : Command { }
public class MakeInvoice : Command { }
public class MarkAsPreffered : Command { } public void Process(Command command)
{
this.commandCounter.Increment(command.GetType().Name); // do actual command processing
}
}

输出:

 Command Counter
Count = 2550 Commands
Total Items = 5
Item 0 = 20.90% 533 Commands [BillCustomer]
Item 1 = 19.22% 490 Commands [MakeInvoice]
Item 2 = 19.41% 495 Commands [MarkAsPreffered]
Item 3 = 20.98% 535 Commands [SendEmail]
Item 4 = 19.49% 497 Commands [ShipProduct]

应用场景:可以用在WEB API中统计各种请求的数量。

3.3 Meters

A meter measures the rate at which an event occurs.meter测量一个事件发生的比率。

示例代码:请求异常的比率

public class RequestProcessor
{
private readonly Meter meter =
Metric.Meter("Errors", Unit.Requests, TimeUnit.Seconds); public void ProcessRequest()
{
try
{
// do actual processing
}
catch
{
meter.Mark(); // records an error
throw;
}
}
}

同样,也可以支持多态的分组:

public class SetMeterSample
{
private readonly Meter errorMeter = Metric.Meter("Errors", Unit.Errors); public interface Command { }
public class SendEmail : Command { }
public class ShipProduct : Command { }
public class BillCustomer : Command { }
public class MakeInvoice : Command { }
public class MarkAsPreffered : Command { } public void Process(Command command)
{
try
{
ActualCommandProcessing(command);
}
catch
{
errorMeter.Mark(command.GetType().Name);
}
}
}

输出:

 Errors
Count = 450 Errors
Mean Value = 35.68 Errors/s
1 Minute Rate = 25.44 Errors/s
5 Minute Rate = 24.30 Errors/s
15 Minute Rate = 24.10 Errors/s
Total Items = 5
Item 0 = 19.56% 88 Errors [BillCustomer]
Count = 88 Errors
Mean Value = 6.98 Errors/s
1 Minute Rate = 6.05 Errors/s
5 Minute Rate = 6.01 Errors/s
15 Minute Rate = 6.00 Errors/s
Item 1 = 18.67% 84 Errors [MakeInvoice]
Count = 84 Errors
Mean Value = 6.66 Errors/s
1 Minute Rate = 4.23 Errors/s
5 Minute Rate = 3.89 Errors/s
15 Minute Rate = 3.83 Errors/s
Item 2 = 20.22% 91 Errors [MarkAsPreffered]
Count = 91 Errors
Mean Value = 7.22 Errors/s
1 Minute Rate = 5.38 Errors/s
5 Minute Rate = 5.24 Errors/s
15 Minute Rate = 5.21 Errors/s
Item 3 = 19.78% 89 Errors [SendEmail]
Count = 89 Errors
Mean Value = 7.06 Errors/s
1 Minute Rate = 4.92 Errors/s
5 Minute Rate = 4.67 Errors/s
15 Minute Rate = 4.62 Errors/s
Item 4 = 21.78% 98 Errors [ShipProduct]
Count = 98 Errors
Mean Value = 7.77 Errors/s
1 Minute Rate = 4.86 Errors/s
5 Minute Rate = 4.50 Errors/s
15 Minute Rate = 4.43 Errors/s

3.4 Histograms

代码片段:搜索结果的分布。

开箱即用的三种抽样方法:

  • Exponentially Decaying Reservoir - 最近五分钟数据的分位数。
  • Uniform Reservoir - 产生整个週期有效的分位数
  • Sliding Window Reservoir - 产生代表过去N次测量的分位数
 private readonly Histogram histogram = Metric.Histogram("Search Results", Unit.Items);
public void Search(string keyword)
{
var results = ActualSearch(keyword);
histogram.Update(results.Length);
} // The histogram has the ability to track for which user value a Min, Max or Last Value has been recorded.
// The user value can be any string value (documentId, operationId, etc).
public class UserValueHistogramSample
{
private readonly Histogram histogram =
Metric.Histogram("Results", Unit.Items); public void Process(string documentId)
{
var results = GetResultsForDocument(documentId);
this.histogram.Update(results.Length, documentId);
}
}

输出:

    Results
Count = 90 Items
Last = 46.00 Items
Last User Value = document-3
Min = 2.00 Items
Min User Value = document-7
Max = 98.00 Items
Max User Value = document-4
Mean = 51.52 Items
StdDev = 30.55 Items
Median = 50.00 Items
75% <= 80.00 Items
95% <= 97.00 Items
98% <= 98.00 Items
99% <= 98.00 Items
99.9% <= 98.00 Items

3.5 Timers

示例代碼:

private readonly Timer timer =
Metric.Timer("HTTP Requests",Unit.Requests); public void ProcessRequest()
{
using(timer.NewContext())
{
// Actual Processing of the request
}
} private readonly Timer timer =
Metric.Timer("Requests", Unit.Requests); public void Process(string documentId)
{
using (var context = timer.NewContext(documentId))
{
ActualProcessingOfTheRequest(documentId); // if needed elapsed time is available in context.Elapsed
}
}

輸出:

  Requests
Count = 14 Requests
Mean Value = 1.86 Requests/s
1 Minute Rate = 1.80 Requests/s
5 Minute Rate = 1.80 Requests/s
15 Minute Rate = 1.80 Requests/s
Count = 14 Requests
Last = 869.03 ms
Last User Value = document-1
Min = 59.90 ms
Min User Value = document-6
Max = 869.03 ms
Max User Value = document-1
Mean = 531.81 ms
StdDev = 212.98 ms
Median = 594.83 ms
75% <= 670.18 ms
95% <= 869.03 ms
98% <= 869.03 ms
99% <= 869.03 ms
99.9% <= 869.03 ms