Anpassad måttsamling i .NET och .NET Core

Azure Monitor Application Insights .NET och .NET Core SDK:er har två olika metoder för att samla in anpassade mått: TrackMetric() och GetMetric(). Den viktigaste skillnaden mellan dessa två metoder är lokal aggregering. Metoden TrackMetric() saknar föraggregering. Metoden GetMetric() har föraggregering. Vi rekommenderar att du använder aggregering, så TrackMetric() det är inte längre den bästa metoden för att samla in anpassade mått. Den här artikeln beskriver hur du använder GetMetric() metoden och en del av logiken bakom hur den fungerar.

Kommentar

Följande dokumentation förlitar sig på det klassiska API:et Application Insights. Den långsiktiga planen för Application Insights är att samla in data med OpenTelemetry. Mer information finns i Aktivera Azure Monitor OpenTelemetry för .NET-, Node.js-, Python- och Java-program.

Föraggregering jämfört med API för icke-föraggregering

Metoden TrackMetric() skickar råtelemetri som anger ett mått. Det är ineffektivt att skicka ett enda telemetriobjekt för varje värde. Metoden TrackMetric() är också ineffektiv när det gäller prestanda eftersom varje TrackMetric(item) går igenom hela SDK-pipelinen för telemetriinitierare och processorer.

Till skillnad från TrackMetric()hanterar GetMetric() lokal föraggregering åt dig och skickar sedan bara ett aggregerat sammanfattningsmått med ett fast intervall på en minut. Om du behöver noggrant övervaka vissa anpassade mått på den andra eller till och med millisekundersnivån kan du göra det samtidigt som du bara ådrar dig lagrings- och nätverkstrafikkostnaden för att bara övervaka varje minut. Det här beteendet minskar också risken för begränsning eftersom det totala antalet telemetriobjekt som behöver skickas för ett aggregerat mått minskar avsevärt.

I Application Insights samlas anpassade mått in via TrackMetric() och GetMetric() omfattas inte av sampling. Sampling av viktiga mått kan leda till scenarier där aviseringar som du kan ha byggt kring dessa mått kan bli otillförlitliga. Genom att aldrig sampla dina anpassade mått kan du vara säker på att när dina aviseringströsklar överskrids utlöses en avisering. Eftersom anpassade mått inte samplas finns det vissa potentiella problem.

Trendspårning i ett mått varje sekund, eller med ett ännu mer detaljerat intervall, kan resultera i:

  • Ökade kostnader för datalagring. Det finns en kostnad som är kopplad till hur mycket data du skickar till Azure Monitor. Ju mer data du skickar, desto större blir den totala kostnaden för övervakning.
  • Ökad nätverkstrafik eller prestandakostnader. I vissa scenarier kan den här kostnaden ha både en ekonomisk kostnad och en programprestandakostnad.
  • Risk för inmatningsbegränsning. Azure Monitor släpper datapunkter ("throttles") när din app skickar en hög telemetrifrekvens på kort tid.

Begränsning är ett problem eftersom det kan leda till missade aviseringar. Villkoret för att utlösa en avisering kan inträffa lokalt och sedan tas bort vid inmatningsslutpunkten på grund av att för mycket data skickas. Vi rekommenderar inte att du använder TrackMetric() för .NET och .NET Core om du inte har implementerat din egen lokala aggregeringslogik. Om du försöker spåra varje instans som en händelse inträffar under en viss tidsperiod kanske det TrackEvent() passar bättre. Tänk på att anpassade händelser till skillnad från anpassade mått omfattas av sampling. Du kan fortfarande använda TrackMetric() även utan att skriva din egen lokala föraggregering. Men om du gör det, var medveten om fallgroparna.

Sammanfattningsvis rekommenderar GetMetric() vi att eftersom den utför föraggregering ackumuleras värden från alla Track() anrop och skickar en sammanfattning/aggregering en gång i minuten. Metoden GetMetric() kan avsevärt minska kostnaderna och prestandakostnaderna genom att skicka färre datapunkter samtidigt som all relevant information samlas in.

