Application Insights: Data for 'xxx' is at its daily cap

Pokud najdete v emailu zprávu "Data for 'xxx' is at its daily cap", znamená to, že Application Insights už nehodlají uchovávat další telemetrie v rámci zvoleného cenového plánu. V tuto chvíli existuje více obecných možností, jak se problému postavit (kromě toho, že prostě zaplatíme za vyšší cenový plán). V tomto článku budu popisovat řešení tohoto problému nad jednou z aplikací, které jsou provozovány v produkčním režimu.

V první řadě nechceme zcela ztratit přehled o tom, co se v aplikaci děje. Než se začneme vrtat v kódu, zachráníme situaci bez nutnosti zásahu do aplikačního kódu.

AI Přehled

Nastavení ingestion samplingu

Pokud mi zpráva přišla poprvé, nejrychlejší možností jak situaci dočasně uhasit je aktivovat Ingestion sampling přímo v portálu Azure. Tímto způsobem se zahodí některé "zbytečné" / redundantní telemetrie bez zkreslení metrik a agregací. Úroveň samplingu lze nastavit na základě počtu requestů proti webové aplikaci a času, kdy se překročil limit.

Mně přišla zpráva v 17 hodin, něco málo po špičce. Špičku si přitom odvozuji na základě metrik ve vybrané Azure WebApp (Pozor: Azure WebApp != App Service plan). Upozorňuji na rozdíl časů v dané lokalitě vs. ČR.

Traffic

V Application Insights jdu přes sekci Features + Pricing na Data volume Management až do Data sampling. Volím sampling na 50%, podle počtu requestů to musí bohatě stačit. Doplňme, že podobný typ samplingu by šel nastavit i na úrovni aplikačního kódu. Rozdíl by byl v tom, že zatímco pro ingestion sampling se telemetrie přenesou po síti a následně zahodí v Azure, v případě samplingu na úrovni SDK by se telemetrie vůbec neodeslaly.

Sampling

Analýza telemetrií

Problém je tedy uhasen. Teď se podívám, jaký typ telemetrií nejvíce chodí do Application Insights. Pohled lze získat na bladu Data volume management a graf si lze upravit dle potřeb. Po rozkliknutí je hned jasno:

Závislosti

Největší problém jsou Dependencies. Protože jejich množství je oproti ostatním telemetriím enormní (89%), budu řešit primárně Dependencies. Zajímá mě, o co přesně jde a zda vůbec potřebuji závislosti sledovat.

První velmi hrubou představu o závislostech získávám na bladu Search, kde si záměrně filtruji jen Dependencies za posledních 24 hodin.

Přehled volání závislostí

Tento vzorek se víceméně pořád opakuje. Hned mě napadá, jestli má smysl uchovávat závislosti – úspěšná volání do databáze. Pomocí filtru (stačí jen rozklikávat) si můžu udělat představu o charakteru telemetrií typu Dependency:

Úspěšná volání Doba řešení závislosti

Už tyto filtry mě vedou k myšlence, že bych mohl zcela zahodit telemetrie, které jsou úspěšné a odbavené do 300 ms. Takové závislosti mě nezajímají a vím, že je nikdy nevyšetřuji. Neúspěšné a dlouhotrvající závislosti si zatím můžu ponechat.

Telemetry processing

Abych si mohl jasněji vybrat telemetrie, které chci sbírat, potřebuji na úrovni kódu vytvořit tzv. Telemetry Processory, které každou telemetrii zanalyzují a zahodí v případě, že není zajímavá. V mém případě udělám pro tento účel jeden processor zaměřený na závislosti:

 public class DependencyTelemetryProcessor : ITelemetryProcessor
{
   private ITelemetryProcessor Next { get; set; }

   public DependencyTelemetryProcessor(ITelemetryProcessor next)
   {
       this.Next = next;
   } 

   public void Process(ITelemetry item)
   {
      if (IsNotInterestingTelemetry(item))
    {
           return;
     }

       this.Next.Process(item);
   }

   private bool IsNotInterestingTelemetry(ITelemetry item)
   {

      var dependency = item as DependencyTelemetry;
       if (dependency?.Success != null && dependency.Success.Value && dependency.Duration <= TimeSpan.FromMiliseconds(300))
     {
           return true;
   }

    return false;
   }
}

Procesor bude ignorovat telemetrie typu Dependency, které jsou úspěšné a jejichž doba trvání je menší nebo rovna 300 ms. Tyto telemetrie se vůbec nebudou odesílat.

Dále je nutné procesor zaregistrovat. Jde to buď v ApplicationInsights.config nebo přímo v kódu. Volím druhou možnost a v global.asax, kde si nastavuji instrumentační klíč doplňuji nový procesor:

 var builder = TelemetryConfiguration.Active.TelemetryProcessorChainBuilder;
builder.Use(next => new DependencyTelemetryProcessor(next));
builder.Build();

Podobným způsobem bych mohl udělat filtrování dalších typů telemetrií, které mě nezajímají. Osobně často filtruji:

  • syntetický provoz (různí roboti / crawlery)
  • požadavky na různé statické soubory (jpg, js, png, css) mimo těch důležitých
  • požadavky na neexistující stránky (obvykle není moc co vyšetřovat)
  • snahu o zobrazení stránek nepřihlášených uživatelů (tady je třeba být opatrnější)
  • úspěšné závislosti směrem do blob storage (absolutně nezajímavé)

Dále je užitečná praktika rozdělení telemetrií instrumentačním klíčem, nicméně tomuto tématu se budu věnovat v samostatném článku.

Závěr

V tomto článku jsme během analýzy objevili velké množství závislostí a řešení bylo celkem přímočaré. Jiný typ závislostí, se kterým se vývojář setká jsou Ajax calls, kde je situace velmi podobná. Vedle možnosti použití Ingestion Samplingu a Telemetry Processoru existují ještě další řešení, kterým se budu věnovat v navazujících článcích na jiných aplikacích z produkčního prostředí.

Miroslav Holec
22. února 2017