Miroslav Holec
Premium

Filtrování "klientských" telemetrií v Application Insights

Miroslav Holec   15. června 2017

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.

Aborted request

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.

Azure portal telemetry ajax

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ů.