Sdílet prostřednictvím


Přepsání vzorkování – Azure Monitor Application Insights pro Javu

Poznámka:

Funkce přepsání vzorkování je ve verzi GA počínaje verzí 3.5.0.

Přepsání vzorkování umožňuje přepsat výchozí procento vzorkování, například:

  • Nastavte procento vzorkování na 0 (nebo nějakou malou hodnotu) pro hlučné kontroly stavu.
  • Pro volání hlučné závislosti nastavte procento vzorkování na 0 (nebo na určitou malou hodnotu).
  • Nastavte procento vzorkování na 100 pro důležitý typ požadavku (například /login) i když máte výchozí vzorkování nakonfigurované na něco nižšího.

Terminologie

Než se dozvíte o přepsání vzorkování, měli byste porozumět rozsahu termínů. Rozsah je obecný termín pro:

  • Příchozí požadavek.
  • Odchozí závislost (například vzdálené volání do jiné služby).
  • Závislost v procesu (například práce provedená dílčími součástmi služby)

Pro přepsání vzorkování jsou tyto součásti rozsahu důležité:

  • Atributy

Atributy span představují standardní i vlastní vlastnosti daného požadavku nebo závislosti.

Začínáme

Začněte vytvořením konfiguračního souboru s názvem applicationinsights.json. Uložte ho do stejného adresáře jako applicationinsights-agent-*.jar. Použijte následující šablonu.

{
  "connectionString": "...",
  "sampling": {
    "percentage": 10,
    "overrides": [
      {
        "telemetryType": "request",
        "attributes": [
          ...
        ],
        "percentage": 0
      },
      {
        "telemetryType": "request",
        "attributes": [
          ...
        ],
        "percentage": 100
      }
    ]
  }
}

Jak to funguje

telemetryType(telemetryKind v Application Insights 3.4.0) musí být jedna z request, , dependencytrace (protokol) nebo exception.

Po spuštění rozsahu se typ rozsahu a atributy, které jsou na něm přítomné, použijí ke kontrole, jestli se některá z přepsání vzorkování neshoduje.

Shody mohou být buď strict nebo regexp. Porovnávání regulárních výrazů se provádí s celou hodnotou atributu, takže pokud chcete shodovat s hodnotou, která obsahuje abc kdekoli v ní, je potřeba použít .*abc.*. Přepsání vzorkování může zadat více kritérií atributů, v takovém případě se musí všechny shodovat, aby se přepsání vzorkování shodovaly.

Pokud se některý z přepsání vzorkování shoduje, použije se jeho procento vzorkování k rozhodnutí, jestli chcete vzorkovat rozsah nebo ne.

Použije se pouze první přepsání vzorkování, které odpovídá.

Pokud se neshodují žádné přepsání vzorkování:

  • Pokud se jedná o první rozsah trasování, použije se konfigurace vzorkování nejvyšší úrovně.
  • Pokud není prvním rozsahem v trasování, použije se nadřazené rozhodnutí vzorkování.

Atributy spanu dostupné pro vzorkování

Atributy rozsahu OpenTelemetry se shromažďují automaticky a vycházejí z sémantických konvencí OpenTelemetry.

Můžete také přidat atributy span prostřednictvím kódu programu a použít je k vzorkování.

Poznámka:

Pokud chcete zobrazit přesnou sadu atributů zachycených v Javě Application Insights pro vaši aplikaci, nastavte úroveň samoobslužné diagnostiky na ladění a vyhledejte ladicí zprávy začínající textem "exporting span".

Poznámka:

Pro vzorkování jsou k dispozici pouze atributy nastavené na začátku rozsahu, takže atributy, jako http.response.status_code je doba trvání požadavku, které jsou zachyceny později, je možné filtrovat prostřednictvím rozšíření OpenTelemetry Java. Tady je ukázkové rozšíření, které filtruje rozsah na základě doby trvání požadavku.

Poznámka:

Atributy přidané s procesorem telemetrie nejsou k dispozici pro vzorkování.

Případy použití

Potlačení shromažďování telemetrie pro kontroly stavu

Tento příklad potlačí shromažďování telemetrie pro všechny požadavky na /health-checks.

Tento příklad také potlačí shromažďování všech podřízených rozsahů (závislostí), které by se normálně shromáždily v rámci /health-checks.

{
  "connectionString": "...",
  "sampling": {
    "overrides": [
      {
        "telemetryType": "request",
        "attributes": [
          {
            "key": "url.path",
            "value": "/health-check",
            "matchType": "strict"
          }
        ],
        "percentage": 0
      }
    ]
  }
}

Potlačení shromažďování telemetrie pro hlučné volání závislostí

