Thursday, June 28, 2018

D365 Application Insights – JavaScript

If you’ve implemented the sample integration for Application Insights you know that a small JavaScript file was provided that was to be included on any forms where you wanted logging. This little script downloads a big script and then by having this, all sorts of useful data is to be magically logged. On the previously linked page it shows the user name, a page/entity name of some sort, and a page view duration measuring in the seconds. I’m not quite sure where that data is coming from but I ended up with data that looked more like this.

No way to identify which form the data came from, no way to identify which user (user_id doesn’t tie back to anything), and the page view durations are all in the milliseconds.

The browser timing (page load times) metrics weren’t any better.


495 millisecond page loads? That never happened… not ever.

It’s not all bad. It does capture exceptions on the form (not that you can trace it back to where), it provides some interesting data on browser use, client location, etc.

It also doesn’t tell you that there is an existing SDK that you can use to log your own telemetry. This is where what I did comes in. I’ve packaged everything together, but ultimately you still end up using the same small initialization script (that defaults some options to off) which pulls down the larger script but then I’ve added a layer on top that adds a few features and fixes some of the previously mentioned problems.

I’ve built onto these telemetry types:
  • Trace
  • Event
  • Metric
    • Page load duration (custom metric implementation)
    • Method execution duration (custom metric implementation)
  • Dependency
  • Exception
  • PageView
For examples of setting up and using, see the GitHub site’s wiki page.
By default with each request it’s going to log the following D365/CRM specific data as custom dimensions:
  • User Id
  • Entity Name
  • Entity Id
  • Form type
  • Form name
  • Organization name
  • Organization version
  • Source (JavaScript)
  • + any other custom dimensions of your choosing
This is in addition to the normal items that are logged like the date/time of the event, browser info, etc. It’s using the ids rather than friendly names to reduce overhead a bit. This could easily be updated to pull the friendly name or else you can cross reference it back to D365/CRM later. Either way, you’ll still have more contextual information about the data you’ve logged.

When setting up on a form you’ll pass a JSON configuration string as a parameter to the setup function. It controls what types of items will be logged (example turn off tracing in production), percentages of event types to log (so maybe you only 25% of total page view times), & debug mode. Exceptions at the form level should still be logged (regardless of you catching them or not), page view times, and page load times will be logged without any interaction so long as they aren’t disabled. All the other items rely on the developer to call the specific logging function when needed.

My implementation of a page view should be a bit more accurate as it logging the total time spent on the page just as the user is closing the form. And how does this happen? As I learned, all modern browsers have the Beacon API which includes the sendBeacon method whos exact purpose is to do things like send telemetry just as the user is leaving the page. Of course Internet Explorer 11 doesn’t have this and it’s still a supported browser, in which can I had to resort to a bit of a hack by including a very short synchronous request in the page’s beforeunload event. Not really perceptible but still ugly. 

Now my page view time is showing around 41 seconds, that sounds a little more reasonable. Also shown here is the current user id as user_AuthenticatedId and also the default D365/CRM specific custom dimensions.


Page load time isn’t really anything special (other than being more accurate) as it’s just using the browser’s performance APIs to read what the browser records as opposed to trying to start a timer yourself which would never really be close to accurate anyway. I’m logging them a custom metric.

image

7.4 seconds sounds a little more accurate.

Logging traces, metrics, events, caught exceptions, dependencies, and method execution times are all pretty straight forward. Logging XMLHTTPRequest dependency times an be done with 1 line of code. Pass the request and whatever name you want to the tracking function and then you won’t need to worry about wrapping a timer around anything or handling the end times in both successful and error events. Examples for everything is on the wiki page.

All the code is on GitHub:
https://github.com/jlattimer/D365AppInsights.Js

I’ve packaged the source files for distribution so that you can either use it as is or make your own modifications. If you’re going to being doing the later, read the notes here and/or look at the gulp file in the source code to see how the files are being put together.

NuGet JavaScript/TypeScript source package:
https://www.nuget.org/packages/JLattimer.D365AppInsights.Js