Filtrování "klientských" telemetrií v Application Insights
Tento článek byl napsán v roce 2017. Vývojářské technologie se neustále inovují a článek již nemusí popisovat aktuální stav technologie, ideální řešení a můj současný pohled na dané téma.
Čas od času se může vývojář dostat do situace, kdy telemetrie sbírané JS kódem a odesílané do služby Application Insights jsou zcela zbytečné nebo neodráží realitu. Příkladem může být problém prohlašování AJAX závislostí jako failed v případě, kdy AJAX požadavek explicitně zruší přímo klient (například jQuery). V tomto článku nastíním, jak tento problém vyřešit snadno pomocí filtrů.
Problém z praxe
Pokud máme vykreslenou HTML stránku, na které se nachází kompletní měřící kód Application Insights, automaticky tak sbíráme telemetrie typu PageViews i Dependencies. PageViews vznikají explicitně voláním appInsights.trackPageView();
a dependencies jsou odhalovány interním mechanismem. Typická dependency telemetrie vznikne například když jQuery odešle Post/Get požadavek na server. Pokud je toto volání úspěšné (server jej vyřeší s návratovým kódem 200), je taková telemetrie označena jako success = true. Pokud by došlo k výjimce na serveru a vrátila se například chyba 500, pak je závislost označena jako success = false.
Výše uvedené demo popisuje nicméně speciální případ, kdy jQuery (nebo nějaký JS framework) odešle na server požadavek, který následně zruší, aniž by měl server čas jej dořešit. V praxi se tak může stát například u různých našeptávačů a vyhledávátek. Uživatel chce najít určitý produkt a tak píše do vyhledávání název produktu. Než server stihne najít a vrátit odpovídající produkty, uživatel přidává další písmena a JS framework je nucen původní requesty abortovat.
Takto abortované requesty jsou reprezentovány dependency telemetrií s vlastností success = false a jejich status kód (resultCode) je typicky 0.
Filtrování telemetrií
Dobrá zpráva je, že před odesláním telemetrií do Azure je možné na každou z nich sáhnout a buď ji zcela zahodit nebo i upravit. Není tak problém handlovat telemetrie, které mají výše uvedenou signaturu a prohlásit je například za úspěšné (protože ono defacto k žádné chybě nedošlo). Jako bonus si lze k telemetriím i připojit dodatečnou vlastnost, aby bylo možné tyto případy snadněji dohledat.
<script type="text/javascript"> var appInsights = window.appInsights || function (config) { function i(config) { t[config] = function () { var i = arguments; t.queue.push(function () { t[config].apply(t, i) }) } } var t = { config: config }, u = document, e = window, o = "script", s = "AuthenticatedUserContext", h = "start", c = "stop", l = "Track", a = l + "Event", v = l + "Page", y = u.createElement(o), r, f; y.src = config.url || "https://az416426.vo.msecnd.net/scripts/a/ai.0.js"; u.getElementsByTagName(o)[0].parentNode.appendChild(y); try { t.cookie = u.cookie } catch (p) { } for (t.queue = [], t.version = "1.0", r = ["Event", "Exception", "Metric", "PageView", "Trace", "Dependency"]; r.length;)i("track" + r.pop()); return i("set" + s), i("clear" + s), i(h + a), i(c + a), i(h + v), i(c + v), i("flush"), config.disableExceptionTracking || (r = "onerror", i("_" + r), f = e[r], e[r] = function (config, i, u, e, o) { var s = f && f(config, i, u, e, o); return s !== !0 && t["_" + r](config, i, u, e, o), s }), t }({ instrumentationKey: "a27c1cd2-3a02-4406-ae10-01c89da5b349" }); window.appInsights = appInsights; // Přidání inicializeru appInsights.queue.push(function () { appInsights.context.addTelemetryInitializer(function (envelope) { var telemetryItem = envelope.data.baseData; if (telemetryItem.type === "Ajax" && (telemetryItem.resultCode === "0" || telemetryItem.resultCode === "-1")) { telemetryItem.success = true; telemetryItem.properties = telemetryItem.properties || {}; telemetryItem.properties["isAbortedOnClientSide"] = true; } }); }); // Konec přidání inicializeru appInsights.trackPageView(); </script>
Příklad výše ukazuje, jak lze definovat vlastní inicializer. Tento inicializer přečte vlastnosti telemetrie a pokud se jedná o typ Ajax s resultCode 0 nebo -1, pak proběhne úprava takové telemetrie. Nejprve je prohlášena za úspěšnou pomocí příkazu telemetryItem.success = true
a následně je k ni připojena vlastnost isAbortedOnClientSide, která bude následně dohledatelná v Azure portálu.
Další bádání
Pokud vás filtrování telemetrií v JavaScriptu zaujalo, doporučuji probádat i zbytek Application Insights SDK na stránce GitHubu, kde je celá řada zajímavých příkladů.