D365 Custom Log

Share this:

You can log information in Dynamics 365 for Finance and Operations in several different ways. However, it can be very helpful in some cases to have a specific D365 custom log table and form to provide detailed information on complex processes. A custom log is able to store multiple specific pieces of information in ways that other logging methods cannot do as well.

Example Use Cases

For example, integrations often require the system to validate and process a large amount of information for every transaction that comes into D365.

In these cases, having a D365 custom log with records that are tied to the transaction, have a message, and are easily visible can be extremely helpful in resolving issues across many records.

Certainly, use D365 infolog messages to start. However, oftentimes, these are not helpful enough.

Unlike just a message or a database log, a custom log table can store relevant values from the process along with a message. To explain, the custom log table can store the unique transaction ID in a separate field, allowing it to be joined and displayed in a workbench form when the transaction is selected.

In cases where a batch job only prints out messages, there could be thousands of messages. In theory, each transaction would start with a message saying:

info(strfmt("Begining transaction %1.", transactionID));

Then, all messages afterward would relate to this transaction. However, it would take some time even to find the start of the transaction you are looking for.

Having a D365 custom log table where messages, values, and created dates can all be combined is very helpful in some scenarios.

Create A Custom Log Table

First, create a new table to store the D365 custom log records. For this example, call the table customLog.

Second, add a string field named ‘Message‘. Then, set the Extended Data Type to ‘LongDescription‘. This field stores any messages we send to the log.

Third, add an int64 field named ‘LogRefRecId‘. Then, set the Extended Data Type to ‘RefRecId‘. This field stores the RecId of the related record that the log is about.

Fourth, in the Properties of the table, set the ‘CreatedDateTime‘ property to true. This will allow the log messages to be sorted by the order they were inserted later on.

Finally, add all of the fields that you have created to a new field group named ‘All‘. (You may not have all the fields shown created yet. That is fine).

Create A Helper Method

After creating the table, create a method on the table that will help developers use the D365 custom log table.

The method will take the message and the relevant record and insert a record.

    public static void log(LongDescription _message, RefRecId _refRecId)
    {
        customLog customLog;
        customLog.Message = _message;
        customLog.LogRefRecId = _refRecId;

        customLog.insert(); 
    }

Create A Workbench Form

To demonstrate this example, we need to create several other objects. For this example, create a workbench form that shows both the transaction information and the log messages related to the transaction. For your use case, modify these steps to match your needs.

First, create a new table named TransactionTable, and add a new string field named TransactionID.

Next, ensure the ‘synchronize database on build‘ project property is set to true.

Then, build the solution to ensure the table synchronizes with the database.

Second, create a new form named ‘TransactionTable‘ and add the TransactionTable and CustomLog table to the Data Sources node.

Join The Log Table To The Transaction Table

Next, right-click the ‘CustomLog‘ datasource, select properties, and set the Join Source property to the other table, ‘TransactionTable‘ in this case.

Additionally, set the ‘Allow Create,’ ‘Allow Delete,’ ‘Allow Edit, ‘Insert at End,’ and the ‘Insert If Empty‘ properties all to No. To explain, no person should modify or add additional logging records.

Third, go back to the CustomLog table and create a new relation.

Then, right-click the relation table and select New>Normal to add a new relationship between the two tables.

In the properties window, set the Field to ‘LogRefRecId‘ and the Related Field to ‘RecId‘.

Add Grids To The Form

Fourth, back on the TransactionTable form designer, right click on the set the ‘Design pattern‘ to ‘Simple Details w/Standard Tabs‘.

Next, add an ActionPane and Tab control to the form design.

Then, add two ‘Tab Page’ nodes onto the ‘Tab’ control.

In the properties, set the Caption property to ‘Transaction‘ for the first Tab Page, and ‘Logs‘ for the second Tab Page.

Next, right-click on each Tab Page, and select Apply Pattern>Fields and Field Groups.

Fifth, add a grid control to each Tab Page Control.

Then, drag the TransactionID field from the TransactionTable data source onto the first Tab Page control, and the ‘All‘ field group from the CustomLog data source onto the second Tab Page Control.

