Kolekcja metryk niestandardowych na platformach .NET i .NET Core

Zestawy SDK aplikacji usługi Azure Monitor Szczegółowe informacje .NET i .NET Core mają dwie różne metody zbierania metryk niestandardowych: TrackMetric() i GetMetric(). Kluczową różnicą między tymi dwiema metodami jest agregacja lokalna. Metoda TrackMetric() nie ma agregacji wstępnej. Metoda GetMetric() ma wstępnie agregację. Zalecamy używanie agregacji, więc TrackMetric() nie jest to już preferowana metoda zbierania metryk niestandardowych. Ten artykuł przeprowadzi Cię przez proces używania GetMetric() metody i niektóre uzasadnienie jego działania.

Uwaga

Poniższa dokumentacja opiera się na klasycznym interfejsie API usługi Application Szczegółowe informacje. Długoterminowy plan Szczegółowe informacje aplikacji polega na zbieraniu danych przy użyciu biblioteki OpenTelemetry. Aby uzyskać więcej informacji, zobacz Enable Azure Monitor OpenTelemetry for .NET, Node.js, Python and Java applications (Włączanie usługi Azure Monitor OpenTelemetry dla platformy .NET, Node.js, Python i Java applications).

Wstępne agregowanie a nie agregowanie interfejsu API

Metoda TrackMetric() wysyła nieprzetworzone dane telemetryczne oznaczające metrykę. Nieefektywne jest wysyłanie pojedynczego elementu telemetrii dla każdej wartości. Metoda TrackMetric() jest również nieefektywna pod względem wydajności, ponieważ każdy TrackMetric(item) przechodzi przez pełny potok zestawu SDK inicjatorów i procesorów telemetrii.

W przeciwieństwie do TrackMetric()programu GetMetric() obsługuje lokalną agregację wstępną, a następnie przesyła tylko zagregowaną metrykę podsumowania w stałym interwale jednej minuty. Jeśli musisz dokładnie monitorować metrykę niestandardową na drugim lub nawet milisekundowym poziomie, możesz to zrobić, jednocześnie generując tylko koszt magazynowania i ruchu sieciowego tylko co minutę. To zachowanie znacznie zmniejsza również ryzyko wystąpienia ograniczania przepustowości, ponieważ całkowita liczba elementów telemetrii, które należy wysłać dla zagregowanej metryki, jest znacznie zmniejszona.

W Szczegółowe informacje aplikacji metryki niestandardowe zbierane za pośrednictwem TrackMetric() metody i GetMetric() nie podlegają próbkowaniu. Próbkowanie ważnych metryk może prowadzić do scenariuszy, w których alerty mogły zostać skompilowane wokół tych metryk, mogą stać się zawodne. Nigdy nie próbkując metryk niestandardowych, możesz mieć pewność, że po naruszeniu progów alertu alert zostanie wyzwolony. Ponieważ metryki niestandardowe nie są próbkowane, istnieją pewne potencjalne obawy.

Śledzenie trendów w metryce co sekundę lub w jeszcze bardziej szczegółowym interwale może spowodować:

  • Zwiększone koszty magazynowania danych. Istnieje koszt związany z ilością danych wysyłanych do usługi Azure Monitor. Im więcej wysyłanych danych, tym większy całkowity koszt monitorowania.
  • Zwiększony ruch sieciowy lub obciążenie związane z wydajnością. W niektórych scenariuszach obciążenie to może mieć zarówno koszt wydajności pieniężnej, jak i aplikacji.
  • Ryzyko ograniczenia pozyskiwania. Usługa Azure Monitor odrzuca punkty danych ("throttles"), gdy aplikacja wysyła wysoką szybkość telemetrii w krótkim przedziale czasu.

Ograniczanie przepustowości jest problemem, ponieważ może prowadzić do nieodebranych alertów. Warunek wyzwalania alertu może wystąpić lokalnie, a następnie zostać porzucony w punkcie końcowym pozyskiwania z powodu zbyt dużej ilości wysyłanych danych. Nie zalecamy używania dla TrackMetric() platform .NET i .NET Core, chyba że zaimplementowano własną lokalną logikę agregacji. Jeśli próbujesz śledzić każde wystąpienie, które występuje w danym okresie, może się okazać, że TrackEvent() jest to lepsze dopasowanie. Należy pamiętać, że w przeciwieństwie do metryk niestandardowych zdarzenia niestandardowe podlegają próbkowaniu. Nadal można używać TrackMetric() nawet bez konieczności pisania własnej lokalnej wstępnej agregacji. Ale jeśli to zrobisz, pamiętaj o pułapkach.

