awdwadawdawdawdadawdawdadwadaw v1.0.1
Logging
Bluestone NPM module providing:
- a logging library and patterns for structuring log entries
- automatic logging of HTTP calls via middlewares
Build
- When changes are introduced in the NPM module, run this command to re-build it:
yarn install
yarn build
- Commit and push the
dist/
folder in Git.
Installation as an NPM dependency
Add this to your package.json
:
{
...
"dependencies": {
"@lambda-middleware/compose": "^1.2.0",
"bluestone-logging": "file:../../utils/logging",
}
...
If the NPM module has been recently updated, run the following command to retrieve its latest version (given there is currently no support for NPM versionning of the module):
cd my-service/
yarn install --force
Usage
Application logging
This NPM module provides a logger
object that can be used anywhere in application code. Behind the scene, the logging framework it relies on is winston.
logger
must be used for any type of application logs (instead of console.log).
In order to keep logs searchable and consistent, we provide below a few good and bad examples of structured log entries.
The benefit of structuring logs through this NPM modules is that it becomes easier to build functionality around it
- ie. correlation IDs
- ie. dashboard view
- ie. signals filtered of all the logs with a given loan ID
Initial logger configuration
- Initialise the logger with:
export const loggerConfiguration = {
service: 'my-service-name',
level: <LogLevel>config.LOG_LEVEL,
format: <LogFormat>format
};
export const logger = new Logger(loggerConfiguration);
- Change the
service
attribute value to be the name of the current application/service.
Notes:
- The
service
name is used to search logs across multiple services in AWS CloudWatch Logs Insights. - The
format
is used to change the output depending on the environment variable calledENVIRONMENT
.- In AWS (
ENVIRONMENT
= sandbox|staging|production), the format used is JSON. CloudWatch Logs Insights provides a query engine capable of searching the fields present in the JSON log entries. - Locally,
ENVIRONMENT
= local and the logs are using a prettified JSON output.
- In AWS (
- The
level
is used to search logs by level (ie. info, debug, warn, error) across multiple services in AWS CloudWatch Logs Insights.
Adding structured logs
- Import the logger
import { Logger } from 'bluestone-logging';
- Create application-specific standardised codes:
The convention used consists in using TypeScript enums named *Code
.
For example:
export enum LambdaHandlerCode {
OK = '@LAMBDA/HANDLER/OK',
ERROR = '@LAMBDA/HANDLER/ERROR'
}
or
export enum LoanAccountCode {
CLONE_OK = '@LOANACCOUNT/CLONE/OK',
CLONE_ERROR = '@LOANACCOUNT/CLONE/ERROR'
}
- Adding application logs
Application logs can be added using logger.info()
, logger.warn()
, logger.error()
, logger.debug()
.
All log messages have to be of type LogEntry
.
Example:
try {
...
} catch (error) {
logger.error({
code: LOANACCOUNT.CLONE_ERROR,
message: `Failed to clone Product ${process.env.MAMBU_LOANPRODUCT_ID}`,
data: error
});
}
- The use of standardised codes enables log correlation and queries across different execution contexts or services.
message
is used to provide human readable information messagedata
is optional and provide additional structured log data as an object.
- Advanced search filters
To provide advanced search filters, it is recommended to use the data
attribute mentioned above.
Example:
try {
...
} catch (error) {
logger.error({
code: ProductCode.CLONE_ERROR,
message: `Failed to clone Product ${process.env.MAMBU_LOANPRODUCT_ID}`,
data: {
loanId: 'MY-LOAN-ID'
}
});
}
The object { loanId: '...' }
is application specific and should be typed, so that it can be re-used for adding multiple logs that can expose the loanId
as a searchable field in AWS CloudWatch Logs Insights.
Good/bad examples
Bad example of use:
logger.info({
code: 'MY-LOAN-ID',
message: 'This is the loan ID in a log entry'
})
In contrast to the previous example, a good example would be:
logger.info({
code: '@LOAN_ACCOUNT/DELETE/OK',
message: 'This is the loan ID in a log entry',
data: {
loanId: 'MY-LOAN-ID'
}
})
Recommendations:
- Use code to describe actions, not data.
- Use data to provide fields that are commonly used in searches for correlation purposes.
Mambu logging serverless middleware
This middleware intercepts all API calls to Mambu and logs request + response information.
To add the middleware to a serverless function, update the handler to follow this template:
import { APIGatewayEvent,
APIGatewayProxyResult,
ProxyHandler } from 'aws-lambda';
import { MambuLoggingMiddleware } from 'bluestone-logging';
import { compose } from '@lambda-middleware/compose';
async function lambda(
event: APIGatewayEvent,
): Promise<APIGatewayProxyResult> {
// lambda code
};
export const handler: ProxyHandler = compose(
MambuLoggingMiddleware(loggerConfiguration)
)(lambda);
See the Initial Logger Configuration section(#Initial logger configuration) above for information on how to create the loggerConfiguration
object.
3 years ago