Debugging integration issues
Integration logging
Integration logging provides a summary of requests and responses for NexJ CRM channels that interact with a third-party application or process.
Integration logs are used by system administrators to validate processing times, identify performance issues, and troubleshoot reported errors for the external application or process. A system administrator also enables integration logging for the system or for a specific channel in NexJ System Admin Console.
You can modify exception and description information for integration logs, which are stored in the NJIntegrationLog table. You can also filter and display the logs on the Integration Log page in NexJ System Admin Console. By default, the description attribute is empty and only send and receive exceptions are automatically logged for outbound services. Exceptions are not logged if they occur after an outbound response is successfully received. Logging of these exceptions must be manually specified.
You configure logging of exceptions for an outbound service by passing exceptions either as a string or as an exception object. You configure logging of descriptions by modifying the description attribute in the service that is bound to the target channel.
You can also configure logging of a custom attribute by specifying the attribute in a subclass of the SysIntegrationLog
.
Configuring integration logging of exception and description attributes
You can configure integration logging of the exception and description attributes for an outbound service by modifying the outbound service in NexJ Studio.
To configure integration logging of exception and description attributes:
- In NexJ Studio, navigate to the Integration layer and select the Services tab.
- Create a new service or select and open an existing outbound service.
To configure logging of the exception attribute, in the Source tab, pass the exception as either as a string or as an exception object, as shown in the examples below.
Info
You must add the exception before the service terminates.
The following example shows how to pass an exception as a string.
SCHEME((SysIntegrationLog'senderEntry)'exception "Exception: collection of IDs returned when only one was expected" )
The following example shows how to pass an exception as an exception object.
((SysIntegrationLog'senderEntry)'exception exceptionObject)
Info
You do not need to enable exception logging for inbound services. Errors encountered by the inbound service are assigned the ERROR log level. Errors are written to the Exception column in the NJIntegrationLog table.
To configure logging of the description attribute, in the Source tab, modify the description attribute in the service that is bound to the target channel, as shown in the examples below.
Info
For an outbound service, add the description before the service terminates.
The following example shows how to enable logging of the description for an inbound service.
((SysIntegrationLog'receiverEntry)'description "<sample description string>")
The following example shows how to enable logging of the description for an outbound service.((SysIntegrationLog'senderEntry)'description "<sample description string>")
Similarly, you can enable exception logging by modifying the exception attribute, as shown in the following inbound service example.SCHEME(SysIntegrationLog'receiverEntry (message (: exception "Exception: collection of IDs returned when only one was expected" ) )
Save and close the outbound service.
You have configured integration logging for exception and description attributes.
Configuring integration logging of a custom attribute
You can configure integration logging of a custom attribute by specifying the attribute in a derived class of the SysIntegrationLog
class. A derived class is also known as a subclass.
Also, you must specify that the System.IntegrationLogger component uses the new derived class instead of the SysIntegrationLog
class.
To configure logging of a custom attribute:
- In NexJ Studio, navigate to the Business Model layer and select the Classes tab.
- Create a new class and specify the
SysIntegrationLog
class as the base class of the new class. Add the custom attribute or attributes that you want to configure logging for.
Info
If you want to persist logging of the custom attribute, ensure that you add the attribute to an extension table rather than the NJIntegrationLog table.
If you want to persist logging of the custom attribute, ensure that you add the attribute to an extension table rather than the NJIntegrationLog table.
In the Resources layer, select the Components tab, and open the System.IntegrationLogger component.
In the Source tab, change the integrationLogClass property value to the name of the derived class that you created earlier. For example, change:
<Property name="integrationLogClass"><SysIntegrationLog></Property>
to:<Property name="integrationLogClass"><SysIntegrationLogDerivedClass></Property>
If you want to persist logging of the custom attribute, then you must specify the column name of the custom attribute before the service terminates. The following example shows the syntax for persisting logging of a custom attribute as a string:
((SysIntegrationLog'senderEntry)'<customAttribute> "<AttributeStringValue>")
The following example shows how to persist logging of an outbound call to the messageId custom column:((SysIntegrationLog'senderEntry)'<messageId> "<1567651>")
You have added logging of a custom attribute to the integration logs.
Analyzing dataload extract output
You can use the debug:normalize-objects-to-file function to identify differences between objects in a large collections of messages. When you extract data using the invoke-dataload-extract function, several messages in the collection may have the same attribute values as other messages. The debug:normalize-objects-to-file function separates unique attributes of messages from those that are common to multiple messages. This minimizes the amount of data for you to review when you debug issues.
Info
The debug:normalize-objects-to-file function can only be used to analyze persisted messages that specify an object ID (OID) and class.
The function uses the following arguments:
objects collection<msg>
, which represents the collection of messages that need to be parsedfunPrefix string
, which is a string to prefix all of the defined variablesoutFile
, which is the location of the output file with the generated scheme code
Example of the debug: normalize-objects-to-file function
The following example shows the debug:normalize-objects-to-file function run on data related to a group of contacts.
(debug:normalize-objects-to-file
(collection
(message
(: :class "Person")
(: :oid (oid #z2931241FFA5944A483A249EF3482988C))
(: firstName "Tagan")
(: lastName "Kenton")
(: tier "A")
)
(message
(: :class "Person")
(: :oid (oid #z2931241FFA5944A48FA249EF3482988C))
(: firstName "Giovanni")
(: lastName "Kenton")
(: tier "A")
)
)
"contactImport"
(string-collection-affix (java.io.File'separator) (debug:get-project_dir) "etc"
"scratchpads" "seed_contact_data.scm")
)
After the function is run, the output file (seed_contact_data.scm
) is saved to a scratchpad in your project directory.
The output file lists attributes common to all messages at the top of the file, for example, the class, last name, and tier in this case. The file then lists individual messages in the same sequence as in the input file, but only displays attributes that are unique to each message, for example, the first name.
(define contactImport:getMsgCollection
(lambda ()
(define msgCollection (collection))
(msgCollection'add (contactImport:Person:getMessage
"Person_102931241FFA5944A483A249EF3482988C"))
(msgCollection'add (contactImport:Person:getMessage
"Person_102931241FFA5944A48FA249EF3482988C"))
; return
msgCollection
)
)
(define contactImport:Person:getMessage
(lambda (imgId)
; Common values are defined once
(define msg
(message
(: :class "Person")
(: :oid (string->oid ((string-match imgId "_([A-Z\\d]+)$") 1)))
(: lastName "Kenton")
(: tier "A")
)
)
(cond
((= imgId "Person_102931241FFA5944A483A249EF3482988C") (msg 'firstName
"Tagan"))
((= imgId "Person_102931241FFA5944A48FA249EF3482988C") (msg 'firstName
"Giovanni"))
(else (set! msg ()))
)
; return
msg
)
)