Podsumowując, zalecamy GetMetric() , ponieważ wykonuje agregację wstępną, gromadzi wartości ze wszystkich Track() wywołań i wysyła podsumowanie/agregację raz na minutę. Metoda GetMetric() może znacząco zmniejszyć koszty i obciążenie związane z wydajnością, wysyłając mniej punktów danych, jednocześnie zbierając wszystkie istotne informacje.

Uwaga

Tylko zestawy .NET i .NET Core SDK mają metodę GetMetric() . Jeśli używasz języka Java, zobacz Wysyłanie metryk niestandardowych przy użyciu mikrometru. W przypadku języków JavaScript i Node.js nadal należy używać elementu TrackMetric(), ale należy pamiętać o zastrzeżeniach, które zostały opisane w poprzedniej sekcji. W przypadku języka Python możesz użyć biblioteki OpenCensus.stats do wysyłania metryk niestandardowych, ale implementacja metryk jest inna.

Wprowadzenie do usługi GetMetric

W naszych przykładach użyjemy podstawowej aplikacji usługi procesu roboczego platformy .NET Core 3.1. Jeśli chcesz replikować środowisko testowe używane z tymi przykładami, wykonaj kroki 1–6 w artykule Monitorowanie usługi procesu roboczego. Te kroki umożliwiają dodanie Szczegółowe informacje aplikacji do podstawowego szablonu projektu usługi procesu roboczego. Koncepcje dotyczą dowolnej aplikacji ogólnej, w której można używać zestawu SDK, w tym aplikacji internetowych i aplikacji konsolowych.

Wysyłanie metryk

Zastąp zawartość worker.cs pliku następującym kodem:

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

Po uruchomieniu przykładowego kodu pętla while jest wielokrotnie wykonywana bez wysyłania danych telemetrycznych w oknie danych wyjściowych programu Visual Studio. Pojedynczy element telemetrii jest wysyłany przez około 60-sekundowego znacznika, który w naszym teście wygląda następująco:

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

Ten pojedynczy element telemetrii reprezentuje agregację 41 odrębnych pomiarów metryk. Ponieważ wysyłaliśmy tę samą wartość ponownie, mamy odchylenie standardowe (stDev) z 0 identycznymi wartościami maksymalnymi (max) i minimalnymi (min). Właściwość value reprezentuje sumę wszystkich poszczególnych wartości, które zostały zagregowane.

Uwaga

Metoda GetMetric nie obsługuje śledzenia ostatniej wartości (na przykład gauge) ani śledzenia histogramów lub dystrybucji.

Jeśli zbadamy nasz zasób aplikacji Szczegółowe informacje w środowisku dzienników (analiza), pojedynczy element telemetrii będzie wyglądać podobnie jak na poniższym zrzucie ekranu.

Screenshot that shows the Log Analytics query view.

Uwaga

Podczas gdy nieprzetworzony element telemetrii nie zawierał jawnej właściwości sumy/pola po pozyskaniu, utworzymy go dla Ciebie. W tym przypadku zarówno właściwość , jak value i valueSum reprezentuje to samo.

Dostęp do niestandardowej telemetrii metryk można również uzyskać w sekcji Metryki portalu jako metryki opartej na dzienniku i niestandardowej. Poniższy zrzut ekranu jest przykładem metryki opartej na dzienniku.

Screenshot that shows the Metrics explorer view.

Dokumentacja metryk pamięci podręcznej na potrzeby użycia wysokiej przepływności

W niektórych przypadkach wartości metryk mogą być obserwowane często. Na przykład usługa o wysokiej przepływności, która przetwarza 500 żądań na sekundę, może chcieć emitować 20 metryk telemetrii dla każdego żądania. Wynik oznacza śledzenie 10 000 wartości na sekundę. W takich scenariuszach o wysokiej przepływności użytkownicy mogą potrzebować pomocy zestawowi SDK, unikając niektórych odnośników.

Na przykład w poprzednim przykładzie wykonano wyszukiwanie uchwytu dla metryki ComputersSold , a następnie prześledził obserwowaną wartość 42. Zamiast tego dojście może być buforowane dla wielu wywołań śledzenia:

//...

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

Oprócz buforowania uchwytu metryki, powyższy przykład również zmniejszył Task.Delay się do 50 milisekund, aby pętla wykonywała się częściej. Wynik to 772 TrackValue() wywołania.

Metryki wielowymiarowe

W przykładach w poprzedniej sekcji przedstawiono metryki zerowymiarowe. Metryki mogą być wielowymiarowe. Obecnie obsługujemy maksymalnie 10 wymiarów.

Oto przykład tworzenia metryki jednowymiarowej:

//...

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

Uruchomienie przykładowego kodu przez co najmniej 60 sekund powoduje wysłanie trzech odrębnych elementów telemetrii na platformę Azure. Każdy element reprezentuje agregację jednego z trzech czynników formularzy. Tak jak wcześniej, można dokładniej zbadać w widoku Dzienniki (analiza).

