Skip to content

Commit 336e57b

Browse files
arthurM2xdashed
andauthored
New Koa configuration (#1804)
* New Koa configuration Co-authored-by: Alberto Leal <[email protected]>
1 parent 244fed6 commit 336e57b

File tree

1 file changed

+103
-0
lines changed
  • src/collections/_documentation/performance-monitoring/configuration

1 file changed

+103
-0
lines changed
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
### Koa
2+
3+
Creates and attach a transaction to each context
4+
5+
```javascript
6+
const Sentry = require('@sentry/node')
7+
const { Span } = require('@sentry/apm')
8+
const Koa = require('koa')
9+
const app = new Koa()
10+
const domain = require('domain')
11+
12+
Sentry.init({
13+
dsn: "___PUBLIC_DSN___",
14+
tracesSampleRate: 0.25
15+
})
16+
17+
// not mandatory, but adding domains do help a lot with breadcrumbs
18+
const requestHandler = (ctx, next) => {
19+
return new Promise((resolve, reject) => {
20+
const local = domain.create()
21+
local.add(ctx)
22+
local.on('error', (err) => {
23+
ctx.status = err.status || 500
24+
ctx.body = err.message
25+
ctx.app.emit('error', err, ctx)
26+
})
27+
local.run(async() => {
28+
Sentry.getCurrentHub().configureScope(scope =>
29+
scope.addEventProcessor((event) => Sentry.Handlers.parseRequest(event, ctx.request, {user: false}))
30+
)
31+
await next()
32+
resolve()
33+
})
34+
})
35+
}
36+
37+
// this tracing middleware creates a transaction per request
38+
const tracingMiddleWare = async (ctx, next) => {
39+
// captures span of upstream app
40+
const sentryTraceId = ctx.request.get('sentry-trace')
41+
let traceId
42+
let parentSpanId
43+
if (sentryTraceId) {
44+
const span = Span.fromTraceparent(sentryTraceId)
45+
if (span) {
46+
traceId = span.traceId
47+
parentSpanId = span.parentSpanId
48+
}
49+
}
50+
const transaction = Sentry.startTransaction({
51+
name: `${ctx.method} ${ctx.url}`,
52+
op: 'http.server',
53+
parentSpanId,
54+
traceId,
55+
})
56+
ctx.__sentry_transaction = transaction
57+
await next()
58+
59+
// if using koa router, a nicer way to capture transaction using the matched route
60+
if (ctx._matchedRoute) {
61+
const mountPath = ctx.mountPath || ''
62+
transaction.setName(`${ctx.method} ${mountPath}${ctx._matchedRoute}`)
63+
}
64+
transaction.setHttpStatus(ctx.status)
65+
transaction.finish()
66+
}
67+
68+
app.use(requestHandler)
69+
app.use(tracingMiddleWare)
70+
71+
// usual error handler
72+
app.on('error', (err, ctx) => {
73+
Sentry.withScope(function (scope) {
74+
scope.addEventProcessor(function (event) {
75+
return Sentry.Handlers.parseRequest(event, ctx.request)
76+
})
77+
Sentry.captureException(err)
78+
})
79+
})
80+
// the rest of your app
81+
```
82+
83+
#### Subsequent manual child transactions
84+
85+
The following example creates a transaction for a part of the code that contains an expensive operation, and sends the result to Sentry, you will need to use the transaction stored in the context
86+
87+
```javascript
88+
const myMiddleware = async (ctx, next) => {
89+
let span
90+
const transaction = ctx.__sentry_transaction
91+
if (transaction) {
92+
span = transaction.startChild({
93+
description: route,
94+
op: 'myMiddleware',
95+
})
96+
}
97+
await myExpensiveOperation()
98+
if (span) {
99+
span.finish()
100+
}
101+
return next()
102+
}
103+
```

0 commit comments

Comments
 (0)