Add Sentry for api
parent
ff2b3bf207
commit
aebfce578c
|
@ -32,6 +32,8 @@
|
|||
"@koa/cors": "^3.3.0",
|
||||
"@koa/router": "^10.1.1",
|
||||
"@publicodes/api": "^1.0.0-beta.42",
|
||||
"@sentry/node": "^7.1.1",
|
||||
"@sentry/tracing": "^7.1.1",
|
||||
"koa": "^2.13.4",
|
||||
"koa-body": "^5.0.0",
|
||||
"koa-static": "^5.0.0",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import cors from '@koa/cors'
|
||||
import Router from '@koa/router'
|
||||
import Router, { RouterContext } from '@koa/router'
|
||||
import { koaMiddleware as publicodesAPI } from '@publicodes/api'
|
||||
import Koa from 'koa'
|
||||
import rules from 'modele-social'
|
||||
|
@ -7,6 +7,7 @@ import Engine from 'publicodes'
|
|||
import openapi from './openapi.json' assert { type: 'json' }
|
||||
import { docRoutes } from './route/doc.js'
|
||||
import { openapiRoutes } from './route/openapi.js'
|
||||
import Sentry, { requestHandler, tracingMiddleWare } from './sentry.js'
|
||||
|
||||
type State = Koa.DefaultState
|
||||
type Context = Koa.DefaultContext
|
||||
|
@ -14,6 +15,18 @@ type Context = Koa.DefaultContext
|
|||
const app = new Koa<State, Context>()
|
||||
const router = new Router<State, Context>()
|
||||
|
||||
app.use(requestHandler)
|
||||
app.use(tracingMiddleWare)
|
||||
|
||||
app.on('error', (err, ctx: RouterContext) => {
|
||||
Sentry.withScope((scope) => {
|
||||
scope.addEventProcessor((event) => {
|
||||
return Sentry.Handlers.parseRequest(event, ctx.request)
|
||||
})
|
||||
Sentry.captureException(err)
|
||||
})
|
||||
})
|
||||
|
||||
app.use(cors())
|
||||
|
||||
const apiRoutes = publicodesAPI(new Engine(rules))
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
import { RouterContext } from '@koa/router'
|
||||
import * as Sentry from '@sentry/node'
|
||||
import * as Tracing from '@sentry/tracing'
|
||||
// eslint-disable-next-line n/no-deprecated-api
|
||||
import Domains from 'domain'
|
||||
import { Context, Next } from 'koa'
|
||||
|
||||
Sentry.init({
|
||||
dsn: 'https://21ddaba2424b46b4b14185dba51b1288@sentry.incubateur.net/42',
|
||||
|
||||
// Set tracesSampleRate to 1.0 to capture 100%
|
||||
// of transactions for performance monitoring.
|
||||
// We recommend adjusting this value in production
|
||||
tracesSampleRate: 0.5,
|
||||
})
|
||||
|
||||
export default Sentry
|
||||
|
||||
// not mandatory, but adding domains does help a lot with breadcrumbs
|
||||
export const requestHandler = (ctx: Context, next: Next) => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
const local = Domains.create()
|
||||
local.add(ctx as never)
|
||||
local.on('error', (err) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
ctx.status = (err.status as number) || 500
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
ctx.body = err.message
|
||||
ctx.app.emit('error', err, ctx)
|
||||
})
|
||||
void local.run(async () => {
|
||||
Sentry.getCurrentHub().configureScope((scope) =>
|
||||
scope.addEventProcessor((event) =>
|
||||
Sentry.Handlers.parseRequest(event, ctx.request, { user: false })
|
||||
)
|
||||
)
|
||||
await next()
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// this tracing middleware creates a transaction per request
|
||||
export const tracingMiddleWare = async (ctx: RouterContext, next: Next) => {
|
||||
const reqMethod = (ctx.method || '').toUpperCase()
|
||||
const reqUrl = ctx.url && Tracing.stripUrlQueryAndFragment(ctx.url)
|
||||
|
||||
// connect to trace of upstream app
|
||||
let traceparentData
|
||||
if (ctx.request.get('sentry-trace')) {
|
||||
traceparentData = Tracing.extractTraceparentData(
|
||||
ctx.request.get('sentry-trace')
|
||||
)
|
||||
}
|
||||
|
||||
const transaction = Sentry.startTransaction({
|
||||
name: `${reqMethod} ${reqUrl}`,
|
||||
op: 'http.server',
|
||||
...traceparentData,
|
||||
})
|
||||
|
||||
ctx.__sentry_transaction = transaction
|
||||
|
||||
// We put the transaction on the scope so users can attach children to it
|
||||
Sentry.getCurrentHub().configureScope((scope) => {
|
||||
scope.setSpan(transaction)
|
||||
})
|
||||
|
||||
ctx.res.on('finish', () => {
|
||||
// Push `transaction.finish` to the next event loop so open spans have a chance to finish before the transaction closes
|
||||
setImmediate(() => {
|
||||
// if using koa router, a nicer way to capture transaction using the matched route
|
||||
if (ctx._matchedRoute) {
|
||||
const mountPath = (ctx.mountPath as undefined | string) || ''
|
||||
transaction.setName(
|
||||
`${reqMethod} ${mountPath}${ctx._matchedRoute.toString()}`
|
||||
)
|
||||
}
|
||||
transaction.setHttpStatus(ctx.status)
|
||||
transaction.finish()
|
||||
})
|
||||
})
|
||||
|
||||
await next()
|
||||
}
|
79
yarn.lock
79
yarn.lock
|
@ -4369,6 +4369,18 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/core@npm:7.1.1":
|
||||
version: 7.1.1
|
||||
resolution: "@sentry/core@npm:7.1.1"
|
||||
dependencies:
|
||||
"@sentry/hub": 7.1.1
|
||||
"@sentry/types": 7.1.1
|
||||
"@sentry/utils": 7.1.1
|
||||
tslib: ^1.9.3
|
||||
checksum: 687d46e7a0960cf595ae7ce392aaad2157653513cd1f92bf2bbcbfe6663365fab874a53f63220fcf1ad1312abe27bc871bc1e84abe5b60cd661642e661be4b6c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/hub@npm:6.19.6":
|
||||
version: 6.19.6
|
||||
resolution: "@sentry/hub@npm:6.19.6"
|
||||
|
@ -4380,6 +4392,17 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/hub@npm:7.1.1":
|
||||
version: 7.1.1
|
||||
resolution: "@sentry/hub@npm:7.1.1"
|
||||
dependencies:
|
||||
"@sentry/types": 7.1.1
|
||||
"@sentry/utils": 7.1.1
|
||||
tslib: ^1.9.3
|
||||
checksum: ddc61b31aa0f45ee9ea3f32173d6e49fa93fa8b83eb7d5ab0c53758f31731e1ae70a0730212ed3a0889ea47372e5919f511ad7c056dae2c18d31049caeb0c38c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/integrations@npm:^6.19.6":
|
||||
version: 6.19.6
|
||||
resolution: "@sentry/integrations@npm:6.19.6"
|
||||
|
@ -4403,6 +4426,22 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/node@npm:^7.1.1":
|
||||
version: 7.1.1
|
||||
resolution: "@sentry/node@npm:7.1.1"
|
||||
dependencies:
|
||||
"@sentry/core": 7.1.1
|
||||
"@sentry/hub": 7.1.1
|
||||
"@sentry/types": 7.1.1
|
||||
"@sentry/utils": 7.1.1
|
||||
cookie: ^0.4.1
|
||||
https-proxy-agent: ^5.0.0
|
||||
lru_map: ^0.3.3
|
||||
tslib: ^1.9.3
|
||||
checksum: ecda1b11356da01fbfbf0909fa7eead19c442ff6ef7bce9f7a5fadcdc220399014a42ac08614d6fa03e555084de00c0ef8904fb45e0682010ef5a8e2920692f9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/react@npm:^6.19.6":
|
||||
version: 6.19.6
|
||||
resolution: "@sentry/react@npm:6.19.6"
|
||||
|
@ -4432,6 +4471,18 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/tracing@npm:^7.1.1":
|
||||
version: 7.1.1
|
||||
resolution: "@sentry/tracing@npm:7.1.1"
|
||||
dependencies:
|
||||
"@sentry/hub": 7.1.1
|
||||
"@sentry/types": 7.1.1
|
||||
"@sentry/utils": 7.1.1
|
||||
tslib: ^1.9.3
|
||||
checksum: 3b11cc36eaf99c716185ccd80a0ec2e5b042a38cf4419ce5a0eeda7f81c7d097134e94c4aa6dfa45b23c83d8563b20ac6ad9cd47bbd164f363039672b971b87d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/types@npm:6.19.6":
|
||||
version: 6.19.6
|
||||
resolution: "@sentry/types@npm:6.19.6"
|
||||
|
@ -4439,6 +4490,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/types@npm:7.1.1":
|
||||
version: 7.1.1
|
||||
resolution: "@sentry/types@npm:7.1.1"
|
||||
checksum: 3f1b43782ca93c6520589b3739d4833cd00afb0f3ff72f5afaa42d4224c63163b1ef6bd167143b7d72667d0711f09fc4a42d36418ee242898a9cbd979dbac65d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/utils@npm:6.19.6":
|
||||
version: 6.19.6
|
||||
resolution: "@sentry/utils@npm:6.19.6"
|
||||
|
@ -4449,6 +4507,16 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/utils@npm:7.1.1":
|
||||
version: 7.1.1
|
||||
resolution: "@sentry/utils@npm:7.1.1"
|
||||
dependencies:
|
||||
"@sentry/types": 7.1.1
|
||||
tslib: ^1.9.3
|
||||
checksum: b36d0e03b007229cad81dc8db517c4bf58c8e7636aa80a575dc91fb605028c1a0b61e5f090704e04b5e9021fd8ec95b1a6f1465449f2a1a6c657b283295add71
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sideway/address@npm:^4.1.3":
|
||||
version: 4.1.4
|
||||
resolution: "@sideway/address@npm:4.1.4"
|
||||
|
@ -7770,6 +7838,8 @@ __metadata:
|
|||
"@koa/cors": ^3.3.0
|
||||
"@koa/router": ^10.1.1
|
||||
"@publicodes/api": ^1.0.0-beta.42
|
||||
"@sentry/node": ^7.1.1
|
||||
"@sentry/tracing": ^7.1.1
|
||||
"@types/koa": ^2.13.4
|
||||
"@types/koa-static": ^4.0.2
|
||||
"@types/koa__cors": ^3.3.0
|
||||
|
@ -9882,7 +9952,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cookie@npm:0.4.2":
|
||||
"cookie@npm:0.4.2, cookie@npm:^0.4.1":
|
||||
version: 0.4.2
|
||||
resolution: "cookie@npm:0.4.2"
|
||||
checksum: a00833c998bedf8e787b4c342defe5fa419abd96b32f4464f718b91022586b8f1bafbddd499288e75c037642493c83083da426c6a9080d309e3bd90fd11baa9b
|
||||
|
@ -15884,6 +15954,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lru_map@npm:^0.3.3":
|
||||
version: 0.3.3
|
||||
resolution: "lru_map@npm:0.3.3"
|
||||
checksum: ca9dd43c65ed7a4f117c548028101c5b6855e10923ea9d1f635af53ad20c5868ff428c364d454a7b57fe391b89c704982275410c3c5099cca5aeee00d76e169a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lz-string@npm:^1.4.4":
|
||||
version: 1.4.4
|
||||
resolution: "lz-string@npm:1.4.4"
|
||||
|
|
Loading…
Reference in New Issue