Introduction
Application logging and error handling are critical parts of log management and help a business run smoothly. If you don’t have any proper logging records, it is difficult to identify the events, making troubleshooting a long and time-consuming process.
Generally, developers use different logging practises to log the events, but in case of a mishap, it is a default to find the required data that is helpful for troubleshooting. This again requires a long process of additional coding or debugging to derive the relevant data.
To overcome the above scenarios, we have developed a framework for service utility service error handling. This essentially standardises the message logging and exception handling scenarios in any kind of MuleSoft API. The out-of-box utility service minimises developer efforts by 10-15%.
What is Utility Service?
Utility Service is a framework that logs messages with all the required information that would be helpful for troubleshooting. It has the capability to log the message in different formats.
Services offered by Utility Service
- It supports different log formats.
- Maintains one transaction across different layers (system, process, and experience). Using this, one can easily track the transaction from start to finish.
- No additional formatting or logging is required, and it is easily publishable to data aggregation platforms like Splunk, ELK, and others.
- It calculates the latency from start to end across layers, which is useful to monitor the performance of the application.
- Request level details can be tracked using RequestID and FunctionalID params. The RequestID will be unique for different layers.
- Additionally, it supports up to 10 context keys to log any other information.
- It will propagate the actual error details to the consumer, even in the case of an API-led approach.
- One can easily configure it to log the original and errored payloads.
- Logs the source and target names, which are helpful for the triage team.
Different formats are supported by Utility Service
- JSON
- XML
- CSV
Setting up the Utility Service
Using the Runnable Jar
1. Download the Utility Service Jar.
2. Include the Utility Service library in the Maven local repository using the below command.
mvn install:install-file -Dfile=\\co-utility-service-v1-1.0.0-mule-application.jar -DgroupId=com.co -DartifactId=co-utility-service-v1 -Dversion=1.0.0 -Dpackaging=jar -DgeneratePom=true
3. Add the below dependency to your mule project pom.xml
<dependency>
<groupId>com.co</groupId>
<artifactId>co-utility-service-v1</artifactId>
<version>1.0.0</version>
</dependency>
4. Import “co-utility-service.xml” from the utility service into your project global elements and use the utility service for logging and error handling.
Code snippet
<import doc:name=“Import” doc:id=“6dfee7a7-d89a-499b-a4c6-4e24e28d1dd5” file=“co-utility-service.xml” />
Using Utility Service for Error Handling
The utility service is simply used by calling the flows defined using Flow Reference. From here, it automatically handles the errors and logs the transaction in the specified format.
Prerequisite properties to configure
Property | Usage | Supported values | Example |
app.sysname | Application Name | Any | co-utility-service |
app.version | Application Version | Any | V1 |
app.source | Source Name | Any | SFTP |
app.target | Target Name | Any | Salesforce |
app.log.originalPayload | Logs the original payload from the source if set to true | true/false Default – false | true |
app.log.erroredPayload | Logs the errored-out payload in case of error if set to true | true/false Default – false | true |
app.log.format | Logs the message in the specified format | json/xml/csv Default – json | json |
The Utility Service logs the below information
Log Fields | usage |
serverName | Name of the server where application hosted |
appName | Name of the Application |
appVersion | Application Version |
environment | Environment of the application |
source | Source Name |
target | Target Name |
transactionId | Transaction Id |
transactionState | Transaction state |
requestId | Request Id |
executionState | Execution State |
serviceResource | End point called |
serviceMethod | Method of the resource |
payload | Payload |
logTimeStamp | Current Time Stamp |
logMessage | Logs the Message provided |
functionalId | Any unique ID from the Request |
contextKey1 .. contextKey10 | Any additional details for logging |
logLevel | Log Level |
latency | Total time is taken for the process |
errorAt | The component at which the error has occurred |
errorCode | The Response Status code in error cases default is 500 |
errorType | Type of the error Ex: “Internal Server Error” |
errorMessage | The appropriate error message |
Global Error Handler
The globalErrorHandler flow logs the error details in the event of any errors. This flow works on “On Error Propagate” as well as “On Error Continue”. It logs the error messages in different formats like JSON, XML, and CSV.
Steps to configure
- Drag and drop ‘On Error Continue’ or ‘On Error Propagate’ based on the requirement.
- Drag and drop the flow reference inside the error handling.
- Select the globalErrorHandler as a flow name from the drop-down.
- Configure app.log.erroredPayload property to log the errored-out payload if required.
- Configure log format and other properties as per requirements.
The globalErrorHandler logs the root cause of the error.
Suppose the error occurs at the system layer; the same error will be propagated back to the process and application layers.
Snippet of globalErrorHandler
The globalErrorHandler set the actual error status code in the httpStatus variable. The same variable can be used in the HTTP response header to propagate the error status.
Sample error log
{
"serverName": "LAPTOP-KALVA",
"appName": "demo-sample-papi",
"appVersion": "v1",
"environment": "dev",
"transactionId": "5da88430-08f8-11ed-bd7c-d20f0c30c779",
"transactionState": "Transaction_Error",
"requestId": "66870726-279b-45dc-8270-a48b165a2740",
"executionState": "Error",
"serviceResource": "/papi/orders",
"serviceMethod": "GET",
"payload": "{\n \"orderId\": 987456321,\n \"customerId\": \"12934\",\n \"items\": [\n \"ABB-123\",\n \"ACC-452\"\n ]\n}",
"logTimeStamp": "2022-07-21T18:53:54+0530",
"functionalId": 123,
"contextKey1": "test",
"logLevel": "Error",
"latency": 1118,
"errorAt": "demo-sample-sapi-flow/processors/4 @ demo-sample-sapi:demo-sample-sapi.xml:24 (Request)",
"errorCode": 404,
"errorType": "Not Found",
"errorMessage": "No listener for endpoint: /test11111111"
}