你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
.NET 和 .NET Core 中的自定义指标集合
Azure Monitor Application Insights.NET 和 .NET Core SDK 有两种不同的收集自定义指标的方法:TrackMetric()
和 GetMetric()
。 这两种方法的主要区别在于本地聚合。 TrackMetric()
方法缺少预聚合数据。 GetMetric()
方法具有预聚合数据。 建议使用聚合,因此,TrackMetric()
不再是收集自定义指标的首选方法。 本文介绍如何使用 GetMetric()
方法及其工作原理背后的一些基本原理。
注意
以下文档依赖于 Application Insights 经典 API。 Application Insights 的长期计划是使用 OpenTelemetry 收集数据。 有关详细信息,请参阅为 .NET、Node.js、Python 和 Java 应用程序启用 Azure Monitor OpenTelemetry 和我们的 OpenTelemetry 路线图。 迁移指导适用于 .NET、Node.js 和 Python。
预聚合与非预聚合 API
TrackMetric()
方法发送表示指标的原始遥测。 为每个值发送单个遥测项效率低。 TrackMetric()
方法在性能方面的效率也较低,因为每个 TrackMetric(item)
都要经过遥测初始化表达式和处理器的完整 SDK 管道。
与 TrackMetric()
不同,GetMetric()
为你处理本地预聚合,然后仅以一分钟的固定间隔提交经过汇总的指标摘要。 如果你需要在秒级甚至毫秒级密切监视某些自定义指标,则可以这样做,同时只需要承担每分钟监视一次的存储和网络流量成本。 这样做也极大降低了出现限制的风险,因为需要为聚合指标发送的遥测项总数大大减少。
在 Application Insights 中,通过 TrackMetric()
和 GetMetric()
收集的自定义指标不受采样限制。 对重要指标进行采样可能会导致以下情况:围绕这些指标构建的警报可能变得不可靠。 通过从不采样自定义指标,通常可以确信,一旦超过警报阈值,便会触发警报。 由于没有对自定义指标进行采样,因此存在一些潜在的问题。
如果需要每秒钟跟踪一个指标的趋势,或以更细粒度的间隔进行跟踪,这可能会导致:
- 数据存储成本增加。 向 Azure Monitor 发送的数据量会产生一定的成本。 发送的数据越多,监视的总体成本就越高。
- 网络流量或性能开销增加。 在某些情况下,此类开销可能会产生货币成本和应用程序性能成本。
- 引入限制风险。 当应用以短时间间隔发送速率很高的遥测时,Azure Monitor 会丢弃(“限制”)数据点。
限制是一个问题,因为它可能导致错过警报。 触发警报的情况可能在本地发生,然后由于发送的数据太多而在引入终结点被丢弃。 这就是对于 .NET 和 .NET Core,我们不建议使用 TrackMetric()
的原因,除非你已实现自己的本地聚合逻辑。 如果尝试跟踪事件在给定时间段内发生的每个实例,则可能会发现 TrackEvent()
更适合。 请记住,与自定义指标不同,自定义事件受采样限制。 即使不编写自己的本地预聚合,也可以使用 TrackMetric()
。 但如果这样做,请注意陷阱。
总之,建议使用 GetMetric()
,因为它执行预聚合、从所有 Track()
调用中累积值,并每分钟发送一次摘要/汇总。 通过发送更少的数据点,同时仍然收集所有相关信息,GetMetric()
方法可以显著降低成本和性能开销。
注意
只有 .NET 和 .NET Core SDK 具有 GetMetric()
方法。 如果使用的是 Java,请参阅使用 Micrometer 发送自定义指标。 对于 JavaScript 和 Node.js,仍可以使用 TrackMetric()
,但请记住上一部分总结的注意事项。 对于 Python,可以使用 OpenCensus.stats 发送自定义指标,但指标的实现是不同的。
GetMetric 入门
在示例中,我们将使用基本的 .NET Core 3.1 辅助角色服务应用程序。 如果你想复制与这些示例一起使用的测试环境,请遵循监视辅助角色服务一文中的步骤 1-6。 这些步骤会将 Application Insights 添加到基本辅助角色服务项目模板。 此概念适用于任何可以使用 SDK 的通用应用程序,包括 Web 应用和控制台应用。
发送指标
将 worker.cs
文件的内容替换为以下内容:
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.ApplicationInsights;
namespace WorkerService3
{
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private TelemetryClient _telemetryClient;
public Worker(ILogger<Worker> logger, TelemetryClient tc)
{
_logger = logger;
_telemetryClient = tc;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ // The following line demonstrates usages of GetMetric API.
// Here "computersSold", a custom metric name, is being tracked with a value of 42 every second.
while (!stoppingToken.IsCancellationRequested)
{
_telemetryClient.GetMetric("ComputersSold").TrackValue(42);
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
await Task.Delay(1000, stoppingToken);
}
}
}
}
运行示例代码时,你将看到 while
循环重复执行,且不会在 Visual Studio 输出窗口中发送遥测数据。 将围绕 60 秒的标记发送单个遥测项,测试中如下所示:
Application Insights Telemetry: {"name":"Microsoft.ApplicationInsights.Dev.00000000-0000-0000-0000-000000000000.Metric", "time":"2019-12-28T00:54:19.0000000Z",
"ikey":"00000000-0000-0000-0000-000000000000",
"tags":{"ai.application.ver":"1.0.0.0",
"ai.cloud.roleInstance":"Test-Computer-Name",
"ai.internal.sdkVersion":"m-agg2c:2.12.0-21496",
"ai.internal.nodeName":"Test-Computer-Name"},
"data":{"baseType":"MetricData",
"baseData":{"ver":2,"metrics":[{"name":"ComputersSold",
"kind":"Aggregation",
"value":1722,
"count":41,
"min":42,
"max":42,
"stdDev":0}],
"properties":{"_MS.AggregationIntervalMs":"42000",
"DeveloperMode":"true"}}}}
此单个遥测项代表了 41 个不同指标度量的聚合。 由于我们反复发送相同的值,因此标准偏差 (stDev
) 为 0
,具有相同的最大值 (max
) 和最小值 (min
)。 value
属性表示聚合的所有单个值的总和。
注意
GetMetric
方法不支持跟踪最后一个值(例如 gauge
)或跟踪直方图/分布。
如果我们在“日志(分析)”体验中检查 Application Insights 资源,此单独的遥测项将如以下屏幕截图所示。
注意
虽然原始遥测项在引入后不包含显式的总和属性/字段,但我们会为你创建一个。 在本例中,value
和 valueSum
属性都表示相同的内容。
还可以在门户的指标部分访问自定义指标遥测,作为基于日志的指标和自定义指标。 以下屏幕截图是基于日志的指标的一个示例。
用于高吞吐量使用情况的缓存指标引用
在某些情况下,可能会经常观察到指标值。 例如,每秒处理 500 个请求的高吞吐量服务可能希望为每个请求发出 20 个遥测指标。 该结果意味着每秒跟踪 10,000 个值。 在这种高吞吐量方案中,用户可能需要通过避免一些查找来帮助 SDK。
例如,上述示例对指标 ComputersSold
的句柄执行了查找操作,然后跟踪了观察到的值 42
。 相反,用户应该缓存该句柄,以进行多次跟踪调用:
//...
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
// This is where the cache is stored to handle faster lookup
Metric computersSold = _telemetryClient.GetMetric("ComputersSold");
while (!stoppingToken.IsCancellationRequested)
{
computersSold.TrackValue(42);
computersSold.TrackValue(142);
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
await Task.Delay(50, stoppingToken);
}
}
除了缓存指标句柄之外,上述示例还将 Task.Delay
缩短到了 50 毫秒,这样循环将更频繁地执行, 从而导致了 772 次 TrackValue()
调用。
多维指标
上一部分的示例显示零维度指标。 指标也可以是多维的。 目前最多支持 10 个维度。
下面是如何创建一维指标的示例:
//...
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
// This is an example of a metric with a single dimension.
// FormFactor is the name of the dimension.
Metric computersSold= _telemetryClient.GetMetric("ComputersSold", "FormFactor");
while (!stoppingToken.IsCancellationRequested)
{
// The number of arguments (dimension values)
// must match the number of dimensions specified while GetMetric.
// Laptop, Tablet, etc are values for the dimension "FormFactor"
computersSold.TrackValue(42, "Laptop");
computersSold.TrackValue(20, "Tablet");
computersSold.TrackValue(126, "Desktop");
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
await Task.Delay(50, stoppingToken);
}
}
运行示例代码至少 60 秒,这会将三个不同的遥测项发送到 Azure。 每个项都表示这三种外形规格之一的聚合。 与之前一样,你可以在“日志(分析)”视图中执行进一步检查。
在指标资源管理器中:
请注意,你无法按新的自定义维度拆分指标,也无法使用指标视图查看自定义维度。
默认情况下,Application Insights 资源中未启用指标资源管理器中的多维指标。
启用多维指标
要为 Application Insights 资源启用多维指标,请选择“使用情况和估计成本”>“自定义指标”>“启用自定义指标维度的警报”>“确定”。 有关详细信息,请参阅自定义指标维度和预聚合。
进行更改并发送新的多维遥测后,可以选择“应用拆分”。
注意
只有在门户中启用此功能后,新发送的指标才会存储维度。
查看每个 FormFactor
维度的指标聚合。
当维度超过三个时使用 MetricIdentifier
目前支持 10 个维度。 超过三个维度需要使用 MetricIdentifier
:
// Add "using Microsoft.ApplicationInsights.Metrics;" to use MetricIdentifier
// MetricIdentifier id = new MetricIdentifier("[metricNamespace]","[metricId],"[dim1]","[dim2]","[dim3]","[dim4]","[dim5]");
MetricIdentifier id = new MetricIdentifier("CustomMetricNamespace","ComputerSold", "FormFactor", "GraphicsCard", "MemorySpeed", "BatteryCapacity", "StorageCapacity");
Metric computersSold = _telemetryClient.GetMetric(id);
computersSold.TrackValue(110,"Laptop", "Nvidia", "DDR4", "39Wh", "1TB");
自定义指标配置
如果想要更改指标配置,则必须在初始化指标的位置进行更改。
特殊维度名称
指标不使用用于访问它们的 TelemetryClient
的遥测上下文。 在 MetricDimensionNames
类中使用可用作常量的特殊维度名称是解决此限制的最佳方法。
以下 Special Operation Request Size
指标发送的指标聚合不会将 Context.Operation.Name
设置为 Special Operation
。 TrackMetric()
方法或任何其他 TrackXXX()
方法会将 OperationName
正确设置为 Special Operation
。
//...
TelemetryClient specialClient;
private static int GetCurrentRequestSize()
{
// Do stuff
return 1100;
}
int requestSize = GetCurrentRequestSize()
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
//...
specialClient.Context.Operation.Name = "Special Operation";
specialClient.GetMetric("Special Operation Request Size").TrackValue(requestSize);
//...
}
}
在这种情况下,使用 MetricDimensionNames
类中列出的特殊维度名称来指定 TelemetryContext
值。
例如,当下一条语句生成的指标聚合发送到 Application Insights 云终结点时,其 Context.Operation.Name
数据字段将设置为 Special Operation
:
_telemetryClient.GetMetric("Request Size", MetricDimensionNames.TelemetryContext.Operation.Name).TrackValue(requestSize, "Special Operation");
此特殊维度的值将复制到 TelemetryContext
中,并且不会用作“普通”维度。 如果还希望用于普通指标探索的操作维度,则需要针对此目的创建单独的维度:
_telemetryClient.GetMetric("Request Size", "Operation Name", MetricDimensionNames.TelemetryContext.Operation.Name).TrackValue(requestSize, "Special Operation", "Special Operation");
维度和时序上限
要防止遥测子系统意外耗尽资源,可以控制每个指标的最大数据系列数。 默认限制是每个指标的总数据系列不超过 1,000 个,每个维度的不同值不超过 100 个。
重要
对维度使用低基数值以避免限制。
在维度和时序上限的上下文中,我们使用 Metric.TrackValue(..)
来确保遵守限制。 如果已经达到限制,Metric.TrackValue(..)
将返回 False
,并且不会跟踪该值。 否则,它将返回 True
。 如果指标的数据源于用户输入,该行为将很有用。
MetricConfiguration
构造函数可以选择如何在相应的指标以及实现 IMetricSeriesConfiguration
的类对象中管理不同的系列,该类为指标的每个单独系列指定聚合行为:
var metConfig = new MetricConfiguration(seriesCountLimit: 100, valuesPerDimensionLimit:2,
new MetricSeriesConfigurationForMeasurement(restrictToUInt32Values: false));
Metric computersSold = _telemetryClient.GetMetric("ComputersSold", "Dimension1", "Dimension2", metConfig);
// Start tracking.
computersSold.TrackValue(100, "Dim1Value1", "Dim2Value1");
computersSold.TrackValue(100, "Dim1Value1", "Dim2Value2");
// The following call gives 3rd unique value for dimension2, which is above the limit of 2.
computersSold.TrackValue(100, "Dim1Value1", "Dim2Value3");
// The above call does not track the metric, and returns false.
seriesCountLimit
是指标可以包含的最大数据时序数目。 达到此限制时,对TrackValue()
的调用将返回false
,该调用通常会生成新序列。valuesPerDimensionLimit
以类似的方式限制每个维度的非重复值数目。restrictToUInt32Values
确定是否只跟踪非负整数值。
以下示例演示如何发送消息以了解是否超过上限:
if (! computersSold.TrackValue(100, "Dim1Value1", "Dim2Value3"))
{
// Add "using Microsoft.ApplicationInsights.DataContract;" to use SeverityLevel.Error
_telemetryClient.TrackTrace("Metric value not tracked as value of one of the dimension exceeded the cap. Revisit the dimensions to ensure they are within the limits",
SeverityLevel.Error);
}
后续步骤
- 指标 - 获取 - REST API
- 用于处理自定义事件和指标的 Application Insights API
- 详细了解有关监视辅助角色服务应用程序的信息。
- 使用基于日志的指标和预聚合的指标。
- 使用指标资源管理器分析指标。
- 了解如何为 ASP.NET Core 应用程序启用 Application Insights。
- 了解如何为 ASP.NET 应用程序启用 Application Insights。