Aplikační monitoring bez proprietárních SDK v aplikaci

Stále se potkávám se snahou řešit potřebu dohledu aplikace infrastrukturními prostředky. Je vám tohle povědomé?

  • Posbíraná telemetrie zahrnuje CPU, IO, obsazenost paměti, ale neměří pořádně chování aplikačních komponent (requesty, chyby, cache miss, časy zpracování různých volání, délku fronty)
  • Pokud už jsou centralizované logy, jde o výstupy posbírané z obrazovky (stdout/stderr) nebo logovacího souboru a jsou ukládány jako řetězec - struktura vlastně neexistuje, parsuje se to špatně (napíšete geniální regex, ale spousta logů mu nevyhovuje a neprojde sítem) nebo vůbec, některé zprávy jsou víceřádkové a objevují se jako samostatné záznamy (což dělá jejich použití značně obtížné)
  • Pokud pouze určitá část aplikace dělá problémy, vůbec netušíte proč - máte všechnu telemetrii a logy, ale nevíte jak spolu souvisí.
    • Vidíte z auditu SQL dotazy, které běží dlouho - ale jaké tlačítko v aplikaci ovlivňují? Jakou skupinu uživatelů to zasahuje?
    • Odhalíte vysokou zátěž CPU u jedné ze služeb, ale jaké komponenty ji v tu chvíli volají?
    • Aplikace byla včera v 15:00 prokazatelně pomalá, ale žádná infrastrukturní komponenta neukazuje přetížené CPU. Bylo to díky pomalé reakci databáze? Nebo nějaké z mikroslužeb? Nebo se komunikace mezi službami ztrácela a bylo nutné ji opakovat?
  • Máte kontejnery, mikroslužby a plachtíte poslepu a říkáte si, že tady vás zachrání jen service mesh. Ještě chytřejší a složitější infrastruktura přece povede k cíli. (pozn.: service mesh není špatně, ale monitoring není dobrý hlavní důvod … jestli chcete masivně kanárkovat, šifrovat, vstřikovat chaos nebo mít circuit breakery, fajn - ale to je jiné téma)

Skutečně aplikační monitoring, často uváděné důvody proč ne a jejich řešení

Řešením je samozřejmě monitoring na úrovni aplikace, protože tam se dozvíme opravdu nejvíc. Ale pak očekávám následující dvě obvyklé námitky:

  • My aplikace pouze provozujeme, nejsme jejich vývojáři. Náš dodavatel by nám do kódu musel potřebná SDK dát. Buď si za to řekne moc peněz (často vidím u komerčních firem) nebo to nechce, protože bychom mu pak opravdu viděli pod ruce a věděli co se děje (univerzální vytváření závislosti, k nalezení všude) nebo to není součást podepsané smlouvy (dost typické ve státní správě aneb dodáváme “na klíč” a po dvou letech výběrovek je přesně napsáno, co v tom krásném šelmostroji bude … no a instrumentace pro monitoring tam jaksi není zmíněna, takže není a nebude).
  • Nechci nebo nemůžu do své aplikace přidávat SDK nějakého komerčního software, to by byl lockin. Milé Azure Monitor (Application Insights), Dynatrace, Datadog, New Relic i AWS X-Ray, odneste si svá SDK, nemáme zájem - my jsme open.

Zařazení instrumentace bez změny kódu (codeless attach)

Nutnost změnit kód je, jak už jsem vlastně psal, často brzdou nasazení aplikačního monitoringu. Neměla by být - vývoj software je přece k ničemu, když ho nejste schopni efektivně provozovat a to je zejména v éře mikroslužeb obtížné bez aplikačního monitoringu. Kolik vás stojí to, že raději nafouknete všechny zdroje na dvojnásobek (v cloudu se díky transparentnosti nákladů dá na tohle velmi dobře odpovědět)? Kolik vás stojí výpadky? Kolik naštvaný uživatel, kterému to jede pomalu? Investice do dobré provozovatelnosti by zkrátka měla být jedním ze zásadních nefunkčních požadavků na vývoj stejně jako třeba bezpečnost.

Ale zpět k tématu - někdy to prostě nejde nebo to nejde hned. V mnoha případech ale není nic ztraceno a je možné použít codeless attach neboli auto-instrumentation. Potřebné háčky do aplikace, které tuhle něco změří, odešlou, přidají hlavičku, se dají udělat i bez změny kódu. Monitorovací agent se napojí na proces v hostitelském serveru jako je Tomcat pro Javu nebo IIS pro .NET a automaticky rozezná použité frameworky a začne monitorovat. V případě Python se pak třeba aplikace spouští přes “zavaděč”, který aplikaci obohatí a tak podobně. Techniky jsou různé. U PaaS služeb jako je Azure App Service se to může stát přímo v platformě, u kontejnerové aplikace v Azure Kubernetes Service se to dá zařídit konceptem sidecar u aplikace a k tomu kolektor, v on-prem VM stačí pustit agenta jako další proces v JVM a tak podobně.

