Coleção de métricas personalizadas no .NET e no .NET CoreCustom metric collection in .NET and .NET Core

Os SDKs Azure Monitor Application Insights .NET e .NET Core têm dois métodos diferentes de coletar métricas personalizadas, TrackMetric() e GetMetric() .The Azure Monitor Application Insights .NET and .NET Core SDKs have two different methods of collecting custom metrics, TrackMetric(), and GetMetric(). A principal diferença entre esses dois métodos é a agregação local.The key difference between these two methods is local aggregation. TrackMetric()falta de pré-autenticação enquanto GetMetric() tem pré-autenticação.TrackMetric() lacks pre-aggregation while GetMetric() has pre-aggregation. A abordagem recomendada é usar a agregação, portanto, TrackMetric() não é mais o método preferencial para coletar métricas personalizadas.The recommended approach is to use aggregation, therefore, TrackMetric() is no longer the preferred method of collecting custom metrics. Este artigo explicará como usar o método getmetric () e algumas das razões por trás de como ele funciona.This article will walk you through using the GetMetric() method, and some of the rationale behind how it works.

TrackMetric versus getmetricTrackMetric versus GetMetric

TrackMetric()envia telemetria bruta, indicando uma métrica.TrackMetric() sends raw telemetry denoting a metric. Não é eficiente enviar um único item de telemetria para cada valor.It is inefficient to send a single telemetry item for each value. TrackMetric()também é ineficiente em termos de desempenho, já que cada TrackMetric(item) um passa pelo pipeline completo do SDK de inicializadores e processadores de telemetria.TrackMetric() is also inefficient in terms of performance since every TrackMetric(item) goes through the full SDK pipeline of telemetry initializers and processors. Ao contrário de TrackMetric() , GetMetric() o manipula a pré-autenticação local para você e envia apenas uma métrica de resumo agregada em um intervalo fixo de um minuto.Unlike TrackMetric(), GetMetric() handles local pre-aggregation for you and then only submits an aggregated summary metric at a fixed interval of one minute. Portanto, se você precisar monitorar com atenção alguma métrica personalizada no segundo ou até mesmo nível de milissegundos, poderá fazer isso enquanto apenas o custo do tráfego de rede e do armazenamento do monitoramento somente a cada minuto.So if you need to closely monitor some custom metric at the second or even millisecond level you can do so while only incurring the storage and network traffic cost of only monitoring every minute. Isso também reduz bastante o risco de que a limitação ocorra, já que o número total de itens de telemetria que precisam ser enviados para uma métrica agregada é muito reduzido.This also greatly reduces the risk of throttling occurring since the total number of telemetry items that need to be sent for an aggregated metric are greatly reduced.

Em Application Insights, as métricas personalizadas coletadas por meio do TrackMetric() e GetMetric() não estão sujeitas à amostragem.In Application Insights, custom metrics collected via TrackMetric() and GetMetric() are not subject to sampling. A amostragem de métricas importantes pode levar a cenários em que os alertas que você pode ter criado sobre essas métricas podem se tornar não confiáveis.Sampling important metrics can lead to scenarios where alerting you may have built around those metrics could become unreliable. Ao nunca fazer amostragem de suas métricas personalizadas, você geralmente pode ter certeza de que quando os limites de alerta forem violados, um alerta será acionado.By never sampling your custom metrics, you can generally be confident that when your alert thresholds are breached, an alert will fire. Mas como as métricas personalizadas não são amostradas, há algumas preocupações potenciais.But since custom metrics aren't sampled, there are some potential concerns.

