Skip to content

Commit

Permalink
feat: add debug option
Browse files Browse the repository at this point in the history
  • Loading branch information
chunkai1312 committed Jan 1, 2020
1 parent f8195f9 commit c4a3da9
Show file tree
Hide file tree
Showing 7 changed files with 306 additions and 229 deletions.
13 changes: 12 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,16 @@
"env": {
"node": true,
"mocha": true
}
},
"overrides": [
{
"files": [
"*.test.js",
"*.spec.js"
],
"rules": {
"no-unused-expressions": "off"
}
}
]
}
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,14 @@ Create a error handling middleware to send error reporting to Slack channel.
```js
{
webhookUri: String,
skip: function (err, req, res) { return false }
skip: function (err, req, res) { return false },
debug: Boolean
}
```

- `webhookUri`: Required. Your Slack webhook uri that the channel will receive error reporting.
- `skip`: Optional. A function to determine if handler is skipped, defaults to returning false.
- `skip`: Optional. A function to determine if handler is skipped. Defaults to always returning `false`.
- `debug`: Optional. Show logging of response from Slack if set true. Defaults to `false`.

## Result Example

Expand All @@ -73,4 +75,4 @@ MIT © [Chun-Kai Wang](https://github.com/chunkai1312)
[travis-image]: https://img.shields.io/travis/chunkai1312/express-error-slack.svg
[travis-url]: https://travis-ci.org/chunkai1312/express-error-slack
[codecov-image]: https://img.shields.io/codecov/c/github/chunkai1312/express-error-slack.svg
[codecov-url]: https://codecov.io/gh/chunkai1312/express-error-slack
[codecov-url]: https://codecov.io/gh/chunkai1312/express-error-slack
33 changes: 19 additions & 14 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,17 @@

const sendError = require('./send-error')

function errorToSlack (options = {}) {
if (typeof options !== 'object') {
throw new Error('Expected options to be a object')
}

if (typeof options.webhookUri === 'undefined') {
throw new Error('Missing webhookUri')
}
function errorToSlack (options) {
options = Object.assign({
webhookUri: null,
skip: (/* err, req, res */) => false,
debug: false
}, options)

if (typeof options.webhookUri !== 'string') {
throw new Error('Expected webhookUri to be a string')
}

const webhookUri = options.webhookUri
const skip = options.skip || false

return function (err, req, res, next) {
if (!(err instanceof Error)) {
// In case a number or other primitive is thrown
Expand All @@ -26,12 +21,22 @@ function errorToSlack (options = {}) {

err.status = err.status || 500

if (skip !== false && skip(err, req, res)) return next(err)
sendError(webhookUri, err, req)
if (options.skip(err, req, res)) {
return next(err)
}

// send error report to slack
sendError(options, err, req, (error, response) => {
if (options.debug) {
console.log(response)
if (error) console.error(error)
}
})

next(err)
}
}

errorToSlack.sendError = sendError
errorToSlack.sendErrorToSlack = sendError

module.exports = errorToSlack
13 changes: 6 additions & 7 deletions lib/send-error.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
'use strict'

const Slack = require('slack-node')
const { extend, isEmpty } = require('lodash')

function getRemoteAddress (req) {
/* istanbul ignore next */
return req.headers['x-forwarded-for'] || req.ip || (req.connection && req.connection.remoteAddress)
}

function createCodeBlock (title, code) {
if (isEmpty(code)) return ''
code = (typeof code === 'string') ? code.trim() : JSON.stringify(code, null, 2)
const tripleBackticks = '```'
return `_${title}_${tripleBackticks}${code}${tripleBackticks}\n`
}

function sendError (webhookUri, err, req) {
function sendError (options, err, req, cb) {
const slack = new Slack()
slack.setWebhook(webhookUri)
slack.setWebhook(options.webhookUri)

const request = {
method: req.method,
Expand All @@ -26,7 +25,7 @@ function sendError (webhookUri, err, req) {
body: req.body || {}
}

const attachment = extend({}, {
const attachment = Object.assign({}, {
fallback: `${err.name}: ${err.message}`,
color: (err.status < 500) ? 'warning' : 'danger',
author_name: req.headers.host,
Expand All @@ -43,10 +42,10 @@ function sendError (webhookUri, err, req) {
].map(data => createCodeBlock(data.title, data.code)).join(''),
mrkdwn_in: ['text'],
footer: 'express-error-slack',
ts: parseInt(Date.now() / 1000)
ts: Math.floor(Date.now() / 1000)
})

slack.webhook({ attachments: [attachment] }, (error, response) => { if (error) console.error(error) })
slack.webhook({ attachments: [attachment] }, cb)
}

module.exports = sendError
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
},
"homepage": "https://github.com/chunkai1312/express-error-slack#readme",
"dependencies": {
"lodash": "^4.17.15",
"slack-node": "^0.1.8"
},
"devDependencies": {
Expand Down
70 changes: 52 additions & 18 deletions test/express-error-slack.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,18 @@ const errorToSlack = require('../lib')

describe('Express Error Slack', () => {
const sandbox = sinon.createSandbox()
let spy
let stub

beforeEach(() => {
spy = sandbox.spy(Slack.prototype, 'webhook')
stub = sandbox
.stub(Slack.prototype, 'webhook')
.callsFake((options, cb) => cb(null, { response: 'ok' }))
})

afterEach(() => {
sandbox.restore()
})

it('should throw error if options not a object', () => {
expect(() => errorToSlack(false)).to.throw(Error)
})

it('should throw error if missing webhookUri', () => {
expect(() => errorToSlack({})).to.throw(Error)
})

it('should throw error if webhookUri not a string', () => {
expect(() => errorToSlack({ webhookUri: false })).to.throw(Error)
})
Expand All @@ -42,8 +36,8 @@ describe('Express Error Slack', () => {
.expect(400)
.end((err, res) => {
expect(err).to.not.exist
expect(spy.calledOnce).to.be.true
expect(spy.args[0][0].attachments[0]).to.have.property('color', 'warning')
expect(stub.calledOnce).to.be.true
expect(stub.args[0][0].attachments[0]).to.have.property('color', 'warning')
done()
})
})
Expand All @@ -58,8 +52,8 @@ describe('Express Error Slack', () => {
.expect(500)
.end((err, res) => {
expect(err).to.not.exist
expect(spy.calledOnce).to.be.true
expect(spy.args[0][0].attachments[0]).to.have.property('color', 'danger')
expect(stub.calledOnce).to.be.true
expect(stub.args[0][0].attachments[0]).to.have.property('color', 'danger')
done()
})
})
Expand All @@ -74,13 +68,13 @@ describe('Express Error Slack', () => {
.expect(500)
.end((err, res) => {
expect(err).to.not.exist
expect(spy.calledOnce).to.be.true
expect(spy.args[0][0].attachments[0]).to.have.property('color', 'danger')
expect(stub.calledOnce).to.be.true
expect(stub.args[0][0].attachments[0]).to.have.property('color', 'danger')
done()
})
})

it('should skip to send error to slack if options.skip returns true', (done) => {
it('should skip to send error to slack if options.skip is set', (done) => {
const app = express()
app.use((req, res, next) => next(createError(404)))
app.use(errorToSlack({
Expand All @@ -93,7 +87,47 @@ describe('Express Error Slack', () => {
.expect(404)
.end((err, res) => {
expect(err).to.not.exist
expect(spy.calledOnce).to.be.false
expect(stub.calledOnce).to.be.false
done()
})
})

it('should show logging of response from slack if options.debug is true', (done) => {
const app = express()
app.use((req, res, next) => next(createError(404)))
app.use(errorToSlack({
webhookUri: 'https://hooks.slack.com/services/TOKEN',
debug: true
}))

request(app)
.get('/')
.expect(404)
.end((err, res) => {
expect(err).to.not.exist
expect(stub.calledOnce).to.be.true
expect(stub.args[0][0].attachments[0]).to.have.property('color', 'warning')
done()
})
})

it('should show logging of error from slack if options.debug is true', (done) => {
stub.callsFake((options, cb) => cb(new Error()))

const app = express()
app.use((req, res, next) => next(createError(404)))
app.use(errorToSlack({
webhookUri: 'https://hooks.slack.com/services/TOKEN',
debug: true
}))

request(app)
.get('/')
.expect(404)
.end((err, res) => {
expect(err).to.not.exist
expect(stub.calledOnce).to.be.true
expect(stub.args[0][0].attachments[0]).to.have.property('color', 'warning')
done()
})
})
Expand Down
Loading

0 comments on commit c4a3da9

Please sign in to comment.