Skvělé - proč se tedy vůbec zabývat instrumentací přímo v kódu? Má codeless attach nějaké nevýhody?

  • Přidávat custom spany (pro tracing), vlastní atributy (například nejen “že volám” ale “proč volám” nebo “co dalšího bych měl o volání vědět”, třeba customerId, sessionId, orderId) nebo metriky je obtížné nebo spíše nemožné. Získáte tedy informace kdo koho jak volá přes standardní frameworky (Flask, Express, Requests, …), ale nebudete moci si přidat vlastní span nebo změnit jeho atributy (teď pouštím resizing obrázku, což je procedura uvnitř služby nebo obohatit data jako je “teď volám do SAPu a tohle je moje query”).
  • Logicky připojíte konkrétní platformu, ale trochu přicházíte o možnost využívat vícero různých exporterů. Tak například pokud vaše aplikace chce nabídnout custom metriky, můžete je přes exportér jednoduše pushnout do Azure Monitor nebo Datadog (třeba podle toho v kterém prostředí běží) pro celkový monitoring a analytiku a současně je automaticky vystavit pro pull pro Prometheus, přes který třeba jedete automatické škálování aplikace.
  • Instrumentace aplikace je závislá na použité platformě, takže v Kubernetes, v PaaS službě, ve VM, na edge třeba v Raspberry nebo Javascript běžící v browseru budete pokaždé potřebovat jiný způsob napojení a někde třeba ani k dispozici nebude. Pokud je instrumentace už součástí aplikace víte, že si ji můžete vzít s sebou doslova všude a její nasazení se zjednodušuje.

Standardizace instrumentace kódu

Na trhu je spousta proprietárních systémů (Azure Monitor, Dynatrace, Datadog, X-Ray+CloudWatch, New Relic), které řeší problém v celé své škále. K tomu si můžete poskládat řešení z open source, ale jako vždy každou komponentu řeší něco jiného a navíc jsou mezi nimi alternativy. Trasování dělá třeba Zipkin (s pochybnou governance projektu) a Jaeger (CNCF), metriky hezky sbírá Prometheus, logy kombinace Logstash nebo Fluentd a Elastic, vizualizace metrik Grafana, vizualizace Elastiku Kibana a tak podobně. Místo jednoho řešení s podporou máte volně integrované komponenty a spoustu práce. Často pak vídám nasazení monitoringu do stejného prostředí jako aplikaci a v okamžiku kdy prostředí z důvodu nějaké havárie zmizí (třeba přijdete o svůj Kubernetes cluster i s daty), je docela škoda, že už nikdy nezjistíte co se vlastně dělo. Mám učinit svůj kód specifický pro nějaký konkrétní systém? To je těžké rozhodování a naděje v open source mě nezachrání (viz Zipkin vs. Jaeger).

Pokusy o vytvoření standardizovaného open source způsobu instrumentace aplikace už nějakou dobu běží. Smyslem je vytvořit otevřené API a SDK, takže aplikaci je nutné obohatit pouze jednou a na ni si pak napojit systém dle vlastní volby. Můžu využít obrovské síly komerčních řešení s pokročilými funkcemi včetně umělé inteligence nebo si to pytlíkovat sám v open source (nebo se to rozhodnu v provozu neřešit, protože na to nejsou peníze a čas a vrátím se k tomu až po prvních pár nocích s problémem, který nechá aplikaci žít, ale dělá ji občas nepoužitelně pomalou a moje CPU metrika mi nepomohla a v logu sice nacházím error, ale nevím ke které transakci patří) a přitom můj kód se tím nemění. Bohužel i tady se objevily dva projekty se vzájemným překryvem - OpenCensus a OpenTracing. Naštěstí se oba projekty dohodly a spojily do jednoho většího - OpenTelemetry.

Svatá trojice aplikačního monitoringu

Výbornou kombinací pro aplikační monitoring je vidět jednotlivé události jako systém návazností (trasování), měřit aplikační metriky (metrics) a logovat co se aktuálně děje ať už špatného nebo dobrého, ale zásadního (logging).

Trasování (distributed tracing)

