From 2f8c942637efd8d97532d6164d29bbff3b359f53 Mon Sep 17 00:00:00 2001 From: Dallin Osmun Date: Thu, 21 Jun 2018 14:40:43 -0600 Subject: [PATCH 1/3] obscure the x-kuali-authm header (#15) --- lib/server.js | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/server.js b/lib/server.js index 942ff4f..72eb832 100644 --- a/lib/server.js +++ b/lib/server.js @@ -43,7 +43,7 @@ function validateConfig (config) { } function getMiddlewareConfig (config, logger) { - const alwaysObscureHeaders = ['authorization', 'cookie'] + const alwaysObscureHeaders = ['authorization', 'cookie', 'x-kuali-authm'] const middleConfig = { headerName: 'X-Request-Id', diff --git a/package.json b/package.json index 37d81b1..8ac236d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "kuali-logger", - "version": "0.1.2", + "version": "0.1.3", "description": "Standardized logger for Kuali apps", "main": "lib/index.js", "scripts": { From fd81000e1c8107554f0545fa160fda58c2f3317c Mon Sep 17 00:00:00 2001 From: Douglas Pace Date: Fri, 27 Jul 2018 11:10:21 -0700 Subject: [PATCH 2/3] Additional config options to customize middleware logger (#16) * Additional config options to customize middleware logger * fix circle and increment version --- .circleci/config.yml | 1 + lib/server.js | 7 +++-- package.json | 4 +-- readme.md | 9 +++++- test/middleware.test.js | 64 +++++++++++++++++++++++++++++++---------- 5 files changed, 64 insertions(+), 21 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3f207c8..f38ba56 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -123,6 +123,7 @@ jobs: - run: name: Publish to npm command: npm publish + workflows: version: 2 test_deploy: diff --git a/lib/server.js b/lib/server.js index 72eb832..83cb862 100644 --- a/lib/server.js +++ b/lib/server.js @@ -51,12 +51,13 @@ function getMiddlewareConfig (config, logger) { logName: 'requestId', obscureHeaders: alwaysObscureHeaders.concat(config.obscureHeaders || []), excludeHeaders: config.excludeHeaders || [], - additionalRequestFinishData: req => { - const extraFields = { + filter: config.middlewareFilter, + additionalRequestFinishData: (req, res) => { + const extraFields = Object.assign({ event: 'REQUEST', tenant: req.headers['x-kuali-tenant'], lane: req.headers['x-kuali-lane'] - } + }, (config.additionalRequestFinishData ? config.additionalRequestFinishData(req, res) : {})) return extraFields } } diff --git a/package.json b/package.json index 8ac236d..ce12105 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "kuali-logger", - "version": "0.1.3", + "version": "0.1.4", "description": "Standardized logger for Kuali apps", "main": "lib/index.js", "scripts": { @@ -52,4 +52,4 @@ "standard": "^10.0.3", "supertest": "^3.0.0" } -} +} \ No newline at end of file diff --git a/readme.md b/readme.md index 447d618..f49df44 100644 --- a/readme.md +++ b/readme.md @@ -93,7 +93,14 @@ Adding the logger middleware will automatically log all request and response eve ```js const express = require('express') -const log = require('kuali-logger')(config.get('log')) +const log = require('kuali-logger')({ + ...config.get('log'), + additionalRequestFinishData: (req, res) => ({ + userId: req.userInfo.id, + userName: req.userInfo.userName + }, + filter: (req, res) => req.url.includes('/api/v1/health') +) const app = express() app.use(log.middleware) diff --git a/test/middleware.test.js b/test/middleware.test.js index 9f3b3f7..491299c 100644 --- a/test/middleware.test.js +++ b/test/middleware.test.js @@ -14,22 +14,26 @@ const stream = { const obscureHeaders = ['obscure'] const excludeHeaders = ['exclude'] -const log = require('../lib')({ - name: 'testLogger', - team: 'testTeam', - product: 'testProduct', - environment: 'testEnvironment', - stream, - obscureHeaders, - excludeHeaders -}) +function createApp (customConfig) { + const log = require('../lib')(Object.assign({ + name: 'testLogger', + team: 'testTeam', + product: 'testProduct', + environment: 'testEnvironment', + stream, + obscureHeaders, + excludeHeaders + }, customConfig)) -const app = express() -app.use(log.middleware) -app.get('/', (req, res) => { - req.log.info() - res.send('ok') -}) + const app = express() + app.use(log.middleware) + app.get('/', (req, res) => { + req.appSpecificReq = 'test' + req.log.info() + res.send('ok') + }) + return app +} beforeEach(() => { catcher.clear() @@ -38,6 +42,7 @@ beforeEach(() => { describe('middleware', () => { describe('requestId', () => { test('sets requestId correctly if no existing requestId', done => { + const app = createApp() request(app).get('/').end((err, res) => { if (err) throw err expect(res.headers.hasOwnProperty('x-request-id')).toBe(true) @@ -47,6 +52,7 @@ describe('middleware', () => { }) test('leaves existing requestId unchanged', done => { + const app = createApp() request(app).get('/').set('X-Request-Id', 'test').end((err, res) => { if (err) throw err expect(res.headers['x-request-id']).toBe('test') @@ -57,6 +63,7 @@ describe('middleware', () => { }) describe('additional fields', () => { + const app = createApp() test('adds additional fields to log output', done => { request(app) .get('/') @@ -70,10 +77,24 @@ describe('middleware', () => { done() }) }) + test('adds app specific fields', done => { + const app = createApp({additionalRequestFinishData: req => ({appSpecificReq: req.appSpecificReq})}) + request(app) + .get('/') + .set('x-kuali-tenant', 'tenant') + .set('x-kuali-lane', 'lane') + .end((err, res) => { + if (err) throw err + expect(catcher.last.event).toBe('REQUEST') + expect(catcher.last.appSpecificReq).toBe('test') + done() + }) + }) }) describe('obscureHeaders and excludeHeaders', () => { test('obscures and excludes configured headers', done => { + const app = createApp() request(app) .get('/') .set('obscure', 'test') @@ -90,4 +111,17 @@ describe('middleware', () => { }) }) }) + + describe('filters requests', () => { + test('filters requests based on filter function', done => { + const app = createApp({middlewareFilter: req => req.url.includes('filtered')}) + request(app) + .get('/filtered') + .end((err, res) => { + if (err) throw err + expect(catcher.last).toBeFalsy() + done() + }) + }) + }) }) From a91ba912d57339cc17581ad937c1270cdb33e6a0 Mon Sep 17 00:00:00 2001 From: Tadd Giles Date: Fri, 10 Aug 2018 12:02:02 -0600 Subject: [PATCH 3/3] Add ability to replace standard serializers via log config (#17) * Update readme * Add ability to replace standard serializers via log config * 0.1.5 --- lib/server.js | 20 +++++++++++----- package.json | 4 ++-- readme.md | 65 +++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 66 insertions(+), 23 deletions(-) diff --git a/lib/server.js b/lib/server.js index 83cb862..be46b6a 100644 --- a/lib/server.js +++ b/lib/server.js @@ -53,11 +53,16 @@ function getMiddlewareConfig (config, logger) { excludeHeaders: config.excludeHeaders || [], filter: config.middlewareFilter, additionalRequestFinishData: (req, res) => { - const extraFields = Object.assign({ - event: 'REQUEST', - tenant: req.headers['x-kuali-tenant'], - lane: req.headers['x-kuali-lane'] - }, (config.additionalRequestFinishData ? config.additionalRequestFinishData(req, res) : {})) + const extraFields = Object.assign( + { + event: 'REQUEST', + tenant: req.headers['x-kuali-tenant'], + lane: req.headers['x-kuali-lane'] + }, + config.additionalRequestFinishData + ? config.additionalRequestFinishData(req, res) + : {} + ) return extraFields } } @@ -73,7 +78,10 @@ function getLoggerConfig (config) { product: config.product, environment: config.environment, level: config.level || 'info', - serializers: { err: bunyan.stdSerializers.err }, + serializers: Object.assign( + { err: bunyan.stdSerializers.err }, + config.serializers || {} + ), streams: [ { level: config.level || 'info', diff --git a/package.json b/package.json index ce12105..b95188a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "kuali-logger", - "version": "0.1.4", + "version": "0.1.5", "description": "Standardized logger for Kuali apps", "main": "lib/index.js", "scripts": { @@ -52,4 +52,4 @@ "standard": "^10.0.3", "supertest": "^3.0.0" } -} \ No newline at end of file +} diff --git a/readme.md b/readme.md index f49df44..7b55a8d 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,3 @@ -[![bitHound Overall Score](https://www.bithound.io/projects/badges/2258aae0-8f63-11e7-b68c-bd8234fdabb6/score.svg)](https://www.bithound.io/github/KualiCo/kuali-logger) -[![bitHound Dependencies](https://www.bithound.io/projects/badges/2258aae0-8f63-11e7-b68c-bd8234fdabb6/dependencies.svg)](https://www.bithound.io/github/KualiCo/kuali-logger/master/dependencies/npm) [![CircleCI](https://circleci.com/gh/KualiCo/kuali-logger/tree/master.svg?style=shield&circle-token=b8b3696e50f3bce018f444658e7bd9c738d41751)](https://circleci.com/gh/KualiCo/kuali-logger/tree/master) [![codecov](https://codecov.io/gh/KualiCo/kuali-logger/branch/master/graph/badge.svg)](https://codecov.io/gh/KualiCo/kuali-logger) @@ -43,18 +41,20 @@ const log = require('kuali-logger')(config.get('log')) These are the supported configuration options: -| Option | Type | Valid values or examples | Default | Required | -| --- | :---: | --- | :---: | :---: | -| `name` | string | res-coi-production | | X | -| `team` | string | res | | X | -| `product` | string | coi | | X | -| `environment` | string | production | | X | -| `level` | string | `trace`, `debug`, `info`, `warn`, `error`, `fatal` | `info` || -| `format` | string | `short`, `long`, `simple`, `json`, `bunyan`, `pretty` | `json` || -| `obscureHeaders` | array of strings | `['x-newrelic-id', 'ip']` | `['authorization', 'cookie']` || -| `excludeHeaders` | array of strings | `['x-real-ip','x-newrelic-transaction']` | `[]` || -| `stream` | object | ```{ name: 'myStream', stream: process.stdout, level: 'debug', outputFormat: 'json' }``` | bunyan-format stream || -| `src` | boolean | false, true *(Slows output, don't use in production)* | false || +| Option | Type | Valid values or examples | Default | Required | +| ------------------ | :------------------------------------------------------------------------: | ---------------------------------------------------------------------------------------- | :---------------------------: | :------: | +| `name` | string | res-coi-production | | X | +| `team` | string | res | | X | +| `product` | string | coi | | X | +| `environment` | string | production | | X | +| `level` | string | `trace`, `debug`, `info`, `warn`, `error`, `fatal` | `info` | +| `format` | string | `short`, `long`, `simple`, `json`, `bunyan`, `pretty` | `json` | +| `obscureHeaders` | array of strings | `['x-newrelic-id', 'ip']` | `['authorization', 'cookie']` | +| `excludeHeaders` | array of strings | `['x-real-ip','x-newrelic-transaction']` | `[]` | +| `stream` | object | ```{ name: 'myStream', stream: process.stdout, level: 'debug', outputFormat: 'json' }``` | bunyan-format stream | +| `src` | boolean | false, true *(Slows output, don't use in production)* | false | +| `serializers` | [object with functions](https://github.com/trentm/node-bunyan#serializers) | valid javascript serializer functions | | +| `middlewareFilter` | function | | valid javascript function | | ### Log Example @@ -94,7 +94,7 @@ Adding the logger middleware will automatically log all request and response eve ```js const express = require('express') const log = require('kuali-logger')({ - ...config.get('log'), + ...config.get('log'), additionalRequestFinishData: (req, res) => ({ userId: req.userInfo.id, userName: req.userInfo.userName @@ -198,6 +198,21 @@ if(err) { } ``` +## Filter log output +You can filter log output by creating a function that modifies the `req` and `res` objects and applying it to the log configuration. + +```js +function myMiddlewareFilter (req, res) { + const pattern = /(\/readyz$|\/healthz$|\/metrics$|\/health$)/ + return req.headers['x-synthetic'] || pattern.test(req.url) +} + +module.exports = { + log: { + middlewareFilter: myMiddlewareFilter + } +} +``` ## Configure a custom stream You can override the default stream configuration with your own [stream configuration](https://github.com/trentm/node-bunyan#streams). @@ -222,6 +237,26 @@ const logConfig = { const log = require('kuali-logger')(logConfig) ``` +## Replace a standard serializer +You can replace the built-in serializers (`req` and `res`) with your own functions. + +```js +function myResSerializer(res) { + return { + statusCode: res.statusCode, + header: res._header + } +} + +module.exports = { + log: { + serializers: { + res: myResSerializer + } + } +} +``` + ## Add a custom serializer You can use the standard bunyan method to [add a custom serializer](https://github.com/trentm/node-bunyan#serializers).