Se você precisar controlar as tendências em uma métrica a cada segundo, ou em um intervalo ainda mais granular, isso poderá resultar em:If you need to track trends in a metric every second, or at an even more granular interval this can result in:

  • Aumento dos custos de armazenamento de dados.Increased data storage costs. Há um custo associado à quantidade de dados que você envia para Azure Monitor.There is a cost associated with how much data you send to Azure Monitor. (Quanto mais dados você enviar, maior será o custo geral do monitoramento.)(The more data you send the greater the overall cost of monitoring.)
  • Aumento do tráfego de rede/sobrecarga de desempenho.Increased network traffic/performance overhead. (Em alguns cenários, isso pode ter um custo monetário e de desempenho do aplicativo.)(In some scenarios this could have both a monetary and application performance cost.)
  • Risco de limitação de ingestão.Risk of ingestion throttling. (O serviço de Azure Monitor descarta os pontos de dados ("limitadores") quando seu aplicativo envia uma taxa muito alta de telemetria em um intervalo de tempo curto.)(The Azure Monitor service drops ("throttles") data points when your app sends a very high rate of telemetry in a short time interval.)

A limitação é uma preocupação específica que, como a amostragem, a limitação pode levar a alertas perdidos, pois a condição para disparar um alerta pode ocorrer localmente e, em seguida, ser descartada no ponto de extremidade de ingestão devido a excesso de dados sendo enviados.Throttling is of particular concern in that like sampling, throttling can lead to missed alerts since the condition to trigger an alert could occur locally and then be dropped at the ingestion endpoint due to too much data being sent. É por isso que, para .NET e .NET Core, não recomendamos usar TrackMetric() a menos que você tenha implementado sua própria lógica de agregação local.This is why for .NET and .NET Core we don't recommend using TrackMetric() unless you have implemented your own local aggregation logic. Se você estiver tentando rastrear todas as instâncias que um evento ocorre durante um determinado período de tempo, você pode achar TrackEvent() melhor se ajustar.If you are trying to track every instance an event occurs over a given time period, you may find that TrackEvent() is a better fit. Embora tenha em mente que, ao contrário das métricas personalizadas, os eventos personalizados estão sujeitos à amostragem.Though keep in mind that unlike custom metrics, custom events are subject to sampling. É claro que você ainda pode usar TrackMetric() mesmo sem escrever sua própria pré-autenticação local, mas se você fizer isso, fique atento às armadilhas.You can of course still use TrackMetric() even without writing your own local pre-aggregation, but if you do so be aware of the pitfalls.

No resumo GetMetric() , é a abordagem recomendada, já que ela faz a agregação, acumula valores de todas as chamadas Track () e envia um resumo/agregação a cada minuto.In summary GetMetric() is the recommended approach since it does pre-aggregation, it accumulates values from all the Track() calls and sends a summary/aggregate once every minute. Isso pode reduzir significativamente o custo e a sobrecarga de desempenho enviando menos pontos de dados e, ao mesmo tempo, coletando todas as informações relevantes.This can significantly reduce the cost and performance overhead by sending fewer data points, while still collecting all relevant information.

Observação

Somente os SDKs .NET e .NET Core têm um método getmetric ().Only the .NET and .NET Core SDKs have a GetMetric() method. Se você estiver usando o Java, poderá usar as métricas micrometer ou TrackMetric() .If you are using Java you can use Micrometer metrics or TrackMetric(). Para Python, você pode usar OpenCensus. stats para enviar métricas personalizadas.For Python you can use OpenCensus.stats to send custom metrics. Para JavaScript e Node.js você ainda usaria TrackMetric() , mas tenha em mente as advertências que foram descritas na seção anterior.For JavaScript and Node.js you would still use TrackMetric(), but keep in mind the caveats that were outlined in the previous section.

Introdução ao getmetricGetting started with GetMetric

Para nossos exemplos, vamos usar um aplicativo básico do serviço de trabalho do .NET Core 3,1.For our examples, we are going to use a basic .NET Core 3.1 worker service application. Se você quiser replicar exatamente o ambiente de teste que foi usado com esses exemplos, siga as etapas 1-6 do artigo do serviço de trabalho de monitoramento para adicionar Application insights a um modelo de projeto de serviço de trabalho básico.If you would like to exactly replicate the test environment that was used with these examples, follow steps 1-6 of the monitoring worker service article to add Application Insights to a basic worker service project template. Esses conceitos se aplicam a qualquer aplicativo geral em que o SDK possa ser usado, incluindo aplicativos Web e aplicativos de console.These concepts apply to any general application where the SDK can be used including web apps and console apps.

Enviando métricasSending metrics

Substitua o conteúdo do worker.cs arquivo pelo seguinte:Replace the contents of your worker.cs file with the following:

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

Se você executar o código acima e observar a telemetria sendo enviada por meio da janela de saída do Visual Studio ou de uma ferramenta como o Fiddler de Telerik, você verá o loop while executando repetidamente sem nenhuma telemetria sendo enviada e um único item de telemetria será enviado por toda a marca 60-Second, que, no caso de nosso teste, terá a seguinte aparência :If you run the code above and watch the telemetry being sent via the Visual Studio output window or a tool like Telerik's Fiddler, you will see the while loop repeatedly executing with no telemetry being sent and then a single telemetry item will be sent by around the 60-second mark, which in the case of our test looks as follows:

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

Este item de telemetria única representa uma agregação de 41 medidas de métricas distintas.This single telemetry item represents an aggregate of 41 distinct metric measurements. Como estávamos enviando o mesmo valor repetidamente, temos um desvio padrão (DESVPAD) de 0 com valores máximos (máximos) e mínimos ( mínimos) idênticos.Since we were sending the same value over and over again we have a standard deviation (stDev) of 0 with an identical maximum (max), and minimum (min) values. A propriedade Value representa uma soma de todos os valores individuais que foram agregados.The value property represents a sum of all the individual values that were aggregated.

Se examinarmos nosso recurso de Application Insights na experiência de logs (análise), esse item de telemetria individual será semelhante ao seguinte:If we examine our Application Insights resource in the Logs (Analytics) experience, this individual telemetry item would look as follows:

Log Analytics exibição de consulta

Observação

Enquanto o item de telemetria bruta não continha um campo/Propriedade Sum explícita depois de ser ingerido, criamos um para você.While the raw telemetry item did not contain an explicit sum property/field once ingested we create one for you. Nesse caso value , as propriedades e valueSum representam a mesma coisa.In this case both the value and valueSum property represent the same thing.

Você também pode acessar a telemetria de métrica personalizada na seção métricas do Portal.You can also access your custom metric telemetry in the Metrics section of the portal. Como uma métrica baseada em log e personalizada.As both a log-based, and custom metric. (A captura de tela abaixo é um exemplo de baseado em log.) Exibição do Metrics Explorer(The screenshot below is an example of log-based.) Metrics explorer view

Referência de métrica de cache para uso de alta taxa de transferênciaCaching metric reference for high-throughput usage

Em alguns casos, os valores de métrica são observados com muita frequência.In some cases metric values are observed very frequently. Por exemplo, um serviço de alta taxa de transferência que processa 500 solicitações/segundo pode querer emitir 20 métricas de telemetria para cada solicitação.For example, a high-throughput service that processes 500 requests/second may want to emit 20 telemetry metrics for each request. Isso significa controlar 10.000 valores por segundo.This means tracking 10,000 values per second. Nesses cenários de alta taxa de transferência, os usuários podem precisar ajudar o SDK, evitando algumas pesquisas.In such high-throughput scenarios, users may need to help the SDK by avoiding some lookups.

Por exemplo, nesse caso, o exemplo acima realizou uma pesquisa para um identificador para a métrica "ComputersSold" e, em seguida, rastreou um valor observado 42.For example, in this case, the example above performed a lookup for a handle for the metric "ComputersSold" and then tracked an observed value 42. Em vez disso, o identificador pode ser armazenado em cache para várias invocações de faixa:Instead, the handle may be cached for multiple track invocations:

