diff --git a/jest.config.js b/jest.config.js index fc724cb..26f3faa 100644 --- a/jest.config.js +++ b/jest.config.js @@ -2,6 +2,7 @@ module.exports = { preset: '@lifeomic/jest-config', testMatch: ['/**/*.test.ts'], collectCoverage: true, + coveragePathIgnorePatterns: ['./src/jest-utils.ts'], coverageThreshold: { global: { branches: 100, diff --git a/package.json b/package.json index 0d6ccf3..3bc25c2 100644 --- a/package.json +++ b/package.json @@ -26,11 +26,12 @@ "@aws-sdk/client-dynamodb": "^3.369.0", "@lifeomic/eslint-config-standards": "^3.2.3", "@lifeomic/jest-config": "^1.1.2", - "@lifeomic/logging": "^4.0.0", "@lifeomic/typescript-config": "^3.1.0", + "@types/bunyan": "^1.8.11", "@types/jest": "^27.4.1", "@types/lodash": "^4.14.195", "@types/uuid": "^8.3.4", + "bunyan": "^1.8.15", "conventional-changelog-conventionalcommits": "^4.6.3", "eslint": "^8.9.0", "eslint-config-prettier": "^8.4.0", @@ -51,6 +52,6 @@ "uuid": "^8.3.2" }, "peerDependencies": { - "@lifeomic/logging": "*" + "bunyan": "^1.8" } } diff --git a/src/dynamo-streams.test.ts b/src/dynamo-streams.test.ts index 1a9de42..ac5e8f4 100644 --- a/src/dynamo-streams.test.ts +++ b/src/dynamo-streams.test.ts @@ -1,9 +1,10 @@ -import { LoggerInterface } from '@lifeomic/logging'; import { v4 as uuid } from 'uuid'; -import { DynamoStreamHandler } from './dynamo-streams'; import { marshall } from '@aws-sdk/util-dynamodb'; import { z } from 'zod'; +import { DynamoStreamHandler } from './dynamo-streams'; +import { useMockLogger } from './jest-utils'; + const TestSchema = z.object({ id: z.string(), name: z.string().optional(), @@ -20,21 +21,13 @@ const testSerializer = { parse: (object: any) => TestSchema.parse(object), }; -const logger: jest.Mocked = { - info: jest.fn(), - error: jest.fn(), - child: jest.fn(), -} as any; +const logger = useMockLogger(); const dataSources = { doSomething: jest.fn(), }; beforeEach(() => { - logger.info.mockReset(); - logger.error.mockReset(); - logger.child.mockReset(); - logger.child.mockImplementation(() => logger); dataSources.doSomething.mockReset(); }); diff --git a/src/dynamo-streams.ts b/src/dynamo-streams.ts index adb5882..fed5e48 100644 --- a/src/dynamo-streams.ts +++ b/src/dynamo-streams.ts @@ -1,4 +1,3 @@ -import { LoggerInterface } from '@lifeomic/logging'; import { v4 as uuid } from 'uuid'; import { Context as AWSContext, @@ -6,6 +5,7 @@ import { DynamoDBRecord, } from 'aws-lambda'; import { marshall, unmarshall } from '@aws-sdk/util-dynamodb'; +import bunyan from 'bunyan'; import { BaseContext, BaseHandlerConfig, @@ -14,6 +14,7 @@ import { processWithOrdering, withHealthCheckHandling, } from './utils'; +import { LoggerInterface } from './logging'; export type DynamoStreamHandlerConfig = BaseHandlerConfig & { @@ -207,10 +208,14 @@ export class DynamoStreamHandler { ) => Promise { return withHealthCheckHandling(async (event, ctx) => { const correlationId = uuid(); + /* istanbul ignore next */ + const logger = + this.config.logger ?? + bunyan.createLogger({ name: 'DynamoStreamHandler' }); const base: BaseContext = { correlationId, - logger: this.config.logger.child({ + logger: logger.child({ requestID: ctx.awsRequestId, correlationId, }), diff --git a/src/jest-utils.ts b/src/jest-utils.ts index 788b847..e1bb046 100644 --- a/src/jest-utils.ts +++ b/src/jest-utils.ts @@ -1,5 +1,4 @@ import { v4 as uuid } from 'uuid'; -import type { LoggerInterface } from '@lifeomic/logging'; import type { DynamoStreamHandler, DynamoStreamHandlerHarnessConfig, @@ -11,6 +10,7 @@ import { SQSMessageHandlerHarnessContext, SQSMessageHandlerHarnessOptions, } from './sqs'; +import { LoggerInterface } from './logging'; /** * Returns a mock logger for use with assertions in a Jest environment. @@ -55,7 +55,7 @@ export const useMockLogger = () => { logger.error.mockReset(); logger.fatal.mockReset(); logger.child.mockReset(); - logger.child.mockImplementation(() => logger); + logger.child.mockImplementation(() => logger as any); }); return logger; diff --git a/src/kinesis.test.ts b/src/kinesis.test.ts index 01347d0..8bf07ca 100644 --- a/src/kinesis.test.ts +++ b/src/kinesis.test.ts @@ -1,21 +1,9 @@ import { v4 as uuid } from 'uuid'; -import { LoggerInterface } from '@lifeomic/logging'; + import { KinesisEventHandler } from './kinesis'; +import { useMockLogger } from './jest-utils'; -const logger: jest.Mocked = { - info: jest.fn(), - error: jest.fn(), - child: jest.fn(), - warn: jest.fn(), -} as any; - -beforeEach(() => { - logger.info.mockReset(); - logger.error.mockReset(); - logger.warn.mockReset(); - logger.child.mockReset(); - logger.child.mockImplementation(() => logger); -}); +const logger = useMockLogger(); const testSerializer = { parseEvent: (msg: string) => JSON.parse(msg), diff --git a/src/kinesis.ts b/src/kinesis.ts index 91ba403..78cc4e7 100644 --- a/src/kinesis.ts +++ b/src/kinesis.ts @@ -1,6 +1,6 @@ -import { LoggerInterface } from '@lifeomic/logging'; import { v4 as uuid } from 'uuid'; import { KinesisStreamEvent, Context as AWSContext } from 'aws-lambda'; +import bunyan from 'bunyan'; import { BaseContext, BaseHandlerConfig, @@ -9,6 +9,7 @@ import { processWithOrdering, withHealthCheckHandling, } from './utils'; +import { LoggerInterface } from './logging'; export type KinesisEventHandlerConfig = BaseHandlerConfig & { @@ -78,9 +79,14 @@ export class KinesisEventHandler { return withHealthCheckHandling(async (event, awsContext) => { // 1. Build the context. const correlationId = uuid(); + /* istanbul ignore next */ + const logger = + this.config.logger ?? + bunyan.createLogger({ name: 'KinesisEventHandler' }); + const context: BaseContext & Context = { correlationId, - logger: this.config.logger.child({ + logger: logger.child({ requestID: awsContext.awsRequestId, correlationId, }), diff --git a/src/logging.ts b/src/logging.ts new file mode 100644 index 0000000..f0789dd --- /dev/null +++ b/src/logging.ts @@ -0,0 +1,6 @@ +import Logger from 'bunyan'; + +export type LoggerInterface = Pick< + Logger, + 'child' | 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal' +>; diff --git a/src/sqs.test.ts b/src/sqs.test.ts index bd537a8..184ab2c 100644 --- a/src/sqs.test.ts +++ b/src/sqs.test.ts @@ -1,15 +1,11 @@ import { v4 as uuid } from 'uuid'; -import { LoggerInterface } from '@lifeomic/logging'; -import { SQSMessageAction, SQSMessageHandler } from './sqs'; import { promises as fs } from 'fs'; import { privateDecrypt } from 'crypto'; -const logger: jest.Mocked = { - info: jest.fn(), - error: jest.fn(), - child: jest.fn(), - warn: jest.fn(), -} as any; +import { SQSMessageAction, SQSMessageHandler } from './sqs'; +import { useMockLogger } from './jest-utils'; + +const logger = useMockLogger(); let publicKey: string; beforeAll(async () => { @@ -19,14 +15,6 @@ beforeAll(async () => { ); }); -beforeEach(() => { - logger.info.mockReset(); - logger.error.mockReset(); - logger.warn.mockReset(); - logger.child.mockReset(); - logger.child.mockImplementation(() => logger); -}); - const testSerializer = { parseMessage: (msg: string) => JSON.parse(msg), stringifyMessage: (msg: any) => JSON.stringify(msg), diff --git a/src/sqs.ts b/src/sqs.ts index d91c2fe..a02a25b 100644 --- a/src/sqs.ts +++ b/src/sqs.ts @@ -1,6 +1,6 @@ -import { LoggerInterface } from '@lifeomic/logging'; import { v4 as uuid } from 'uuid'; import { SQSEvent, Context as AWSContext, SQSRecord } from 'aws-lambda'; +import bunyan from 'bunyan'; import { BaseContext, BaseHandlerConfig, @@ -10,6 +10,7 @@ import { withHealthCheckHandling, } from './utils'; import { publicEncrypt } from 'crypto'; +import { LoggerInterface } from './logging'; export type SQSMessageHandlerConfig = BaseHandlerConfig & { @@ -141,9 +142,14 @@ export class SQSMessageHandler { return withHealthCheckHandling(async (event, awsContext) => { // 1. Build the context. const correlationId = uuid(); + /* istanbul ignore next */ + const logger = + this.config.logger ?? + bunyan.createLogger({ name: 'SQSMessageHandler' }); + const context: BaseContext & Context = { correlationId, - logger: this.config.logger.child({ + logger: logger.child({ requestID: awsContext.awsRequestId, correlationId, }), diff --git a/src/utils.ts b/src/utils.ts index 94c8abc..541d9d2 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,8 +1,8 @@ -import { LoggerInterface } from '@lifeomic/logging'; import { Context } from 'aws-lambda'; import pMap from 'p-map'; import groupBy from 'lodash/groupBy'; import AggregateError from 'aggregate-error'; +import { LoggerInterface } from './logging'; export type BaseContext = { logger: LoggerInterface; @@ -11,9 +11,9 @@ export type BaseContext = { export type BaseHandlerConfig = { /** - * A logger to use in the context. + * An optional logger to use in the context. */ - logger: LoggerInterface; + logger?: LoggerInterface; /** * Create a "context" for the lambda execution. (e.g. "data sources") */ diff --git a/yarn.lock b/yarn.lock index deb50a5..0fe75ed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1122,14 +1122,6 @@ resolved "https://registry.yarnpkg.com/@lifeomic/jest-config/-/jest-config-1.1.2.tgz#761cc893ca3613f09dd40b75e3324d7d5dbdd03f" integrity sha512-w3oQvdcS9y0Ccr7+xkQggmoNM/1woCZGvyMnqAo1np15tvvowpUlrfx3n4IWXRJhHEntB4ri3cciP0B17+lsXQ== -"@lifeomic/logging@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@lifeomic/logging/-/logging-4.0.0.tgz#2dab3321b534b7590838ac3666df43ffe78b05aa" - integrity sha512-HPw00qnBcMAhWcfJymaZ7DABujPXX4fHyG4yFuvQzjeWbODYAR5Q8va7byBJJtq5Keq1ZlLJPYXYb+UehJLT+Q== - dependencies: - "@types/bunyan" "^1.8.7" - bunyan "^1.8.15" - "@lifeomic/typescript-config@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@lifeomic/typescript-config/-/typescript-config-3.1.0.tgz#853b8f8db86b2a83b21302b0d3305dcf495b15c1" @@ -1930,10 +1922,10 @@ dependencies: "@babel/types" "^7.3.0" -"@types/bunyan@^1.8.7": - version "1.8.8" - resolved "https://registry.yarnpkg.com/@types/bunyan/-/bunyan-1.8.8.tgz#8d6d33f090f37c07e2a80af30ae728450a101008" - integrity sha512-Cblq+Yydg3u+sGiz2mjHjC5MPmdjY+No4qvHrF+BUhblsmSfMvsHLbOG62tPbonsqBj6sbWv1LHcsoe5Jw+/Ow== +"@types/bunyan@^1.8.11": + version "1.8.11" + resolved "https://registry.yarnpkg.com/@types/bunyan/-/bunyan-1.8.11.tgz#0b9e7578a5aa2390faf12a460827154902299638" + integrity sha512-758fRH7umIMk5qt5ELmRMff4mLDlN+xyYzC+dkPTdKwbSkJFvz6xwyScrytPU0QIBbRRwbiE8/BIg8bpajerNQ== dependencies: "@types/node" "*" @@ -3603,7 +3595,7 @@ glob-parent@^6.0.1: glob@^6.0.1: version "6.0.4" resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" - integrity sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI= + integrity sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A== dependencies: inflight "^1.0.4" inherits "2" @@ -5028,6 +5020,11 @@ minimist@^1.2.0, minimist@^1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== +minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + minipass-collect@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" @@ -5121,11 +5118,11 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== mkdirp@~0.5.1: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== dependencies: - minimist "^1.2.5" + minimist "^1.2.6" mnemonist@0.38.3: version "0.38.3" @@ -5140,9 +5137,9 @@ modify-values@^1.0.0: integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== moment@^2.19.3: - version "2.29.4" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" - integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== ms@2.1.2: version "2.1.2" @@ -5162,16 +5159,16 @@ mute-stream@~0.0.4: mv@~2: version "2.1.1" resolved "https://registry.yarnpkg.com/mv/-/mv-2.1.1.tgz#ae6ce0d6f6d5e0a4f7d893798d03c1ea9559b6a2" - integrity sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI= + integrity sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg== dependencies: mkdirp "~0.5.1" ncp "~2.0.0" rimraf "~2.4.0" nan@^2.14.0: - version "2.15.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" - integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== + version "2.22.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.22.0.tgz#31bc433fc33213c97bad36404bb68063de604de3" + integrity sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw== natural-compare@^1.4.0: version "1.4.0" @@ -5181,7 +5178,7 @@ natural-compare@^1.4.0: ncp@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" - integrity sha1-GVoh1sRuNh0vsSgbo4uR6d9727M= + integrity sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA== negotiator@^0.6.2, negotiator@^0.6.3: version "0.6.3" @@ -6042,7 +6039,7 @@ rimraf@^3.0.0, rimraf@^3.0.2: rimraf@~2.4.0: version "2.4.5" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.4.5.tgz#ee710ce5d93a8fdb856fb5ea8ff0e2d75934b2da" - integrity sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto= + integrity sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ== dependencies: glob "^6.0.1"