Recopilación de métricas personalizadas en .NET y .NET Core
Los SDK de Application Insights de Azure Monitor para .NET y .NET Core tienen dos métodos diferentes para recopilar métricas personalizadas: TrackMetric()
y GetMetric()
. La diferencia principal entre estos dos métodos es la agregación local. El método TrackMetric()
carece de agregación previa. El método GetMetric()
tiene una agregación previa. Se recomienda usar la agregación, por lo que TrackMetric()
ya no es el método preferido para recopilar métricas personalizadas. En este artículo se le guiará por el uso del método GetMetric()
y parte de la lógica en la que se basa su funcionamiento.
Precaución
Recomendamos la Distribución de OpenTelemetry de Azure Monitor para que las nuevas aplicaciones o clientes alimenten Azure Monitor Application Insights. La Distribución de OpenTelemetry de Azure Monitor ofrece una funcionalidad y una experiencia similares a las del SDK de Application Insights. Es posible migrar desde el SDK de Application Insights usando las guías de migración para .NET, Node.js, y Python, pero todavía estamos trabajando para agregar unas pocas características más para la compatibilidad con versiones anteriores.
API de agregación previa frente a la de sin agregación previa
El método TrackMetric()
envía datos de telemetría sin procesar que denotan una métrica. No es eficaz enviar un elemento de telemetría único para cada valor. El método TrackMetric()
también es ineficaz en términos de rendimiento porque cada TrackMetric(item)
pasa a través de la canalización del SDK de inicializadores y procesadores de telemetría.
A diferencia de TrackMetric()
, GetMetric()
controla la agregación local por usted y, a continuación, solo envía una métrica de resumen agregada a un intervalo fijo de un minuto. Si necesita supervisar de cerca algunas métricas personalizadas en el nivel de segundos o incluso en el de milisegundos, puede hacerlo y además solo se incurre en el costo de almacenamiento y tráfico de red de la supervisión en cada minuto. Este comportamiento también reduce en gran medida el riesgo de que se produzca una limitación, ya que se reduce considerablemente el número total de elementos de telemetría que se deben enviar para una métrica agregada.
En Application Insights, las métricas personalizadas recopiladas mediante TrackMetric()
y GetMetric()
no están sujetas a muestreo. El muestreo de métricas importantes puede dar lugar a escenarios en los que las alertas que se podrían haber creado en torno a esas métricas resulten poco confiables. Si nunca se realiza el muestreo de las métricas personalizadas, normalmente puede estar seguro de que se activará una alerta cuando se infrinjan los umbrales de alerta. Dado que no se muestrean las métricas personalizadas, existen algunas posibles preocupaciones.
El seguimiento de las tendencias de una métrica cada segundo o en un intervalo aún más granular puede dar lugar a:
- Aumento de los costos de almacenamiento de datos. Hay un costo asociado con la cantidad de datos que se envían a Azure Monitor. Cuantos más datos envíe, mayor será el costo total de la supervisión.
- Aumento del tráfico de red o sobrecarga del rendimiento. En algunos escenarios esta sobrecarga podría tener un costo monetario y de rendimiento de la aplicación.
- Riesgo de limitación de la ingesta de datos. Azure Monitor descarta ["limita"] puntos de datos cuando la aplicación envía un número elevado de datos de telemetría en un intervalo de tiempo corto.
La limitación es un problema, ya que puede provocar la pérdida de alertas. La condición para desencadenar una alerta puede producirse localmente y, con posterioridad, anularse en el punto de conexión de ingesta debido a que se envían demasiados datos. No se recomienda usar TrackMetric()
para .NET y .NET Core a menos que haya implementado su propia lógica de agregación local. Si intenta realizar un seguimiento de cada instancia en la que se produce un evento durante un período de tiempo determinado, es posible que sea mejor opción TrackEvent()
. Tenga en cuenta que, a diferencia de las métricas personalizadas, los eventos personalizados están sujetos a muestreo. Todavía puede usar TrackMetric()
incluso sin escribir su propia agregación local. Pero si lo hace, tenga en cuenta los problemas.
En resumen, se recomienda GetMetric()
porque realiza la agregación previa, acumula valores de todas las llamadas Track()
y envía un resumen o agregado una vez cada minuto. El método GetMetric()
puede reducir significativamente los costos y la sobrecarga de rendimiento, ya que envía menos puntos de datos, pero recopila toda la información pertinente.
Nota
Solo los SDK de .NET y .NET Core tienen el método GetMetric()
. Si usa Java, consulte Cómo enviar métricas personalizadas mediante Micrometer. Para JavaScript y Node.js puede utilizar TrackMetric()
, pero tenga en cuenta las advertencias que se han descrito en la sección anterior. En el caso de Python, puede usar OpenCensus.stats para enviar métricas personalizadas, pero la implementación de las métricas es diferente.
Introducción a GetMetric
En los ejemplos, vamos a usar una aplicación básica de servicio de trabajo de .NET Core 3.1. Si quiere replicar el entorno de prueba utilizado con estos ejemplos, siga los pasos 1 a 6 del Artículo sobre supervisión del servicio de trabajo. En estos pasos se agrega Application Insights a una plantilla de proyecto de servicio de trabajo básica. Estos conceptos se aplican a cualquier aplicación general en la que se pueda usar el SDK, incluidas las aplicaciones web y las aplicaciones de consola.
Envío de métricas
Reemplace el contenido del archivo worker.cs
por el siguiente código:
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);
}
}
}
}
Al ejecutar el código de ejemplo, verá que el bucle while
se ejecuta repetidamente sin que se envíen datos de telemetría en la ventana de salida de Visual Studio. Un único elemento de telemetría se envía alrededor de la marca de 60 segundos, que en nuestra prueba tiene el siguiente aspecto:
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 único elemento de telemetría representa un agregado de 41 medidas de métricas distintas. Dado que se envía el mismo valor una y otra vez, tenemos una desviación estándar (stDev
) de 0
con valores idénticos de máximo (max
) y mínimo (min
). La propiedad value
representa la suma de todos los valores individuales que se agregaron.
Nota
El método GetMetric
no admite el seguimiento del último valor (por ejemplo, gauge
) o el seguimiento de histogramas o distribuciones.
Si examinamos el recurso de Application Insights en la experiencia de Registros (Analytics), el elemento de telemetría individual tendrá un aspecto al de la siguiente captura de pantalla.
Nota
Aunque el elemento de telemetría sin procesar no contenía una propiedad ni campo de suma explícitos, creamos uno automáticamente para usted. En este caso, las propiedades value
y valueSum
representan lo mismo.
También puede acceder a la telemetría de métricas personalizada en la sección Métricas del portal como métricas basadas en registros y personalizadas. La captura de pantalla siguiente es un ejemplo de una métrica basada en registros.
Almacenamiento en caché de referencias de métricas para uso de alto rendimiento
Los valores de métricas se podrían observar con frecuencia en algunos casos. Por ejemplo, un servicio de alto rendimiento que procesa 500 solicitudes por segundo podría querer emitir 20 métricas de datos de telemetría por cada solicitud. El resultado significa un seguimiento de 10 000 valores por segundo. En dichos escenarios de alto rendimiento, es posible que los usuarios necesiten ayudar al SDK evitando algunas búsquedas.
Por ejemplo, en el ejemplo anterior se realizó una búsqueda de un manipulador de la métrica ComputersSold
y, a continuación, se supervisó un valor observado de 42
. En su lugar, el manipulador se podría almacenar en caché para las invocaciones de varios seguimientos:
//...
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);
}
}
Además de almacenar en caché el manipulador de la métrica, en el ejemplo anterior también se redujo Task.Delay
a 50 milisegundos para que el bucle se ejecute con más frecuencia. El resultado es 772 TrackValue()
invocaciones.
Métricas multidimensionales
Los ejemplos de la sección anterior muestran métricas de dimensión cero. Las métricas también pueden ser multidimensionales. Actualmente se admiten hasta 10 dimensiones.
Este es un ejemplo de cómo crear una métrica de una dimensión:
//...
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);
}
}
La ejecución del código de ejemplo durante al menos 60 segundos da como resultado el envío de tres elementos de telemetría distintos a Azure. Cada elemento representa la agregación de uno de los tres factores de forma. Como antes, puede examinarlos en mayor profundidad en la vista de Registros (Analytics).
En el explorador de métricas:
Tenga en cuenta que no puede dividir la métrica por su nueva dimensión personalizada ni ver su dimensión personalizada con la vista de métricas.
De manera predeterminada, las métricas multidimensionales dentro del explorador de métricas no están activadas en recursos de Application Insights.
Habilitar métricas multidimensionales
Para habilitar las métricas multidimensionales para un recurso de Application Insights, seleccione Uso y costos estimados>Métricas personalizadas>Habilitar la creación de alertas sobre las dimensiones de las métricas personalizadas>Aceptar. Para obtener más información, consulte dimensiones de métricas personalizadas y de agregación previa.
Una vez realizado ese cambio y enviado la nueva telemetría multidimensional, puede seleccionar Aplicar división.
Nota
Solo se almacenarán las dimensiones de las métricas enviadas después de activar la característica en el portal.
Vea las agregaciones de métricas para cada dimensión FormFactor
.
Uso de MetricIdentifier cuando hay más de tres dimensiones
Actualmente, se admiten 10 dimensiones. Más de tres dimensiones requieren el uso de 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");
Configuración de métricas personalizadas
Si quiere modificar la configuración de la métrica, debe realizar las modificaciones donde se inicializa la métrica.
Nombres de dimensión especiales
Las métricas no usan el contexto de telemetría del TelemetryClient
usado para acceder a ellas. La mejor solución a esta limitación es utilizar nombres de dimensiones especiales disponibles como constantes en la clase MetricDimensionNames
.
Los agregados de métrica enviados por la siguiente Special Operation Request Size
métrica no tendrán Context.Operation.Name
establecido en Special Operation
. El método TrackMetric()
o cualquier otro TrackXXX()
método se habrá OperationName
establecido correctamente en 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);
//...
}
}
En este caso, use los nombres de dimensión especiales que aparecen en la clase MetricDimensionNames
para especificar los valores de TelemetryContext
.
Por ejemplo, cuando el agregado de métricas resultante de la siguiente instrucción se envía al punto de conexión en la nube de Application Insights, el campo de datos Context.Operation.Name
estará establecido en Special Operation
:
_telemetryClient.GetMetric("Request Size", MetricDimensionNames.TelemetryContext.Operation.Name).TrackValue(requestSize, "Special Operation");
Los valores de esta dimensión especial se copiarán en TelemetryContext
y no se utilizarán como una dimensión normal. Si también desea mantener una dimensión de operación para la exploración normal de métricas, debe crear una dimensión independiente para ese propósito:
_telemetryClient.GetMetric("Request Size", "Operation Name", MetricDimensionNames.TelemetryContext.Operation.Name).TrackValue(requestSize, "Special Operation", "Special Operation");
Límites de las dimensiones y las series temporales
Para evitar que el subsistema de telemetría agote accidentalmente los recursos, puede controlar el número máximo de series de datos por métrica. Los límites predeterminados son no más de 1,000 series de datos totales por métrica y no más de 100 valores diferentes por dimensión.
Importante
Use valores cardinales bajos para las dimensiones a fin de evitar la limitación.
En el contexto de los límites de dimensiones y series temporales, utilice Metric.TrackValue(..)
para asegurarse de que se observan los límites. Si se han alcanzado los límites, Metric.TrackValue(..)
devolverá False
y no se supervisará el valor. En caso contrario, devuelve True
. Este comportamiento resulta útil si los datos de una métrica se originan a partir de la entrada de usuario.
El constructor MetricConfiguration
toma algunas opciones para administrar series diferentes dentro de la métrica respectiva y un objeto de una clase que implementa IMetricSeriesConfiguration
, que especifica el comportamiento de agregación para cada serie individual de la métrica:
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
es el número máximo de series temporales de datos que puede contener una métrica. Una vez alcanzado este límite, las llamadas aTrackValue()
que normalmente generarían una nueva serie devolveránfalse
.valuesPerDimensionLimit
limita el número de valores distintos por dimensión de forma similar.restrictToUInt32Values
determina si solo se debe realizar el seguimiento de los valores enteros no negativos.
Este es un ejemplo de cómo enviar un mensaje para saber si se han superado los límites:
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);
}
Pasos siguientes
- Métricas - Obtener - API de REST
- API de Application Insights para eventos y métricas personalizados
- Más información sobre la supervisión de aplicaciones de servicio de trabajo.
- Use métricas basadas en registros y agregación previa.
- Analice las métricas con el explorador de métricas.
- Cómo habilitar Application Insights para Aplicaciones ASP.NET Core.
- Cómo habilitar Application Insights para aplicaciones ASP.NET.