//...

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

Além de armazenar em cache o identificador de métrica, o exemplo acima também reduziu o Task.Delay de 50 milissegundos para que o loop fosse executado com mais frequência, resultando em TrackValue() invocações de 772.In addition to caching the metric handle, the example above also reduced the Task.Delay to 50 milliseconds so that the loop would execute more frequently resulting in 772 TrackValue() invocations.

Métricas multidimensionaisMulti-dimensional metrics

Os exemplos na seção anterior mostram métricas de dimensionalidade zero.The examples in the previous section show zero-dimensional metrics. As métricas também podem ser multidimensionais.Metrics can also be multi-dimensional. Atualmente, damos suporte a até 10 dimensões.We currently support up to 10 dimensions.

Aqui está um exemplo de como criar uma métrica unidimensional:Here is an example of how to create a one-dimensional metric:

//...

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

A execução desse código por pelo menos 60 segundos resultará na envio de três itens de telemetria distintos para o Azure, cada um representando a agregação de um dos três fatores forma.Running this code for at least 60 seconds will result in three distinct telemetry items being sent to Azure, each representing the aggregation of one of the three form factors. Como antes, você pode examiná-los na exibição de logs (análise):As before you can examine these in Logs (Analytics) view:

Exibição do log Analytics de métrica multidimensional

Bem como na experiência do Metrics Explorer:As well as in the Metrics explorer experience:

Métricas personalizadas

No entanto, você observará que não é possível dividir a métrica pela sua nova dimensão personalizada ou exibir sua dimensão personalizada com a exibição de métricas:However, you will notice that you aren't able to split the metric by your new custom dimension, or view your custom dimension with the metrics view:

Divisão de suporte

Por padrão, as métricas multidimensionais dentro da experiência do Gerenciador de métricas não são ativadas no Application Insights recursos.By default multi-dimensional metrics within the Metric explorer experience are not turned on in Application Insights resources.

Habilitar métricas multidimensionaisEnable multi-dimensional metrics

Para habilitar métricas multidimensionais para um recurso Application insights, selecione uso e custos estimados > métricas personalizadas > habilitar alertas em dimensões de métricas personalizadas > OK.To enable multi-dimensional metrics for an Application Insights resource, Select Usage and estimated costs > Custom Metrics > Enable alerting on custom metric dimensions > OK. Mais detalhes sobre isso podem ser encontrados aqui.More details about this can be found here.

Depois de fazer essa alteração e enviar a nova telemetria multidimensional, você poderá aplicar a divisão.Once you have made that change and send new multi-dimensional telemetry, you will be able to Apply splitting.

Observação

Somente as métricas enviadas recentemente depois que o recurso foi ativado no portal terão dimensões armazenadas.Only newly sent metrics after the feature was turned on in the portal will have dimensions stored.

Aplicar a separação

E exiba suas agregações de métrica para cada dimensão FormFactor :And view your metric aggregations for each FormFactor dimension:

Fatores forma

Como usar o MetricIdentifier quando há mais de três dimensõesHow to use MetricIdentifier when there are more than three dimensions

No momento, há suporte para 10 dimensões, mais de três dimensões requer o uso de MetricIdentifier :Currently 10 dimensions are supported however, greater than three dimensions requires the use of 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");

Configuração de métrica personalizadaCustom metric configuration

Se você quiser alterar a configuração de métrica, será necessário fazer isso no local em que a métrica é inicializada.If you want to alter the metric configuration, you need to do this in the place where the metric is initialized.

Nomes de dimensão especiaisSpecial dimension names

As métricas não usam o contexto de telemetria do TelemetryClient usado para acessá-las, os nomes de dimensão especiais disponíveis como constantes na MetricDimensionNames classe são a melhor solução para essa limitação.Metrics do not use the telemetry context of the TelemetryClient used to access them, special dimension names available as constants in MetricDimensionNames class is the best workaround for this limitation.

