Custom Code Tracing & Exception Logging in Dynamics 365 v.9

October 28, 2018

no comments

As a Solution Architect I often review Microsoft Dynamics 365 custom server and client side code.
One of the most common rejects regards tracing and exception handling mechanisms, or their absence. Some code constructs may have empty Try/Catch blocks or none at all, other catch exceptions and just re-throw. As for tracing, code often contains debugging ‘aids’ such as alerts and debugger statements or no tracing notifications at all.

Why is this a reject?

  • Unhandled raw exceptions float to UI, confusing and frustrating users while exposing internal implementation details to potential attackers
  • System Administrator is unaware of custom code exceptions unless users decide to report an error message or a bug
  • Tracing mechanism help diagnose faults and sometimes allow resolving without debugging or recompiling code

Microsoft Dynamics 365 contains a Plug-in Trace repository which contains trace and exception entries originating from Plug-in and Custom Workflow Activity components.
While this is a good built in solution, it has some drawbacks:

  • It does not support common types of custom code such as client side JavaScript and external components consuming Microsoft Dynamics API directly
  • There is no straight forward method to filter Plug-in Trace notification to search for specific text in trace/exception messages
  • No option to trigger a notification to system administrator once an exception is logged
  • No option to accurately correlate a user reported error message to a specific exception entry

In this post I would like to suggest an updated implementation of a more wholesome infrastructure for tracing and exceptions logging. Using this  infrastructure, any developer can easily log trace entries and exceptions from any custom code interacting with Microsoft Dynamics 365 application, while admins can easily monitor the application health in that aspect.


Why using this infrastructure?

  • Easily log trace entries and exceptions from any client and server side custom code interacting with Microsoft Dynamics 365 application in a unified manner
  • You can add processes triggered by exception Log record creation to alert system administrator regarding a fault as it occurs
  • Easily search and filter specific exceptions/trace records according to unique Reference Token provided by users/clients using Quick/Advanced Find

In the following How To Use section you can download a un/managed solution and follow setup and usage instructions.  You can view the GitHub project here.

How to use

  1. Download and import solution

    You can download a managed solution here.
    If you want to make any changes to this solution, download the un-managed version. In that case, open the solution, navigate to the Log entity and check ‘Settings’ to display the entity in the settings area. Finally, publish the solution.

    open the solution, navigate to the Log entity and check ‘Settings’ to display the entity in the settings area

  2. Using in an entity form JavaScript code

    Add the dyn_utils.js Web Resource to the target entity form libraries collection.
    Call the LogTrace and LogException functions in your custom code.

    Add the dyn_utils.js Web Resource to the target entity form Libraries collection

        //perform some business logic including tracing and exception handling 
        ns.DoSomeBusinessLogic = function () {
            //define verbose trace entry
            var traceEntry = {
                "title": "loggingSample.DoSomeBusinessLogic",
                "description": "Start execution",
                //related business record id 
                "relatedBusinessRecordId": "2514FC63-9E58-4D1E-8226-69256D0197E3",
                //related business record URL
                "relatedBusinessRecordURL": "",
                //set current user id as related user id 
                "relatedUserId": getContext().userSettings.userId
            //trace function execution start asynchronously
            Utils.LogTrace(traceEntry, true, SuccessHandler, FailureHandler);
            try {
                //some business logic including some exception 
            catch (err) {
                //define verbose exception entry
                var exceptionEntry = {
                    "title": "loggingSample.DoSomeBusinessLogic",
                    "description": Constants.MSG_GENERAL_FAILURE,
                    //related business record id 
                    "errorMessage": err.message,
                    //related business record URL
                    "stackTrace": err.stack
                //log exception and return reference token
                var referenceToken = Utils.LogException(exceptionEntry, false);
                //notify user with a reference token to report back to admin
                alert(Constants.MSG_GENERAL_FAILURE + referenceToken);
            finally {
                //define thin trace entry 
                var traceEntry = {
                    "title": "loggingSample.DoSomeBusinessLogic",
                    "description": "Start execution",
                //trace function exectuion end asynchronously
                Utils.LogTrace(traceEntry, true, SuccessHandler, FailureHandler);    
  3. Using in Web Resource JavaScript code

    You can view the code in action by launching the dyn_loggingSample.htm Web Resource (replace organization base address)

    You can view the code in action by launching the dyn_loggingSample.htm Web

    Make sure you include the dyn_utils.js as a referenced resource:

        <meta charset="utf-8" />
        <title>Logging Sample</title>
        <script src="ClientGlobalContext.js.aspx" type="text/javascript"></script>
        <script src=""></script>
        <script src="dyn_utils.js"></script>
        <script src="dyn_loggingSample.js"></script>

    The sample code in the dyn_loggingSample.js demonstrates tracing and exception handling, same as in the code sample above.

  4. Using in Plug-in/Custom Workflow Activity/external SDK client

    The following code sample represents usage in Plug-in and is similar to CWA and external SDK client usage:

        public class LogTraceAndException : IPlugin
            public void Execute(IServiceProvider serviceProvider)
                // Obtain the execution context from the service provider
                IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
                // Get a reference to the organization service
                IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                IOrganizationService organizationService = factory.CreateOrganizationService(context.UserId);
                //define a trace entry, all attributes are optional except title 
                Log traceEntry1 = new Log
                    title = "ServerSideLogging: Execute",
                    description = "Execution end",
                    //replace user id with an valid one
                    relatedUser = new EntityReference("systemuser", 
                    relatedBusinessRecordURL = "",
                //log trace entry, get reference token back 
                string refToken1 = GenericLogging.Log(traceEntry1, 
                    GenericLogging.LogType.Trace, organizationService);
                    //some exception raising code.
                    //If transaction is rolled back, Log entries will persist
                    throw new Exception("An error occurred, please notify the System Administrator");
                catch (Exception ex)
                    //define an exception entry 
                    Log excptionEntry = new Log
                        title = "ServerSideLogging: Execute",
                        errorMessage = ex.Message,
                        stackTrace = ex.StackTrace
                    //log exception entry, get reference token back
                    string refToken2 = GenericLogging.Log(excptionEntry,
                    throw new InvalidPluginExecutionException(
                        string.Format("An error occurred, please notify the System Administrator. Reference token: {0}", 

    A resulting exception raised from the Plug-in code includes the reference token. Once reported to an Admin, he can easily find the relevant Log entry using Quick Find

    A resulting exception includes the reference token

    Once reported to an Admin, he can easily find the relevant Log entry using Quick Find

    View Log details

Implementation Notes

I have written about the subject in the past and the described approach has not changed much. The implementation has been updated to leverage version 9 features (currently available on for Online implementations)

What has changed since last version:

  • Using Action definition to activate, deactivate and control logging level
  • Using built-in auto-numbering attribute to generate reference token, so a designated CWA component is no longer required
  • Optional usage of client side asynchronous logging operation to keep UX uninterrupted

In order to support logging from transactional components (such as Plugin registered to pre/post operation stages), the Log method in GenericLogging.cs file is using the ExecuteMultipleRequest class to execute the dyn_Log request.
As the ExecuteMultipleRequest instance is external to the Plugin transaction, it manages to create a Log record without the Plugin transaction rolling it back.
Using the Execute method directly with the dyn_LogRequest request instead, would have executed the Log Action, but the created Exception record would have been deleted by the Plugin transaction rollback, leaving no trace.

Custom Trace & Exception Logging diagram


Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>