Kommentar

Endast .NET- och .NET Core-SDK:erna har en GetMetric() metod. Om du använder Java kan du läsa Skicka anpassade mått med hjälp av mikrometer. För JavaScript och Node.js använder du fortfarande TrackMetric(), men tänk på de varningar som beskrevs i föregående avsnitt. För Python kan du använda OpenCensus.stats för att skicka anpassade mått, men måttimplementeringen är annorlunda.

Kom igång med GetMetric

I våra exempel ska vi använda ett grundläggande .NET Core 3.1-arbetstjänstprogram. Om du vill replikera testmiljön som används med de här exemplen följer du steg 1–6 i artikeln Övervakning av arbetstjänsten. De här stegen lägger till Application Insights i en grundläggande arbetstjänstprojektmall. Begreppen gäller för alla allmänna program där SDK:t kan användas, inklusive webbappar och konsolappar.

Skicka mått

Ersätt innehållet i worker.cs filen med följande kod:

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);
            }
        }
    }
}

När du kör exempelkoden ser du att loopen while körs upprepade gånger utan att telemetri skickas i Visual Studio-utdatafönstret. Ett enda telemetriobjekt skickas av runt 60-sekundersmarkeringen, vilket i vårt test ser ut så här:

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"}}}}

Det här enskilda telemetriobjektet representerar en sammanställning av 41 distinkta måttmätningar. Eftersom vi skickade samma värde om och om igen har vi en standardavvikelse (stDev) av 0 med identiska högsta (max) och lägsta (min) värden. Egenskapen value representerar en summa av alla enskilda värden som aggregerades.

Kommentar

Metoden GetMetric stöder inte spårning av det sista värdet (till exempel gauge) eller spårning av histogram eller distributioner.

Om vi undersöker vår Application Insights-resurs i logs(Analytics) -upplevelsen skulle det enskilda telemetriobjektet se ut som följande skärmbild.

Screenshot that shows the Log Analytics query view.

Kommentar

Även om råtelemetriobjektet inte innehöll en explicit summaegenskap/fält när det matades in skapar vi en åt dig. I det här fallet representerar både value egenskapen och valueSum samma sak.

Du kan också komma åt din anpassade måtttelemetri i avsnittet Mått i portalen som både ett loggbaserat och anpassat mått. Följande skärmbild är ett exempel på ett loggbaserat mått.

Screenshot that shows the Metrics explorer view.

Referens för cachemått för användning med högt dataflöde

Måttvärden kan observeras ofta i vissa fall. En tjänst med högt dataflöde som bearbetar 500 begäranden per sekund kanske vill generera 20 telemetrimått för varje begäran. Resultatet innebär att du spårar 10 000 värden per sekund. I sådana scenarier med högt dataflöde kan användarna behöva hjälpa SDK:t genom att undvika vissa sökningar.

Till exempel utförde föregående exempel en sökning efter ett handtag för måttet ComputersSold och spårade sedan ett observerat värde på 42. I stället kan handtaget cachelagras för flera spåranrop:

//...

        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);
            }
        }

Förutom att cachelagra måtthandtaget minskades Task.Delay även föregående exempel till 50 millisekunder så att loopen skulle köras oftare. Resultatet är 772 TrackValue() anrop.

Flerdimensionella mått

Exemplen i föregående avsnitt visar nolldimensionella mått. Mått kan också vara flerdimensionella. Vi stöder för närvarande upp till 10 dimensioner.

Här är ett exempel på hur du skapar ett endimensionellt mått:

//...

        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);
            }
        }

Om du kör exempelkoden i minst 60 sekunder skickas tre distinkta telemetriobjekt till Azure. Varje objekt representerar aggregeringen av en av de tre formfaktorerna. Precis som tidigare kan du undersöka mer i vyn Loggar (analys).

Screenshot that shows the Log Analytics view of multidimensional metric.

I metrics Explorer:

Screenshot that shows Custom metrics.