Create A Menu Item

Sixth, create a new display menu item for the TransactionTable form.

Then, set the Label to ‘Transaction workbench‘ and the Object property to the name of the form, ‘TransactionTable‘.

Seventh, add the menu item to an existing Menu. For demonstration purposes, add the Accounts Receivable menu extension to your project, then add your new display menu item to that menu.

Now that the workbench form has been created, we can move on to showing how using a D365 custom log would work.

Add Logging To The Process

Next, add code to add D365 custom log messages when the main process runs.

First, to simulate this, add a button group, then a button control, to the TransactionTable form’s Action Pane. Then, set the Text property to ‘Process‘.

Second, override the clicked method.

Second, add the following code inside the clicked method. Specifically, pass a message into the first parameter and the RecId of the record that is being processed into the second parameter.

CustomLog::log(strfmt("Starting to process transaction ID %1", TransactionTable.TransactionId), TransactionTable.RecId);

TransactionTable_ds.reread();
TransactionTable_ds.refresh();
CustomLog_ds.executeQuery();

Importantly, the calls to refresh, reread, and executequery methods ensures that the form shows the newly inserted log records after they have been inserted. Without these calls, users must click the ‘refresh’ button or reload their browser to see the new records.

Now, compile your solution.

Demonstration

Finally, try out the D365 custom log table functionality.

First, navigate to your workbench. In my case, it is found here: Accounts Receivable>Tranaction>transaction workbench.

Second, click the ‘Edit‘ button and enter a value into the field transaction ID in the grid. For this scenario, pretend that an entire transaction record has been created in Dynamics 365 for Finance Operations as part of an integration.

Third, click the ‘Process‘ button to simulate the system running a process, where the D365 custom log will be inserted.

Fourth, click on the Logs tab and notice the record shown in the grid. The message includes the transaction ID as expected.

Fifth, go back to the Transaction tab, click the New button, enter in a new unique Transaction ID value, click the ‘Process‘ button again, then go back to the Logs tab.

Notice that the log record shown only relates to the transaction record selected on the first tab. If we were to insert many messages, only the relevant ones relevant to that process would show in this grid.

Optionally, you can prove to yourself that the log table still includes all of the records by using the table browser to view all of the records. To do this, replace the URL text with ‘&mi=SysTableBrowser&tablename=CustomLog‘. For example:

https://<replace with your environment URL>/?cmp=USRT&mi=SysTableBrowser&tablename=CustomLog

Show The Messages

In addition to saving log messages to a D365 custom log table, you may also want to show the messages. That way, the user can see the messages immediately, or if the process is running in batch, review the messages there as well.

To do this, add another log method in the CustomLog table:

    public static void logAndShow(LongDescription _message, RefRecId _refRecId, boolean _info = true)
    {
        customLog customLog;
        customLog.Message = _message;
        customLog.LogRefRecId = _refRecId;

        if (_info)
        {
            info(customLog.Message);
        }

        customLog.insert(); 
    }

By setting the default value of the third parameter to true, all logged messages will be shown as an info message to the user. But if you do not wish to have the messages shown, pass the value ‘false‘ to the third parameter.

Next, add a second button to the workbench form with the Text property ‘Process and show‘.

Then, override the clicked method and add the following code to call the new method.

Finally, compile the solution, click on the ‘Process and show‘ button, and verify the info message shown on the screen.

Conclusion

In conclusion, Microsoft provides several forms of logging, including the infolog, database logging, and trace parser. However, there are times when the ability to store specific messages and sortable values relating to a process is very helpful. For transactions and processes that occur in large volumes and often have issues that can be very different, D365 custom logging will drastically improve the speed to resolution.

Peter Ramer
Peter Ramer is a part of the Managed Application Services team at RSM working on Microsoft Dynamics 365. He focuses on the Retail and Commerce industries. When he is not solving problems and finding ways to accelerate his clients' business, he enjoys time with his three kids and amazing wife.

Share this:

Leave a Reply

Your email address will not be published. Required fields are marked *

Proudly powered by WordPress | Theme: Baskerville 2 by Anders Noren.

Up ↑