This repo contains the Claim Status Tracker app, which helps Californians better understand what’s happening with their unemployment claim and benefits.
9
stars
4
forks
source link
Log a UUID for all traces in a single request/response cycle using a pino child logger #523
If pino is undefined, still pass the logging message through to console.log()
Context
Right now, there is no way to associate related log lines with one another. This PR creates a UUID for each request and then includes it in all logger calls made for that request. This will allow us to easily search and associate logger calls when analyzing logs.
In the request entrypoint in index.tsx:getServerSideProps():
The UUID is created: const requestId = uuidv4()
When the logger is initialized, it now requires the UUID as an argument and it now returns a pino child logger: childLogger = await logger.initialize(requestId)
The child logger is stored in async local storage and all subsequent utility function calls are made within an async callback function that shares the same context:
await asyncContext.run(childLogger, async () => {
// Make the API request and return the data.
const claimData = await queryApiGateway(req, uniqueNumber)
logger.log(childLogger, 'info', claimData, 'ClaimData')
// Run business logic to get content for the current scenario.
scenarioContent = getScenarioContent(claimData)
logger.log(childLogger, 'info', scenarioContent, 'ScenarioContent')
})
In subsequent utility functions (e.g. queryApiGateway(), getClaimDetails.ts:getProgramExtensionPair(), etc), to make a logger call:
First, get the singleton logger instance: const logger: Logger = Logger.getInstance()
Then, retrieve the child logger from async local storage: const childLogger = asyncContext.getStore() as pinoLogger
Finally, make the logger call: logger.log(childLogger, <log level>, <merging object>, <log message>)
Testing
Regression Testing
Because these changes refactor the way we call the core functionality (i.e. by wrapping queryApiGateway() and getScenarioContent() inside an async callback function), we should thoroughly test for any regressions by:
[x] Making sure the unit tests are sufficient
[x] Doing manual testing locally
[x] Doing manual testing on a remote environment
Testing New Functionality
Secondly, we should make sure the changes actually give us the benefit we want (i.e. the UUID is accessible to associate log lines together).
Easy Tests
These tests are easy to trigger on the local environment connected to Dev API gateway:
[x] A normal successful request should include the request id for:
the Request log line
the ClaimData log line
the Program Type: Known log line
the ScenarioContent log line
[x] A request that is missing a unique number should include the request id for:
the Request log line
the Missing unique number error
[x] Missing a critical environment variable such as API_USER_KEY should include the request id for:
the Request log line
the Missing required environment variable(s) error
[x] A certificate read error (such as the local certificate not being readable) should include the request id for:
the Request log line
the Read certificate error error
the Application error error
Harder Tests
These tests are harder to trigger on a local environment because they cover edge cases that we don't have unique numbers for on the Dev API gateway.
To test these, use the mini API gateway mock I built for this purpose. Instructions:
Ticket
Resolves #506
Changes
AsyncLocalStorage
shared utilityconsole.log()
Context
Right now, there is no way to associate related log lines with one another. This PR creates a UUID for each request and then includes it in all logger calls made for that request. This will allow us to easily search and associate logger calls when analyzing logs.
In the request entrypoint in
index.tsx:getServerSideProps()
:const requestId = uuidv4()
childLogger = await logger.initialize(requestId)
In subsequent utility functions (e.g.
queryApiGateway()
,getClaimDetails.ts:getProgramExtensionPair()
, etc), to make a logger call:const logger: Logger = Logger.getInstance()
const childLogger = asyncContext.getStore() as pinoLogger
logger.log(childLogger, <log level>, <merging object>, <log message>)
Testing
Regression Testing
Because these changes refactor the way we call the core functionality (i.e. by wrapping
queryApiGateway()
andgetScenarioContent()
inside an async callback function), we should thoroughly test for any regressions by:Testing New Functionality
Secondly, we should make sure the changes actually give us the benefit we want (i.e. the UUID is accessible to associate log lines together).
Easy Tests
These tests are easy to trigger on the local environment connected to Dev API gateway:
Request
log lineClaimData
log lineProgram Type: Known
log lineScenarioContent
log lineRequest
log lineMissing unique number
errorAPI_USER_KEY
should include the request id for:Request
log lineMissing required environment variable(s)
errorRequest
log lineRead certificate error
errorApplication error
errorHarder Tests
These tests are harder to trigger on a local environment because they cover edge cases that we don't have unique numbers for on the Dev API gateway.
To test these, use the mini API gateway mock I built for this purpose. Instructions:
docker-compose up --build -d
to build and run the container.env.local
, changeAPI_URL
toAPI_URL=http://localhost:8888/GetClaimStatus
queryApiGateway.ts
, comment out line 209 (agent: sslConfiguredAgent
)yarn dev
and use modHeader to test the various "unique numbers" in https://github.com/rocketnova/ca-ui-mini-api-mock#usageRequest
log lineClaimData
log lineProgram Type: Unknown
log lineScenarioContent
log lineRequest
log lineUnexpected API gateway response
errorApplication error
errorRequest
log lineUnexpected API gateway response
errorApplication error
errorRequest
log lineAPI gateway error
errorApplication error
errorscheduleDate
, invalidrequestDate
) should include the request id for:Request
log lineClaimData
log lineUnexpected date
warningProgram Type: Known
log lineScenarioContent
log linependingDetermination.timeSlotDesc
) should include the request id for:Request
log lineClaimData
log lineUnexpected time
warningProgram Type: Known
log lineScenarioContent
log line