Thursday, July 5, 2018

D365 Application Insights – Plug-ins & Custom Workflows

Not too many people were probably using Application Insights directly in plug-ins and custom workflow steps since it was introduced because every example I ever saw was writing using set a set of assemblies to making interfacing with the service easy (much like we do with D365). Of course awhile back I tried to ILMerge those assemblies into a plug-in but needless to say that didn’t work. I know a few instances where individuals had the logging proxied through something like an Azure Function which I’m sure worked perfectly well but then also took on the extra dependency (and cost) of whatever was doing the relaying. Luckily now we can avoid doing all that because we’ve now established there is a REST API and we can call it from just about anywhere.

I put a wrapper around it using C# so that you can easily include it plug-ins and workflow code. It’s ready to use right away but of course it can be modified as you see fit.
I’ve built in these telemetry types:
  • Trace
  • Event
  • Metric
  • Dependency
  • Exception
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:
  • ExecutionContext
    • InitiatingUserId
    • ImpersonatingUserId
    • CorrelationId
    • Message
    • Mode
    • Depth
    • InputParameters
    • OutputParameters
    • Stage (plug-in)
    • WorkflowCategory (workflow)
    • PrimaryEntityName
    • PrimaryEntityId
    • OrganizationName
  • Organization version
  • Source (Plug-in or Workflow)
This is in addition to the normal items that are logged like the date/time of the event, originating location (datacenter city & state), etc.. Again 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.

Logging traces, metrics, events, caught exceptions, and dependencies are all pretty straight forward. Examples for everything is on the wiki page.

The constructor of the logger will need a configuration passed to it in terms of an object or a JSON string so you’ll need to have a way to get that information into your code by using the plug-ins configurations, workflow inputs, etc. You can control the types of telemetry logged, percentages of the events to log, or to enable and disable context tracking.

Besides context values if you so choose, nothing logged will be automatic. You’ll need to incorporate the Application Insights logger into your own exception handling and performance tracking.

The other important point to bring up is the actual duration it takes to log something. On average from D365 Online it was taking ~700ms to get a response back that the item was accepted. Doesn’t sound like much but if your plug-in is already busy, this isn’t going to help. The first way to mitigate that is to only log a percentage of “normal”, non-exception events. This was one of the driving factors to build in the functionality right away. That operates at a broad level across the logging instance and telemetry type. You can always add it your own filters to reduce the number of normal results. For example if you are logging the duration it takes to call an external web service and it normally take 50ms to complete, wrap the logging statement in something that checks to see if it exceeds 65ms before sending data. The other way to create a custom action which runs asynchronously so you have more of a fire-and-forget approach. This will run in a fraction of the time it takes when you are waiting for a response. If you don’t feel like creating your own I’ve done so already here so you can just install the solution.

All the code is on GitHub:

I’ve packaged the source files for distribution so that you can either use it as is or make your own modifications.

NuGet C# source package: