Invalidaciones de muestreo: Azure Monitor Application Insights para Java
Nota:
La característica de invalidaciones de muestreo está disponible con carácter general a partir de 3.5.0.
Las invalidaciones de muestreo permiten invalidar el porcentaje de muestreo predeterminado, por ejemplo:
- Establezca el porcentaje de muestreo en cero (o algún valor pequeño) para las comprobaciones de estado irrelevantes.
- Establezca el porcentaje de muestreo en cero (o algún valor pequeño) para las llamadas de dependencia irrelevantes.
- Establezca el porcentaje de muestreo en 100 para un tipo de solicitud importante (por ejemplo,
/login
) aunque tenga configurado el muestreo por defecto en algo inferior.
Terminología
Antes de obtener información sobre las invalidaciones de muestreo, debe comprender el término intervalo. Un intervalo es un término general para:
- Un solicitud entrante
- Una dependencia saliente (por ejemplo, una llamada remota a otro servicio)
- Una dependencia en proceso (por ejemplo, trabajo realizado por los subcomponentes del servicio)
En el caso de las invalidaciones de muestreo, estos componentes de intervalo son importantes:
- Atributos
Los atributos de intervalo representan tanto propiedades estándar como personalizadas de una determinada solicitud o dependencia.
Introducción
Para empezar, cree un archivo de configuración denominado applicationinsights.json. Guárdelo en el mismo directorio que applicationinsights-agent-*.jar. Use la siguiente plantilla.
{
"connectionString": "...",
"sampling": {
"percentage": 10,
"overrides": [
{
"telemetryType": "request",
"attributes": [
...
],
"percentage": 0
},
{
"telemetryType": "request",
"attributes": [
...
],
"percentage": 100
}
]
}
}
Funcionamiento
telemetryType
(telemetryKind
en Application Insights 3.4.0) debe ser uno de request
, dependency
, trace
(registro) o exception
.
Cuando se inicia un intervalo, el tipo de intervalo y los atributos presentes en él en ese momento se usan para comprobar si alguna de las invalidaciones de muestreo coinciden.
Las coincidencias pueden ser strict
o regexp
. Las coincidencias de expresiones regulares se realizan en todo el valor del atributo, por lo que si desea hacer coincidir un valor que contiene abc
en cualquier parte de él, debe usar .*abc.*
.
Una invalidación de muestreo puede especificar varios criterios de atributo, en cuyo caso todos deben coincidir para que coincida la invalidación de muestreo.
Si una de las invalidaciones de muestreo coincide, su porcentaje de muestreo se usa para decidir si se muestrea o no el intervalo.
Solo se utiliza la primera invalidación de muestreo que coincida.
Si no coincide ninguna invalidación de muestreo:
- Si es el primer intervalo del seguimiento, se usa la configuración de muestreo de nivel superior.
- No obstante, si no lo es, se utiliza la dirección de muestreo primaria.
Atributos de intervalo disponibles para el muestreo
Los atributos de intervalo de OpenTelemetry se recopilan automáticamente y se basan en las convenciones semánticas de OpenTelemetry.
También puede agregar atributos de intervalo mediante programación y usarlos para el muestreo.
Nota:
Para ver el conjunto exacto de atributos capturados por Java de Application Insights para la aplicación, establezca el nivel de autodiagnóstico en depuración y busque mensajes de depuración empezando por el texto "exporting span".
Nota:
Solo los atributos establecidos al principio del intervalo están disponibles para el muestreo, por lo que los atributos como http.response.status_code
o la duración de la solicitud que se capturan posteriormente se pueden filtrar a través de las extensiones de Java OpenTelemetry. Esta es una extensión de ejemplo que filtra los intervalos en función de la duración de la solicitud.
Nota:
Los atributos agregados con un procesador de telemetría no están disponibles para el muestreo.
Casos de uso
Eliminación de la recopilación de datos de telemetría en las comprobaciones del estado
Este ejemplo suprime la recolección de telemetría para todas las solicitudes a /health-checks
.
Este ejemplo también suprime la recolección de cualquier tramo descendente (dependencias) que normalmente se recogería bajo /health-checks
.
{
"connectionString": "...",
"sampling": {
"overrides": [
{
"telemetryType": "request",
"attributes": [
{
"key": "url.path",
"value": "/health-check",
"matchType": "strict"
}
],
"percentage": 0
}
]
}
}
Eliminación de la recopilación de telemetría para una llamada de dependencia ruidosa
Este ejemplo suprime la recolección de telemetría para todas las GET my-noisy-key
llamadas a redis.
{
"connectionString": "...",
"sampling": {
"overrides": [
{
"telemetryType": "dependency",
"attributes": [
{
"key": "db.system",
"value": "redis",
"matchType": "strict"
},
{
"key": "db.statement",
"value": "GET my-noisy-key",
"matchType": "strict"
}
],
"percentage": 0
}
]
}
}
Recopilación del 100 % de telemetría para un tipo de solicitud importante
Este ejemplo recolecta el 100 % de la telemetría para /login
.
Dado que los tramos descendentes (dependencias) respetan la decisión de muestreo de los padres (en ausencia de cualquier anulación de muestreo para ese tramo descendente), estos también se recolectan para todas las solicitudes "/login".
{
"connectionString": "...",
"sampling": {
"percentage": 10
},
"sampling": {
"overrides": [
{
"telemetryType": "request",
"attributes": [
{
"key": "url.path",
"value": "/login",
"matchType": "strict"
}
],
"percentage": 100
}
]
}
}
Exponer atributos de intervalo para eliminar llamadas de dependencia de SQL
En este ejemplo se explica la experiencia de búsqueda de atributos disponibles para suprimir llamadas SQL ruidosas. En la consulta siguiente se muestran las distintas llamadas SQL y los recuentos de registros asociados en los últimos 30 días:
dependencies
| where timestamp > ago(30d)
| where name == 'SQL: DB Query'
| summarize count() by name, operation_Name, data
| sort by count_ desc
SQL: DB Query POST /Order DECLARE @MyVar varbinary(20); SET @MyVar = CONVERT(VARBINARY(20), 'Hello World');SET CONTEXT_INFO @MyVar; 36712549
SQL: DB Query POST /Receipt DECLARE @MyVar varbinary(20); SET @MyVar = CONVERT(VARBINARY(20), 'Hello World');SET CONTEXT_INFO @MyVar; 2220248
SQL: DB Query POST /CheckOutForm DECLARE @MyVar varbinary(20); SET @MyVar = CONVERT(VARBINARY(20), 'Hello World');SET CONTEXT_INFO @MyVar; 554074
SQL: DB Query GET /ClientInfo DECLARE @MyVar varbinary(20); SET @MyVar = CONVERT(VARBINARY(20), 'Hello World');SET CONTEXT_INFO @MyVar; 37064
A partir de los resultados anteriores, se puede observar que todas las operaciones comparten el mismo valor en el data
campo: DECLARE @MyVar varbinary(20); SET @MyVar = CONVERT(VARBINARY(20), 'Hello World');SET CONTEXT_INFO @MyVar;
. La similitud entre todos estos registros lo convierte en un buen candidato para una invalidación de muestreo.
Al establecer el autodiagnóstico en Depurar, las siguientes entradas de registro su verán en la salida:
2023-10-26 15:48:25.407-04:00 DEBUG c.m.a.a.i.exporter.AgentSpanExporter - exporting span: SpanData{spanContext=ImmutableSpanContext...
El área de interés de esos registros es la sección "atributos":
{
"attributes": {
"data": {
"thread.name": "DefaultDatabaseBroadcastTransport: MessageReader thread",
"thread.id": 96,
"db.connection_string": "apache:",
"db.statement": "DECLARE @MyVar varbinary(20); SET @MyVar = CONVERT(VARBINARY(20), 'Hello World');SET CONTEXT_INFO @MyVar;",
"db.system": "other_sql",
"applicationinsights.internal.item_count": 1
}
}
}
Con esa salida, puede configurar una invalidación de muestreo similar a la siguiente que filtrará nuestras llamadas SQL irrelevantes:
{
"connectionString": "...",
"preview": {
"sampling": {
"overrides": [
{
"telemetryType": "dependency",
"attributes": [
{
"key": "db.statement",
"value": "DECLARE @MyVar varbinary(20); SET @MyVar = CONVERT(VARBINARY(20), 'Hello World');SET CONTEXT_INFO @MyVar;",
"matchType": "strict"
}
],
"percentage": 0
}
]
}
}
}
Una vez aplicados los cambios, la consulta siguiente nos permite determinar la última vez que estas dependencias se ingirieron en Application Insights:
dependencies
| where timestamp > ago(30d)
| where data contains 'DECLARE @MyVar'
| summarize max(timestamp) by data
| sort by max_timestamp desc
DECLARE @MyVar varbinary(20); SET @MyVar = CONVERT(VARBINARY(20), 'Hello World');SET CONTEXT_INFO @MyVar; 11/13/2023 8:52:41 PM
Eliminación de la recopilación de telemetría para el registro
Con SL4J puede agregar atributos de registro:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
public class MdcClass {
private static final Logger logger = LoggerFactory.getLogger(MdcClass.class);
void method {
MDC.put("key", "value");
try {
logger.info(...); // Application log to remove
finally {
MDC.remove("key"); // In a finally block in case an exception happens with logger.info
}
}
}
A continuación, puede quitar el registro que tiene el atributo agregado:
{
"sampling": {
"overrides": [
{
"telemetryType": "trace",
"percentage": 0,
"attributes": [
{
"key": "key",
"value": "value",
"matchType": "strict"
}
]
}
]
}
}
Eliminación de la recopilación de telemetría para un método de Java
Vamos a agregar un intervalo a un método de Java y quitar este intervalo con invalidación de muestreo.
Vamos a agregar primero la dependencia opentelemetry-instrumentation-annotations
:
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-instrumentation-annotations</artifactId>
</dependency>
Ahora podemos agregar la anotación WithSpan
a un método de Java que ejecuta solicitudes SQL:
package org.springframework.samples.petclinic.vet;
@Controller
class VetController {
private final VetRepository vetRepository;
public VetController(VetRepository vetRepository) {
this.vetRepository = vetRepository;
}
@GetMapping("/vets.html")
public String showVetList(@RequestParam(defaultValue = "1") int page, Model model) {
Vets vets = new Vets();
Page<Vet> paginated = findPaginated(page);
vets.getVetList().addAll(paginated.toList());
return addPaginationModel(page, paginated, model);
}
@WithSpan
private Page<Vet> findPaginated(int page) {
int pageSize = 5;
Pageable pageable = PageRequest.of(page - 1, pageSize);
return vetRepository.findAll(pageable); // Execution of SQL requests
}
La siguiente configuración de invalidación de muestreo permite quitar el intervalo agregado por la anotación WithSpan
:
"sampling": {
"overrides": [
{
"telemetryType": "dependency",
"attributes": [
{
"key": "code.function",
"value": "findPaginated",
"matchType": "strict"
}
],
"percentage": 0
}
]
}
El valor del atributo es el nombre del método Java.
Esta configuración quitará todos los datos de telemetría creados desde el método findPaginated
. Las dependencias de SQL no se crearán para las ejecuciones de SQL procedentes del método findPaginated
.
La siguiente configuración quitará todos los datos de telemetría emitidos a partir de métodos de la clase VetController
que tengan la anotación WithSpan
:
"sampling": {
"overrides": [
{
"telemetryType": "dependency",
"attributes": [
{
"key": "code.namespace",
"value": "org.springframework.samples.petclinic.vet.VetController",
"matchType": "strict"
}
],
"percentage": 0
}
]
}
Solución de problemas
Si utiliza regexp
y no funciona la anulación de muestreo, pruebe con la .*
regex. Si el muestreo ahora funciona, significa que tiene un problema con la primera regex y leer esta documentación regex.
Si no funciona con .*
, es posible que tenga un problema de sintaxis en application-insights.json file
. Revise los registros de Application Insights y compruebe si observa mensajes de advertencia.