Skip to content

Commit

Permalink
feat(RequestLogging): Include err field (#56)
Browse files Browse the repository at this point in the history
Consuming applications tend towards the following `logFn` boilerplate:

```typescript
const data = {
  ...fields,
  err: err ?? ErrorMiddleware.thrown(ctx),
};
```

While Koala provides a simplified `internalErrorString`, rich error
details are often handy for troubleshooting, and the `err` property name
is blessed by common logging frameworks like Bunyan and Pino. This
preserves `internalErrorString` for backward compatibility.
  • Loading branch information
72636c authored Dec 13, 2020
1 parent 7b4862f commit f836904
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 4 deletions.
5 changes: 5 additions & 0 deletions src/requestLogging/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@ const healthCheckHandler = async (ctx: Koa.Context) => {
},
"status": 500,
"internalErrorString": "ExpiredTokenException: The security token included in the request is expired",
"err": {
"message": "The security token included in the request is expired",
"name": "ExpiredTokenException",
"stack": "..."
},
"msg": "request log",
"time": "2018-10-16T00:44:41.055Z",
"v": 0
Expand Down
1 change: 1 addition & 0 deletions src/requestLogging/requestLogging.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ describe('RequestLogging', () => {
},
`
Object {
"err": [Error: Something tragic happened],
"headers": Object {
"accept": undefined,
"accept-encoding": "gzip, deflate",
Expand Down
14 changes: 10 additions & 4 deletions src/requestLogging/requestLogging.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Koa from 'koa';

import { thrown } from '../errorMiddleware/errorMiddleware';
import { tracingFromContext } from '../tracingHeaders/tracingHeaders';

/**
Expand Down Expand Up @@ -126,7 +127,7 @@ export const createMiddleware = <StateT extends State, CustomT>(

const requestFinished = (
resultFields: Record<string, unknown>,
error?: unknown,
err?: unknown,
) => {
if (ctx.state.skipRequestLogging) {
return;
Expand All @@ -136,20 +137,25 @@ export const createMiddleware = <StateT extends State, CustomT>(
logFn(
ctx,
{
...(typeof err !== 'undefined' && {
err,
internalErrorString: String(err),
}),
latency,
headers: replaceHeaders(ctx.request.header, headerReplacements),
...contextFields(ctx),
...resultFields,
},
error,
err,
);
};

try {
await next();
requestFinished({ status: ctx.response.status });

requestFinished({ status: ctx.response.status }, thrown(ctx));
} catch (err: unknown) {
requestFinished({ status: 500, internalErrorString: String(err) }, err);
requestFinished({ status: 500 }, err);

throw err;
}
Expand Down

0 comments on commit f836904

Please sign in to comment.