diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5adc03e..9d3f27d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -18,7 +18,7 @@ jobs: strategy: matrix: - node-version: [10.x, 12.x, 14.x] + node-version: [12.x, 14.x] steps: - uses: actions/checkout@v2 diff --git a/README.MD b/README.MD index b652343..75ed2bd 100644 --- a/README.MD +++ b/README.MD @@ -1,7 +1,10 @@ -middy-beeline -=== +[![GitHub release](https://img.shields.io/github/release/resistbot/middy-beeline?include_prereleases=&sort=semver)](https://github.com/resistbot/middy-beeline/releases/) [![Tests](https://github.com/resistbot/middy-beeline/workflows/Tests/badge.svg)](https://github.com/resistbot/middy-beeline/actions?query=workflow:"Tests") -Middy middleware for instrumenting with [Honeycomb](https://honeycomb.io). +[![NPM](https://nodei.co/npm/@resistbot/middy-beeline.png?compact=true)](https://npmjs.org/package/@resistbot/middy-beeline) + +# middy-beeline + +Middy middleware for instrumenting with [Honeycomb](https://honeycomb.io). ## Getting Started @@ -13,6 +16,7 @@ npm install --save @resistbot/middy-beeline ``` Running the tests + ```bash npm test ``` @@ -47,11 +51,13 @@ module.exports = { handler } ``` ## How it works -The middleware will startup [Beeline for Nodejs](https://docs.honeycomb.io/getting-data-in/javascript/beeline-nodejs) with the options you configure before your handler runs, create a trace, and add any of the header context you supplied. It adds the `beeline` instance to the handler.event so you can use it in your function- add spans, more context, etc. + +The middleware will startup [Beeline for Nodejs](https://docs.honeycomb.io/getting-data-in/javascript/beeline-nodejs) with the options you configure before your handler runs, create a trace, and add any of the header context you supplied. It adds the `beeline` instance to the handler.event so you can use it in your function- add spans, more context, etc. Once your handler is done, the middleware will close the trace and run a `beeline.flush()` to make sure all the events are sent. ## Options + Some are obvious from the beeline for nodejs documentation (writeKey, dataset, serviceName, sampleRate) but there are a few extras. Just like the beeline docs say, you can substitute `sampleRate` with `samplerHook: fn()` and the middleware will use your samplerhook function instead of the standard rate. Also the headerContext list allows you to tell middy-beeline which headers to capture as context and what they should be named. Also by default, any errors are marked as `error:true` and `error_message: `. You can change the context key for errors using `errorMessageContext`. @@ -59,3 +65,8 @@ Also the headerContext list allows you to tell middy-beeline which headers to ca ## Contributing Feel free to open a Pull Request or Issue w/ a bug report or feature request. + +## Creating a release + +1. Update `package.json` version element to match the release you'll be using. +1. Create a new Release once your code is merged. If the two versions match, a new version will be delivered to [npm](https://www.npmjs.com/package/@resistbot/middy-beeline). diff --git a/index.js b/index.js index c399618..8566da2 100644 --- a/index.js +++ b/index.js @@ -1,26 +1,22 @@ let HC_INIT = false; -const setopts = (opts) => { - const defaults = { - writeKey: 'null', - serviceName: '', - dataset: 'test', - sampleRate: 10, - headerContext: [], - errorMessageContext: 'error_message', - }; +const defaults = { + writeKey: 'null', + serviceName: '', + dataset: 'test', + sampleRate: 10, + headerContext: [], + errorMessageContext: 'error_message', +}; +const honeycombMiddleware = (opts = {}) => { const options = { ...defaults, ...opts }; - return options; -}; -module.exports = (opts) => ({ - before: (handler, next) => { - const options = setopts(opts); + const honeycombMiddlewareBefore = (request) => { if (!HC_INIT) { if (options.samplerHook) { // eslint-disable-next-line no-param-reassign, global-require - handler.event.beeline = require('honeycomb-beeline')({ + request.event.beeline = require('honeycomb-beeline')({ writeKey: options.writeKey, samplerHook: options.samplerHook, serviceName: options.serviceName, @@ -28,7 +24,7 @@ module.exports = (opts) => ({ }); } else { // eslint-disable-next-line no-param-reassign, global-require - handler.event.beeline = require('honeycomb-beeline')({ + request.event.beeline = require('honeycomb-beeline')({ writeKey: options.writeKey, sampleRate: options.sampleRate, serviceName: options.serviceName, @@ -38,37 +34,42 @@ module.exports = (opts) => ({ HC_INIT = true; } else { // eslint-disable-next-line no-param-reassign, global-require - handler.event.beeline = require('honeycomb-beeline')(); + request.event.beeline = require('honeycomb-beeline')(); } // eslint-disable-next-line no-param-reassign - handler.event.trace = handler.event.beeline.startTrace(); + request.event.trace = request.event.beeline.startTrace(); options.headerContext.forEach((head) => { const { header, contextname } = head; - if (handler.event.headers[header]) { - handler.event.beeline.addContext({ - [contextname]: handler.event.headers[header], + if (request.event.headers[header]) { + request.event.beeline.addContext({ + [contextname]: request.event.headers[header], }); } }); - return next(); - }, - after: (handler, next) => { - handler.event.beeline.finishTrace(handler.event.trace); - handler.event.beeline.flush(); - return next(); - }, - onError: (handler, next) => { - const options = setopts(opts); - if (handler.event.beeline) { - handler.event.beeline.addContext({ + }; + + const honeycombMiddlewareAfter = (request) => { + request.event.beeline.finishTrace(request.event.trace); + request.event.beeline.flush(); + }; + + const honeycombMiddlewareOnError = (request) => { + if (request.event.beeline) { + request.event.beeline.addContext({ error: true, - [options.errorMessageContext]: handler.error.toString(), + [options.errorMessageContext]: request.error.toString(), }); - handler.event.beeline.finishTrace(handler.event.trace); - handler.event.beeline.flush(); + request.event.beeline.finishTrace(request.event.trace); + request.event.beeline.flush(); } + }; + + return { + before: honeycombMiddlewareBefore, + after: honeycombMiddlewareAfter, + onError: honeycombMiddlewareOnError, + }; +}; - return next(handler.error); - }, -}); +module.exports = honeycombMiddleware; diff --git a/index.test.js b/index.test.js index c41431f..cd3a36a 100644 --- a/index.test.js +++ b/index.test.js @@ -1,29 +1,21 @@ -const middy = require('middy'); const middyBeeline = require('.'); describe('middy-beeline', () => { - it('should extract keys', (done) => { - const handler = middy((event, context, callback) => { - callback(null, event.extracted); + it('should extract keys', () => { + const middleware = middyBeeline({ + writeKey: 'key', + serviceName: 'myService', + dataset: 'myDataset', + samplerHook: () => false, }); - handler.use( - middyBeeline({ - writeKey: 'key', - serviceName: 'myService', - dataset: 'myDataset', - }), - ); - const event = { requestContext: {}, headers: { 'Content-Type': 'application/json', }, }; - handler(event, null, (err) => { - expect(err).toBe(null); - done(); - }); + const request = { event }; + middleware.before(request); }); }); diff --git a/package.json b/package.json index 85ac138..0aac7ce 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "@resistbot/middy-beeline", - "version": "0.1.4", + "version": "1.0.0", "description": "Middy Middleware for Honeycomb Beeline", "main": "index.js", "engines": { - "node": ">=8.3.0" + "node": ">=12.13.0" }, "scripts": { "format": "prettier --write .", @@ -42,5 +42,8 @@ "middy": "^0.36.0", "nock": "^13.1.1", "prettier": "^2.3.2" + }, + "peerDependencies": { + "@middy/core": "^2.0.0" } }