.NET 和 .NET Core 中的自訂計量集合
Azure 監視器 Application Insights .NET 和 .NET Core SDK 有兩種不同方法可收集自訂計量:TrackMetric()
和 GetMetric()
。 這兩種方法之間的主要差異是本機彙總。 TrackMetric()
方法缺少預先彙總。 GetMetric()
方法有預先彙總。 建議使用彙總,因此 TrackMetric()
不再是收集自訂計量的慣用方法。 此文章將逐步引導您使用 GetMetric()
方法,以及其運作方式背後的一些原理。
注意
下列文件以 Application Insights 傳統 API 為依據。 Application Insights 的長期計劃是使用 OpenTelemetry 收集資料。 如需詳細資訊,請參閱 啟用適用於 .NET、Node.js、Python 和 JAVA 應用程式的 Azure 監視器 OpenTelemetry 和 我們的 OpenTelemetry 藍圖。 移轉指導適用於 .NET、Node.js 和 Python。
預先彙總與非預先彙總 API
TrackMetric()
方法會傳送代表計量的原始遙測。 針對每個值傳送單一遙測項目的效率不佳。 TrackMetric()
方法在效能方面的效率也不佳,因為每個 TrackMetric(item)
都要經過遙測初始設定式和處理器的完整 SDK 管線。
不同於 TrackMetric()
,GetMetric()
會為您處理本機預先彙總,然後只以一分鐘的固定間隔提交彙總的摘要計量。 如果您需要以秒或甚至毫秒層級密切監視某些自訂計量,您可以執行此動作,同時僅會產生每分鐘只監視一次的儲存體和網路流量成本。 此行為也可大幅降低發生節流的風險,因為需要針對彙總計量傳送的遙測項目總數會大幅降低。
在 Application Insights 中,透過 TrackMetric()
和 GetMetric()
收集的自訂計量不會受到取樣影響。 針對重要計量進行取樣,可能導致警示您圍繞那些計量所建置的案例變得不可靠。 由於絕對不會針對您的自訂計量進行取樣,因此,您通常能夠確信當警示閾值有缺口時,就會引發警示。 因為不會針對自訂計量進行取樣,所以有一些潛在的疑慮。
逐秒追蹤計量中的趨勢,或使用更精細的間隔,可能會導致:
- 增加資料儲存體成本。 傳送至 Azure 監視器的資料量會產生相關聯的成本。 您傳送的資料越多,整體監視成本就越高。
- 增加網路流量或效能額外負荷。 在某些情況下,此額外負荷可能同時帶來費用與應用程式效能成本。
- 擷取節流的風險。 您的應用程式在短時間內傳送高比率的遙測時,Azure 監視器就會捨棄 (「節流」) 資料點。
節流可能會導致警示闕漏,是一項顧慮。 觸發警示的條件可能會在本地發生,但隨後在擷取端點上可能因傳送的資料過多而遭到卸除。 除非您實作了自己的本機彙總邏輯,否則不建議對 .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 個維度。 超過 3 個維度需要使用 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");
維度和時間序列上限
若要防止遙測子系統意外使用您的資源,您可以控制每個計量的資料數列數目上限。 預設限制為每個計量不超過 1000 個資料數列總數,而且每個維度不超過 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。