-
Notifications
You must be signed in to change notification settings - Fork 6
/
handler-standalone.js
88 lines (77 loc) · 2.72 KB
/
handler-standalone.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
const schedule = require('node-schedule')
const { CaptureConsole } = require('@sentry/integrations')
const Sentry = require('@sentry/node')
const Tracing = require('@sentry/tracing')
const { hourlyCheck } = require('./announces')
const { asyncEventRouter } = require('./async-routes')
const wildbuttonApp = require('./wildbutton')
// If sentry is configured, use its express middleware, but also wrap it around asyncEventHandlers
// as well as hourly checks to catch all possible errors.
// Create a no-op helper for when Sentry is not used.
let sentryHelper = {
captureException: () => null,
startTransaction: (ctx) => ({
finish: () => null
})
}
const sentryInitCallback = {
init (app) {
if (process.env.SENTRY_DSN) {
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.SENTRY_ENVIRONMENT,
tracesSampleRate: 1.0,
integrations: [
new CaptureConsole(
{ levels: ['log', 'info', 'warn', 'error', 'assert'] }
),
new Sentry.Integrations.Http({ tracing: true }),
new Tracing.Integrations.Express({ app }),
new Tracing.Integrations.Mongo()
]
})
sentryHelper = {
captureException: Sentry.captureException,
startTransaction: Sentry.startTransaction
}
app.use(Sentry.Handlers.requestHandler())
app.use(Sentry.Handlers.tracingHandler())
console.debug('Sentry configured')
}
},
final (app) {
// The error handler must be before any other error middleware and after all controllers
app.use(Sentry.Handlers.errorHandler())
}
}
wildbuttonApp(asyncEventHandler, sentryInitCallback).listen(process.env.PORT, () => {
console.log(`A wild BUTTON appeared (standalone) listening on port ${process.env.PORT}`)
})
function initSchedule () {
const wrapHourlyCheck = async () => {
const transaction = sentryHelper.startTransaction({
op: 'hourly',
name: 'Hourly check'
})
try {
await hourlyCheck()
} catch (e) {
console.error(`Failed to perform hourly check, got error: ${e} in JSON: ${JSON.stringify(e)}`)
} finally {
transaction.finish()
}
}
schedule.scheduleJob('*/10 * * * *', wrapHourlyCheck)
}
initSchedule()
// In standalone mode, we can call the async router almost directly, except that we defer it
// to the next event loop to allow us to acknowledge Slack before doing event.
async function asyncEventHandler (eventObject) {
setImmediate(() => {
const transaction = sentryHelper.startTransaction({
op: `async_${eventObject.method}`,
name: `Async handling of ${eventObject.method}`
})
asyncEventRouter(eventObject).catch(Sentry.captureException).finally(() => transaction.finish())
})
}