Tento příklad potlačí shromažďování telemetrie pro všechna GET my-noisy-key volání 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
      }
    ]
  }
}

Shromažďování 100 % telemetrie pro důležitý typ požadavku

Tento příklad shromažďuje 100 % telemetrie pro /login.

Vzhledem k tomu, že podřízené rozsahy (závislosti) respektují rozhodnutí nadřazeného vzorkování (chybí veškeré přepsání vzorkování pro toto podřízené rozpětí), shromažďují se také pro všechny požadavky typu /login.

{
  "connectionString": "...",
  "sampling": {
    "percentage": 10
  },
  "sampling": {
    "overrides": [
      {
        "telemetryType": "request",
        "attributes": [
          {
            "key": "url.path",
            "value": "/login",
            "matchType": "strict"
          }
        ],
        "percentage": 100
      }
    ]
  }
}

Zveřejnění atributů span pro potlačení volání závislostí SQL

Tento příklad vás provede hledáním dostupných atributů, které potlačí hlučná volání SQL. Následující dotaz znázorňuje různá volání SQL a související počty záznamů za posledních 30 dnů:

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

Z výše uvedených výsledků lze pozorovat, že všechny operace sdílejí stejnou hodnotu v data poli: DECLARE @MyVar varbinary(20); SET @MyVar = CONVERT(VARBINARY(20), 'Hello World');SET CONTEXT_INFO @MyVar;. Společný vztah mezi všemi těmito záznamy je vhodným kandidátem pro přepsání vzorkování.

Nastavením samoobslužné diagnostiky pro ladění se ve výstupu zobrazí následující položky protokolu:

2023-10-26 15:48:25.407-04:00 DEBUG c.m.a.a.i.exporter.AgentSpanExporter - exporting span: SpanData{spanContext=ImmutableSpanContext...

Oblast zájmu z těchto protokolů je oddíl "atributy":

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

Pomocí takového výstupu můžete nakonfigurovat přepsání vzorkování podobné tomu, které bude filtrovat naše hlučná volání SQL:

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

Po použití změn nám následující dotaz umožňuje určit čas posledního ingestování těchto závislostí do 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 

Potlačení shromažďování telemetrie pro protokol

Pomocí SL4J můžete přidat atributy protokolu:

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

Potom můžete odebrat protokol s přidaným atributem:

{
  "sampling": {
    "overrides": [
      {
        "telemetryType": "trace",
        "percentage": 0,
        "attributes": [
          {
            "key": "key",
            "value": "value",
            "matchType": "strict"
          }
        ]
      }
    ]
  }
}

Potlačení shromažďování telemetrie pro metodu Java

Do metody Java přidáme rozsah a odebereme ho s přepsání vzorkováním.

Nejprve přidáme opentelemetry-instrumentation-annotations závislost:

    <dependency>
      <groupId>io.opentelemetry.instrumentation</groupId>
      <artifactId>opentelemetry-instrumentation-annotations</artifactId>
    </dependency>

Teď můžeme přidat poznámku WithSpan do metody Java, která spouští požadavky 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
	}

Následující konfigurace přepsání vzorkování umožňuje odebrat rozsah přidaný poznámkou WithSpan :

  "sampling": {
    "overrides": [
      {
        "telemetryType": "dependency",
        "attributes": [
          {
            "key": "code.function",
            "value": "findPaginated",
            "matchType": "strict"
          }
        ],
        "percentage": 0
      }
    ]
  }

Hodnota atributu je název metody Java.

Tato konfigurace odebere všechna telemetrická data vytvořená z findPaginated metody. Závislosti SQL nebudou vytvořeny pro spouštění SQL pocházející z findPaginated metody.

Následující konfigurace odebere všechna telemetrická data vygenerovaná z metod VetController třídy, které mají WithSpan anotaci:

 "sampling": {
    "overrides": [
      {
        "telemetryType": "dependency",
        "attributes": [
          {
            "key": "code.namespace",
            "value": "org.springframework.samples.petclinic.vet.VetController",
            "matchType": "strict"
          }
        ],
        "percentage": 0
      }
    ]
  }

Řešení problému

Pokud použijete regexp a přepsání vzorkování nefunguje, zkuste použít .* regulární výraz. Pokud teď vzorkování funguje, znamená to, že máte problém s prvním regulárním výrazem a přečtěte si tuto dokumentaci k regulárnímu výrazu.

Pokud nefunguje .*, může se stát, že máte ve své application-insights.json filesyntaxi problém se syntaxí. Prohlédněte si protokoly Application Insights a podívejte se, jestli si všimnete upozornění.