UNPKG

@uoa/lambda-tracing

Version:

Library for logging & distributed tracing in UoA Lambda projects

169 lines (137 loc) 9.15 kB
![npm (scoped)](https://img.shields.io/npm/v/@uoa/lambda-tracing) # UOA Lambda Tracing Library This library contains functions to enable distributed tracing & logging in University of Auckland AWS Lambda projects. ## Usage ### Prerequisites If deploying to Kong gateway, your lambda plugin should have the `awsgateway_compatible` flag set to `true`. This ensures the trace headers will be passed through to your lambda project correctly, but you will now have to base64 decode the request body before using it. ### Installation Install the library using the command ``` npm install @uoa/lambda-tracing ``` ### Setup In your src folder, create a new file `tracing-wrapper.ts`\ In this, add the following code ``` import {initializeTracing} from "@uoa/lambda-tracing"; initializeTracing(); ``` In your lambda environment.yml file, add the following `NODE_OPTIONS` environment variable in the properties map ``` lambda: properties: NODE_OPTIONS: --require src/tracing-wrapper ``` The above ensures that the `tracing-wrapper.ts` code will be loaded before your lambda app starts, which will perform the required setup for logging and distributed tracing. ### Logging Whenever you want to use the logging provided in this library, simply import the logger using ``` const logger = require('@uoa/lambda-tracing/logging')(module); ``` Note: `(module)` must be passed as a parameter to this import so that the logger knows where it has been called from. Once the logger has been imported, you can log any info using ``` logger.info('Hello Logger!'); ``` **Logging Levels** At UoA, we have five logging levels available to use. Ordered by decreasing priority, these are: | Level | Logger usage | |-------|----------------------| | ERROR | ```logger.error()``` | | WARN | ```logger.warn()``` | | AUDIT | ```logger.audit()``` | | INFO | ```logger.info()``` | | DEBUG | ```logger.debug()``` | By default, any log at the `INFO` level or higher will be logged. However, this can be changed by adding another environment variable `loggingLevel` in the lambda properties map of the environment.yml file. The value of this specifies the lowest level that will be logged. ``` lambda: properties: NODE_OPTIONS: --require src/tracing-wrapper loggingLevel: WARN ``` ``` logger.debug('Will not be logged'); logger.info('Will not be logged'); logger.audit({...}, 'Will not be logged'); logger.warn('Will be logged'); logger.error('Will be logged'); ``` **Logging format** By default, logs will be produced in the following format: ``` date [thread] level class - [[[traceId,spanId,info]]] message ``` This can also be changed by adding another environment variable `loggingPattern` in the lambda properties map of the environment.yml file. ``` lambda: properties: NODE_OPTIONS: --require src/tracing-wrapper loggingPattern: "%date - %message | %level | %class" ``` Valid logging pattern placeholders are as follows: | Placeholder | Replacement value | Example value | |-------------|-----------------------------------------------------------------------------------------------------------------------|----------------------------------| | %date | Date time when the message is logged in ISO8601 format | 2022-05-29T21:31:11.250Z | | %thread | Unused, this is only present in the default pattern to match with UoA logging standards. Value will always be ```-``` | - | | %level | Log level | INFO | | %class | The module which logged the message | src.handle-service | | %traceId | Unique Id for the request | 5c0c783c965a684842608f10422fdf2c | | %spanId | Unique Id for the current lambda invocation | 6a8b025511ac1191 | | %info | Extra information to help with filtering the logs | usefulCode=12345 | | %message | The logged message | Hello Logger! | **Audit Logs** All logger functions **_except_** `logger.audit()` take a single string as the message to be logged. The audit() function takes an `AuditInformation` object as a parameter. A second `message` parameter of type string is optional. Using the values passed in the `AuditInformation` parameter, the audit log message will be standardised so that logstash can correctly ingest and send the logs to the _uoa-app-audit-logs-*_ index on Kibana. The `AuditInformation` parameter has the below required properties: | Property | Type | Description | |--------------|--------------------------------------------------------|----------------------------------------------------| | application (optional) | string | Application name that groups different physical systems into a single logical group. For example, this may be the front end system name so that multiple backend system logs can be grouped together. | | action | 'read' | 'update' | 'create' | 'delete' | The CRUD action being performed on the resource. | | resourceId (optional) | string | The ID of the resource being actioned upon. | | resourceType | string | The name/type of the resource being actioned upon. | | ownerId | string | The ID of the owner of the resource information. | | accessedBy | string | The ID of the person/system accessing the resource. | Calling the `logger.audit()` function as below: ```typescript logger.audit({application: "applicationName", action: "read", resourceId: "123456789", resourceType: "personalDetails", accessedBy: "upi1234", ownerId: "upi5678"}, "Additional useful info"); ``` Will produce the following log message: ```text 2024-04-12T00:58:05.321Z [-] AUDIT src.controller.person-controller - [[[TraceId,SpanId,Info]]] application:applicationName accessedBy:upi1234 action:read owner:upi5678 resourceType:personalDetails resourceId:123456789 Additional useful info ``` ### Distributed Tracing There are two headers that can be passed in API calls to your lambda project using this library: ```X-B3-TraceId``` and ```X-B3-Info```. If passed to a lambda project using this library, the values of %traceId and %info in the logging pattern will be the corresponding header values. `X-B3-TraceId` should be either a 16 or 32 character lowercase hex encoded string.\ If the passed traceId is less than 16 characters, it will be left padded with 0's to get to a length of 16.\ Likewise, if it is longer than 16 but less than 32 characters, it will be left padded with 0's to get to a length of 32.\ If it is longer than 32 characters, a new traceId will be generated.\ If the `X-B3-TraceId` **_and_** `X-B3-SpanId` headers are not passed, they will be randomly generated. `X-B3-Info` can be any string value to provide extra information in your logs.\ The value of this header can be accessed by using the `getTraceInfoHeader(): string` function. Similarly, it can be set using the `setTraceInfoHeader(string)` function.\ These two functions can be imported using: ``` const {setTraceInfoHeader, getTraceInfoHeader} = require('./logging/tracing'); ``` **Header Propagation** To propagate the ```X-B3-TraceId``` and ```X-B3-Info``` headers to other APIs, you can import and use the uoaHttps module: ``` const uoaHttps = require('@uoa/lambda-tracing/uoaHttps'); ``` The `uoaHttps` module exposes some functions to perform the primary HTTP operations. These will inject the tracing headers into requests before they are made: ``` doGetRequest(hostname, path, headers): Promise doPostRequest(hostname, path, headers, data): Promise doPutRequest(hostname, path, headers, data): Promise doDeleteRequest(hostname, path, headers): Promise ``` There is also another function `request()` exposed in this module in case header propagation with operations other than the basic GET, POST, PUT, and DELETE are required.\ The usage of this is the same as the one provided by the Node https library (see specs [here](https://nodejs.org/api/https.html#httpsrequestoptions-callback)).