Screenshot that shows the Log Analytics view of multidimensional metric.

W eksploratorze metryk:

Screenshot that shows Custom metrics.

Zwróć uwagę, że nie można podzielić metryki przez nowy niestandardowy wymiar ani wyświetlić niestandardowego wymiaru z widokiem metryk.

Screenshot that shows splitting support.

Domyślnie metryki wielowymiarowe w eksploratorze metryk nie są włączone w zasobach usługi Application Szczegółowe informacje.

Włączanie metryk wielowymiarowych

Aby włączyć metryki wielowymiarowe dla zasobu aplikacji Szczegółowe informacje, wybierz pozycję Użycie i szacowane koszty>metryki niestandardowe Włącz alerty dotyczące niestandardowych wymiarów>metryk>OK. Aby uzyskać więcej informacji, zobacz Niestandardowe wymiary metryk i wstępna agregacja.

Po wprowadzeniu tej zmiany i wysłaniu nowej telemetrii wielowymiarowej możesz wybrać pozycję Zastosuj dzielenie.

Uwaga

Tylko nowo wysłane metryki po włączeniu funkcji w portalu będą miały przechowywane wymiary.

Screenshot that shows applying splitting.

Wyświetl agregacje metryk dla każdego FormFactor wymiaru.

Screenshot that shows form factors.

Użyj MetricIdentifier, jeśli istnieje więcej niż trzy wymiary

Obecnie obsługiwane są 10 wymiarów. Korzystanie z programu wymaga użycia więcej niż trzech wymiarów 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");

Niestandardowa konfiguracja metryki

Jeśli chcesz zmienić konfigurację metryki, musisz wprowadzić zmiany w miejscu, w którym jest inicjowana metryka.

Specjalne nazwy wymiarów

Metryki nie używają kontekstu telemetrii używanego do uzyskiwania TelemetryClient do nich dostępu. Używanie specjalnych nazw wymiarów dostępnych jako stałe w MetricDimensionNames klasie jest najlepszym obejściem tego ograniczenia.

Agregacje metryk wysyłane przez następującą Special Operation Request Size metryki nie będą miały Context.Operation.Name ustawionej wartości Special Operation. Metoda lub dowolna TrackMetric() inna TrackXXX() metoda zostanie OperationName ustawiona poprawnie na 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);
                //...
            }
                   
        }

W tej sytuacji należy użyć specjalnych nazw wymiarów wymienionych w MetricDimensionNames klasie, aby określić TelemetryContext wartości.

Na przykład gdy agregacja metryk wynikająca z następnej instrukcji zostanie wysłana do punktu końcowego aplikacji Szczegółowe informacje w chmurze, jego Context.Operation.Name pole danych zostanie ustawione na wartość Special Operation:

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

Wartości tego specjalnego wymiaru zostaną skopiowane do TelemetryContext i nie będą używane jako normalny wymiar. Jeśli chcesz również zachować wymiar operacji dla normalnej eksploracji metryki, musisz utworzyć oddzielny wymiar dla tego celu:

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

Ograniczenie wymiarów i szeregów czasowych

Aby zapobiec przypadkowemu używaniu zasobów przez podsystem telemetrii, można kontrolować maksymalną liczbę serii danych na metryki. Limity domyślne to nie więcej niż 1000 łącznych serii danych na metryki i nie więcej niż 100 różnych wartości na wymiar.

Ważne

Użyj niskich wartości kardynaalnych dla wymiarów, aby uniknąć ograniczania przepustowości.

W kontekście ograniczenia wymiarów i szeregów czasowych używamy Metric.TrackValue(..) metody , aby upewnić się, że limity są przestrzegane. Jeśli limity zostały już osiągnięte, Metric.TrackValue(..) zwraca wartość False , a wartość nie będzie śledzona. W przeciwnym razie zwraca wartość True. To zachowanie jest przydatne, jeśli dane metryki pochodzą z danych wejściowych użytkownika.

Konstruktor MetricConfiguration przyjmuje kilka opcji zarządzania różnymi seriami w ramach odpowiedniej metryki i obiektu klasy implementujące IMetricSeriesConfiguration , która określa zachowanie agregacji dla każdej serii metryki:

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 to maksymalna liczba szeregów czasowych danych, które może zawierać metryka. Po osiągnięciu tego limitu wywołania TrackValue() do tego zwykle spowodują zwrócenie nowej serii .false
  • valuesPerDimensionLimit ogranicza liczbę unikatowych wartości na wymiar w podobny sposób.
  • restrictToUInt32Values określa, czy powinny być śledzone tylko wartości nieujemne.

Oto przykład wysyłania komunikatu w celu określenia, czy limity limitów zostały przekroczone:

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

Następne kroki