Observera att du inte kan dela upp måttet med din nya anpassade dimension eller visa din anpassade dimension med måttvyn.

Screenshot that shows splitting support.

Som standard är flerdimensionella mått i måttutforskaren inte aktiverade i Application Insights-resurser.

Aktivera flerdimensionella mått

Om du vill aktivera flerdimensionella mått för en Application Insights-resurs väljer du Användning och uppskattade kostnader>Anpassade mått Aktivera aviseringar>för anpassade måttdimensioner>OK. Mer information finns i Anpassade måttdimensioner och föraggregering.

När du har gjort ändringen och skickat ny flerdimensionell telemetri kan du välja Tillämpa delning.

Kommentar

Endast nyligen skickade mått efter att funktionen har aktiverats i portalen har lagrade dimensioner.

Screenshot that shows applying splitting.

Visa dina måttaggregeringar för varje FormFactor dimension.

Screenshot that shows form factors.

Använd MetricIdentifier när det finns fler än tre dimensioner

För närvarande stöds 10 dimensioner. Mer än tre dimensioner kräver användning av 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");

Anpassad måttkonfiguration

Om du vill ändra måttkonfigurationen måste du göra ändringar på den plats där måttet initieras.

Specialdimensionsnamn

Mått använder inte telemetrikontexten för de TelemetryClient som används för att komma åt dem. Att använda specialdimensionsnamn som är tillgängliga som konstanter i MetricDimensionNames klassen är den bästa lösningen för den här begränsningen.

Måttaggregeringar som skickas av följande Special Operation Request Size mått har Context.Operation.Name inte angetts till Special Operation. Metoden TrackMetric() eller någon annan TrackXXX() metod har OperationName angetts korrekt till 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);
                //...
            }
                   
        }

I det här fallet använder du de specialdimensionsnamn som anges i MetricDimensionNames klassen för att ange TelemetryContext värdena.

När måttaggregatet från nästa instruktion till exempel skickas till Application Insights-molnslutpunkten anges dess Context.Operation.Name datafält till Special Operation:

_telemetryClient.GetMetric("Request Size", MetricDimensionNames.TelemetryContext.Operation.Name).TrackValue(requestSize, "Special Operation");

Värdena för den här specialdimensionen kopieras till TelemetryContext och används inte som en normal dimension. Om du även vill behålla en åtgärdsdimension för normal måttutforskning måste du skapa en separat dimension för detta ändamål:

_telemetryClient.GetMetric("Request Size", "Operation Name", MetricDimensionNames.TelemetryContext.Operation.Name).TrackValue(requestSize, "Special Operation", "Special Operation");

Tak för dimensioner och tidsserier

Om du vill förhindra att telemetriundersystemet oavsiktligt använder dina resurser kan du styra det maximala antalet dataserier per mått. Standardgränserna är högst 1 000 totala dataserier per mått och högst 100 olika värden per dimension.

Viktigt!

Använd låga kardinalvärden för dimensioner för att undvika begränsning.

När det gäller begränsning av dimension och tidsserier använder Metric.TrackValue(..) vi för att se till att gränserna följs. Om gränserna redan har nåtts Metric.TrackValue(..) returneras False och värdet spåras inte. Annars returneras True. Det här beteendet är användbart om data för ett mått kommer från användarindata.

Konstruktorn MetricConfiguration tar några alternativ för hur du hanterar olika serier inom respektive mått och ett objekt i en klass som implementerar IMetricSeriesConfiguration som anger aggregeringsbeteende för varje enskild serie av måttet:

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 är det maximala antalet datatidsserier som ett mått kan innehålla. När den här gränsen har nåtts returnerar anrop till TrackValue() det normalt en ny serie .false
  • valuesPerDimensionLimit begränsar antalet distinkta värden per dimension på ett liknande sätt.
  • restrictToUInt32Values avgör om endast icke-negativa heltalsvärden ska spåras eller inte.

Här är ett exempel på hur du skickar ett meddelande för att veta om gränsen överskrids:

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);
}

Nästa steg