Kdo co zavolal, co se mu vrátilo, na co čekal a jak dlouho to trvalo? Jaký byl kontext toho volání, například na co se té databáze ptal a pro kterého uživatele? Distribuované trasování by mi mělo vytvořit orientovaný acyklický graf, nejčastěji graficky znázorněný jako časová osa událostí. Pokud se podaří kontext a korelační identifikátory předávat mezi systémy, měl by ideálem být stav, kdy v Angular kódu jedu od toho, že přihlášený uživatel Franta kliknul na tlačítko, to udělalo nějakou akci v browseru, která zavolala dvě backend API, ta následně provolala další, jednou se šlo přes frontu, tady je volání do databáze s tímto SELECTem a tady je volání nemonitorovaného externího systému (třeba SAP) a takhle dlouho mu trvala odpověď. Jasně - ne vždy se vyplatí takhle trasovat všechno, takže dává smysl nasadit nějaký sampling a tak podobně.

Díky trasování bych měl vidět svůj systém jako časovou osu pro akci uživatele a schápat tak co s čím a jak.

Měření (metrics)

Druhým důležitým aspektem pro mě budou různé čitače. Kromě obligátních infrastrukturních ukazatelů tady očekávám aplikační věci. Počet requestů na danou instanci, rychlosti odbavení, statistiky chyb, velikosti requestů, počet dokončených objednávek, počet odeslaných potvrzení na email, délka neodbavené fronty požadavků, počet současně řešených požadavků, cache hit vs. miss a tak podobně. Smyslem je schopnost identifikovat negativní trendy nebo anomálie jednotlivých komponent nebo aspektů systému a reagovat na ně ať už automatizovaně (například autoškálováním) nebo ručně (hmm, jak to, že to tak často není v cache, možná ji nějakou operací nevhodně proplachuju nebo ji neplním po restartu a dlouho se učí).

Logování (logging)

Jak se píše v New Yorksém metru - když něco (nedobrého) vidíš, řekni to. O téhle disciplíně není na rozdíl od trasování a aplikačních metrik nikde diskuse o vhodnosti takové investice, logování je zkrátka zažité. To, že by se sbíralo na soubor ve VM asi netřeba komentovat - zuřiví provozáci logující se vzdáleně do OS všech komponent pokulhávajícího systému ideálně pod rootem nejen, že nemají potřebnou rychlost, efektivitu a schopnost korelovat hlášky z různých součástek, ale jejich přístup je bezpečnostní i provozní riziko. Logování na Syslog server, aby se dalo odškrtnout, že to máme, ale logy jsou dobré tak akorát na to, aby se po havárii a odebraných bonusech dalo o víkendu pročítat co to teda vlastně způsobilo, také není ideální cesta. Nepochybně logy patří do centrálního systému s možností v nich efektivně vyhledávat v téměř reálném čase přes nějaký query jazyk včetně věcí jako je parsování, full text a složitější dotazy, joinování dat z různých systémů, vizualizace a reporting až po nějaké sofistikovanější kousky jako je autobasket či clustering (techniky strojového učení hledající podobnosti v hláškách nebo seskupování do kategorií podle obsahu - tak například hláška “brutální error na adrese 0x4a2bc6, restartuju se”, kde se adresa pokaždé mění je rozhodně lépe viditelná, když dostanu výstup typu 1000x byl brutální error s restartem, jen adresa se měnila).

Ideálem tady je schopnost obohatit hlášku v logu kontextem (korelačním id) z distribuovaného trasování. Pokud celá ta Frantova akce s tlačítkem nakonec skončila nějakou nepříjemnou výjimkou v kódu jednoho z backendů, bylo by fajn na té časově ose v tomto místě vidět červeně jak se tato služba obrací na záda odhaluje svůj backtrace.

OpenTelemetry

Výbornou odpovědí na instrumentaci aplikace standardizovaným způsobem je OpenTelemetry. Projekt je sice v beta fázi, ale to neznamená, že není ideální čas se s ním začít seznamovat notabene, když za ním stojí firmy jako je Google, Microsoft, Dynatrace, Uber a řada dalších. Příště se na projekt a specifikaci podíváme detailněji a začneme si ho i prakticky zkoušet, protože exporter do Azure Monitor Application Insights už je v betě.

A jak dnes řešíte aplikační monitoring vy?



Azure, Kubernetes, FinOps a strategie účtování nákladů Monitoring
Máte rádi Prometheus a Grafana pro váš Kubernetes? Jak na to všechno v plně managed formě v Azure? Monitoring
Nativní Azure Monitor a Microsoft Sentinel nově umí levnější logy a zabudovanou levnější archivaci - praxe (část 2) Monitoring
Nativní Azure Monitor a Microsoft Sentinel nově umí levnější logy a zabudovanou levnější archivaci - analýza nákladů (část 1) Monitoring
Prolevněte si Azure Sentinel s Fluent Bit, Blobem a Azure Data Explorer Monitoring