Agregações de métricas enviadas pelo "tamanho de solicitação de operação especial"-a métrica não terá seu Context.Operation.Name conjunto para "operação especial".Metric aggregates sent by the below "Special Operation Request Size"-metric will not have their Context.Operation.Name set to "Special Operation". Enquanto TrackMetric() ou qualquer outro TrackXXX () terá OperationName definido corretamente como "operação especial".Whereas TrackMetric() or any other TrackXXX() will have OperationName set correctly to "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);
                //...
            }
                   
        }

Nessa circunstância, use os nomes de dimensão especiais listados na MetricDimensionNames classe para especificar TelemetryContext valores.In this circumstance, use the special dimension names listed in the MetricDimensionNames class in order to specify TelemetryContext values.

Por exemplo, quando a agregação de métrica resultante da próxima instrução for enviada para o Application Insights ponto de extremidade de nuvem, seu Context.Operation.Name campo de dados será definido como "operação especial":For example, when the metric aggregate resulting from the next statement is sent to the Application Insights cloud endpoint, its Context.Operation.Name data field will be set to "Special Operation":

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

Os valores dessa dimensão especial serão copiados para o TelemetryContext e não serão usados como uma dimensão ' normal '.The values of this special dimension will be copied into the TelemetryContext and will not be used as a 'normal' dimension. Se você também quiser manter uma dimensão de operação para exploração de métrica normal, você precisará criar uma dimensão separada para essa finalidade:If you want to also keep an operation dimension for normal metric exploration, you need to create a separate dimension for that purpose:

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

Dimensão e limitação da série temporalDimension and time-series capping

Para impedir que o subsistema de telemetria use acidentalmente seus recursos, você pode controlar o número máximo de séries de dados por métrica.To prevent the telemetry subsystem from accidentally using up your resources, you can control the maximum number of data series per metric. Os limites padrão não são mais do que 1000 séries de dados totais por métrica e não mais que 100 valores diferentes por dimensão.The default limits are no more than 1000 total data series per metric, and no more than 100 different values per dimension.

No contexto de dimensão e Time Series capping, usamos Metric.TrackValue(..) para garantir que os limites sejam observados.In the context of dimension and time series capping we use Metric.TrackValue(..) to make sure that the limits are observed. Se os limites já forem atingidos, Metric.TrackValue(..) o retornará "false" e o valor não será acompanhado.If the limits are already reached, Metric.TrackValue(..) will return "False" and the value will not be tracked. Caso contrário, ele retornará "true".Otherwise it will return "True". Isso será útil se os dados de uma métrica se originarem da entrada do usuário.This is useful if the data for a metric originates from user input.

O MetricConfiguration Construtor obtém algumas opções sobre como gerenciar diferentes séries dentro da respectiva métrica e um objeto de uma classe que implementa IMetricSeriesConfiguration que especifica o comportamento de agregação para cada série individual da métrica:The MetricConfiguration constructor takes some options on how to manage different series within the respective metric and an object of a class implementing IMetricSeriesConfiguration that specifies aggregation behavior for each individual series of the metric:

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é o número máximo de séries de tempo de dados que uma métrica pode conter.seriesCountLimit is the max number of data time series a metric can contain. Quando esse limite for atingido, o chamará TrackValue() .Once this limit is reached, calls to TrackValue().
  • valuesPerDimensionLimitlimita o número de valores distintos por dimensão de maneira semelhante.valuesPerDimensionLimit limits the number of distinct values per dimension in a similar manner.
  • restrictToUInt32ValuesDetermina se apenas valores inteiros não negativos devem ser controlados.restrictToUInt32Values determines whether or not only non-negative integer values should be tracked.

Aqui está um exemplo de como enviar uma mensagem para saber se os limites de Cap são excedidos:Here is an example of how to send a message to know if cap limits are exceeded:

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

Próximas etapasNext steps