Add initial sentry setup
Related to #343 but will probably need a few more changes
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
"dependencies": {
|
||||
"@redwoodjs/api": "^0.33.0",
|
||||
"@redwoodjs/api-server": "^0.33.0",
|
||||
"@sentry/node": "^6.5.1",
|
||||
"cloudinary": "^1.23.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
makeMergedSchema,
|
||||
makeServices,
|
||||
} from '@redwoodjs/api'
|
||||
import { createSentryApolloPlugin } from 'src/lib/sentry'
|
||||
|
||||
import schemas from 'src/graphql/**/*.{js,ts}'
|
||||
import services from 'src/services/**/*.{js,ts}'
|
||||
@@ -16,6 +17,9 @@ export const handler = createGraphQLHandler({
|
||||
schemas,
|
||||
services: makeServices({ services }),
|
||||
}),
|
||||
plugins: [
|
||||
createSentryApolloPlugin(),
|
||||
],
|
||||
onException: () => {
|
||||
// Disconnect from your database with an unhandled exception.
|
||||
db.$disconnect()
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { createUserInsecure } from 'src/services/users/users.js'
|
||||
import { db } from 'src/lib/db'
|
||||
import { sentryWrapper } from 'src/lib/sentry'
|
||||
import { enforceAlphaNumeric, generateUniqueString } from 'src/services/helpers'
|
||||
|
||||
export const handler = async (req, _context) => {
|
||||
const unWrappedHandler = async (req, _context) => {
|
||||
const body = JSON.parse(req.body)
|
||||
console.log(body)
|
||||
console.log(_context)
|
||||
@@ -82,3 +83,5 @@ export const handler = async (req, _context) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const handler = sentryWrapper(unWrappedHandler)
|
||||
|
||||
106
app/api/src/lib/sentry.ts
Normal file
106
app/api/src/lib/sentry.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import * as Sentry from '@sentry/node'
|
||||
import { context, Config, ApolloError } from '@redwoodjs/api'
|
||||
|
||||
let sentryInitialized = false
|
||||
if (process.env.SENTRY_DSN && !sentryInitialized) {
|
||||
Sentry.init({
|
||||
dsn: process.env.SENTRY_DSN,
|
||||
environment: process.env.CONTEXT,
|
||||
release: process.env.COMMIT_REF,
|
||||
})
|
||||
sentryInitialized = true
|
||||
}
|
||||
|
||||
async function reportError(error) {
|
||||
if (!sentryInitialized) return
|
||||
// If you do have authentication set up, we can add
|
||||
// some user data to help debug issues
|
||||
// if (context.currentUser) {
|
||||
// Sentry.configureScope((scope) => {
|
||||
// scope.setUser({
|
||||
// id: context?.currentUser?.id,
|
||||
// email: context?.currentUser?.email,
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
if (typeof error === 'string') {
|
||||
Sentry.captureMessage(error)
|
||||
} else {
|
||||
Sentry.captureException(error)
|
||||
}
|
||||
await Sentry.flush()
|
||||
}
|
||||
|
||||
export const sentryWrapper = (handler) => async (event, lambdaContext) => {
|
||||
lambdaContext.callbackWaitsForEmptyEventLoop = false
|
||||
try {
|
||||
return await new Promise((resolve, reject) => {
|
||||
const callback = (err, result) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
resolve(result)
|
||||
}
|
||||
}
|
||||
const resp = handler(event, lambdaContext, callback)
|
||||
if (resp?.then) {
|
||||
resp.then(resolve, reject)
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
// This catches both sync errors & promise
|
||||
// rejections, because we 'await' on the handler
|
||||
await reportError(e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
export const createSentryApolloPlugin: Config['plugins'][number] = () => ({
|
||||
requestDidStart: () => {
|
||||
return {
|
||||
didEncounterErrors(ctx) {
|
||||
// If we couldn't parse the operation, don't
|
||||
// do anything here
|
||||
if (!ctx.operation) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const err of ctx.errors) {
|
||||
// Only report internal server errors,
|
||||
// all errors extending ApolloError should be user-facing
|
||||
if (err instanceof ApolloError) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add scoped report details and send to Sentry
|
||||
Sentry.withScope(scope => {
|
||||
// Annotate whether failing operation was query/mutation/subscription
|
||||
scope.setTag("kind", ctx.operation.operation);
|
||||
|
||||
// Log query and variables as extras (make sure to strip out sensitive data!)
|
||||
scope.setExtra("query", ctx.request.query);
|
||||
scope.setExtra("variables", ctx.request.variables);
|
||||
|
||||
if (err.path) {
|
||||
// We can also add the path as breadcrumb
|
||||
scope.addBreadcrumb({
|
||||
category: "query-path",
|
||||
message: err.path.join(" > "),
|
||||
level: Sentry.Severity.Debug
|
||||
});
|
||||
}
|
||||
|
||||
const transactionId = ctx.request.http.headers.get(
|
||||
"x-transaction-id"
|
||||
);
|
||||
if (transactionId) {
|
||||
scope.setTransaction(transactionId);
|
||||
}
|
||||
|
||||
Sentry.captureException(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -8,7 +8,16 @@
|
||||
[web]
|
||||
port = 8910
|
||||
apiProxyPath = "/.netlify/functions"
|
||||
includeEnvironmentVariables = ['GOOGLE_ANALYTICS_ID', 'CLOUDINARY_API_KEY', 'CLOUDINARY_API_SECRET', 'CAD_LAMBDA_BASE_URL']
|
||||
includeEnvironmentVariables = [
|
||||
'GOOGLE_ANALYTICS_ID',
|
||||
'CLOUDINARY_API_KEY',
|
||||
'CLOUDINARY_API_SECRET',
|
||||
'CAD_LAMBDA_BASE_URL',
|
||||
'SENTRY_DSN',
|
||||
'SENTRY_AUTH_TOKEN',
|
||||
'SENTRY_ORG',
|
||||
'SENTRY_PROJECT'
|
||||
]
|
||||
# experimentalFastRefresh = true # this seems to break cascadeStudio
|
||||
[api]
|
||||
port = 8911
|
||||
@@ -18,3 +27,10 @@
|
||||
|
||||
[experimental]
|
||||
esbuild = false
|
||||
|
||||
[[plugins]]
|
||||
package = "@sentry/netlify-build-plugin"
|
||||
|
||||
[plugins.inputs]
|
||||
sentryOrg = "cadhub-org"
|
||||
sentryProject = "cadhub"
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"@redwoodjs/forms": "^0.33.0",
|
||||
"@redwoodjs/router": "^0.33.0",
|
||||
"@redwoodjs/web": "^0.33.0",
|
||||
"@sentry/browser": "^6.5.1",
|
||||
"browser-fs-access": "^0.17.2",
|
||||
"cloudinary-react": "^1.6.7",
|
||||
"controlkit": "^0.1.9",
|
||||
@@ -56,4 +57,4 @@
|
||||
"tailwindcss": "^2.1.2",
|
||||
"worker-loader": "^3.0.7"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { FatalErrorBoundary as FatalErrorBoundaryBase } from '@redwoodjs/web'
|
||||
import * as Sentry from '@sentry/browser'
|
||||
|
||||
class FatalErrorBoundary extends FatalErrorBoundaryBase {
|
||||
componentDidCatch(error, errorInfo) {
|
||||
Sentry.withScope((scope) => {
|
||||
scope.setExtras(errorInfo)
|
||||
Sentry.captureException(error)
|
||||
})
|
||||
}
|
||||
}
|
||||
export default FatalErrorBoundary
|
||||
@@ -2985,6 +2985,84 @@
|
||||
dependencies:
|
||||
any-observable "^0.3.0"
|
||||
|
||||
"@sentry/browser@^6.5.1":
|
||||
version "6.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.5.1.tgz#9a6ed5607b3b0f4e83f38720e3e202906f8c5bdb"
|
||||
integrity sha512-iVLCdEFwsoWAzE/hNknexPQjjDpMQV7mmaq9Z1P63bD6MfhwVTx4hG4pHn8HEvC38VvCVf1wv0v/LxtoODAYXg==
|
||||
dependencies:
|
||||
"@sentry/core" "6.5.1"
|
||||
"@sentry/types" "6.5.1"
|
||||
"@sentry/utils" "6.5.1"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sentry/core@6.5.1":
|
||||
version "6.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.5.1.tgz#c8b6c3ed86ed07b193c95d599c1b9a4a161e500e"
|
||||
integrity sha512-Mh3sl/iUOT1myHmM6RlDy2ARzkUClx/g4DAt1rJ/IpQBOlDYQraplXSIW80i/hzRgQDfwhwgf4wUa5DicKBjKw==
|
||||
dependencies:
|
||||
"@sentry/hub" "6.5.1"
|
||||
"@sentry/minimal" "6.5.1"
|
||||
"@sentry/types" "6.5.1"
|
||||
"@sentry/utils" "6.5.1"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sentry/hub@6.5.1":
|
||||
version "6.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.5.1.tgz#135ef09d07d32e87a53f664c0ae8fcc4f5963519"
|
||||
integrity sha512-lBRMBVMYP8B4PfRiM70murbtJAXiIAao/asDEMIRNGMP6pI2ArqXfJCBYDkStukhikYD0Kqb4trXq+JYF07Hbg==
|
||||
dependencies:
|
||||
"@sentry/types" "6.5.1"
|
||||
"@sentry/utils" "6.5.1"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sentry/minimal@6.5.1":
|
||||
version "6.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.5.1.tgz#b8c1b382c2ea788eec3d32d203e5081b00eb6838"
|
||||
integrity sha512-q9Do/oreu1RP695CXCLowVDuQyk7ilE6FGdz2QLpTXAfx8247qOwk6+zy9Kea/Djk93+BoSDVQUSneNiVwl0nQ==
|
||||
dependencies:
|
||||
"@sentry/hub" "6.5.1"
|
||||
"@sentry/types" "6.5.1"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sentry/node@^6.5.1":
|
||||
version "6.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/node/-/node-6.5.1.tgz#a572b380858de5aeaf98eade6d8d3afcba13d364"
|
||||
integrity sha512-Yh8J/QJ5e8gRBVL9VLCDpUvmiaxsxVZm0CInPHw3V/smgMkrzSKEiqxSeMq8ImPlaJrCFECqdpv4gnvYKI+mQQ==
|
||||
dependencies:
|
||||
"@sentry/core" "6.5.1"
|
||||
"@sentry/hub" "6.5.1"
|
||||
"@sentry/tracing" "6.5.1"
|
||||
"@sentry/types" "6.5.1"
|
||||
"@sentry/utils" "6.5.1"
|
||||
cookie "^0.4.1"
|
||||
https-proxy-agent "^5.0.0"
|
||||
lru_map "^0.3.3"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sentry/tracing@6.5.1":
|
||||
version "6.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-6.5.1.tgz#a5f3e497d4f1f319f36475df050e135cf65af750"
|
||||
integrity sha512-y1W/xFC2hAuKqSuuaovkElHY4pbli3XoXrreesg8PtO7ilX6ZbatOQbHsEsHQyoUv0F6aVA+MABOxWH2jt7tfw==
|
||||
dependencies:
|
||||
"@sentry/hub" "6.5.1"
|
||||
"@sentry/minimal" "6.5.1"
|
||||
"@sentry/types" "6.5.1"
|
||||
"@sentry/utils" "6.5.1"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sentry/types@6.5.1":
|
||||
version "6.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.5.1.tgz#0a34ecfd1ae9275a416a105640eb4bed45a46a1d"
|
||||
integrity sha512-b/7a6CMoytaeFPx4IBjfxPw3nPvsQh7ui1C8Vw0LxNNDgBwVhPLzUOWeLWbo5YZCVbGEMIWwtCUQYWxneceZSA==
|
||||
|
||||
"@sentry/utils@6.5.1":
|
||||
version "6.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.5.1.tgz#046baf7d1a6564d6d555437ad3674dba9bc0806a"
|
||||
integrity sha512-Wv86JYGQH+ZJ5XGFQX7h6ijl32667ikenoL9EyXMn8UoOYX/MLwZoQZin1P60wmKkYR9ifTNVmpaI9OoTaH+UQ==
|
||||
dependencies:
|
||||
"@sentry/types" "6.5.1"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sindresorhus/is@^0.14.0":
|
||||
version "0.14.0"
|
||||
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
|
||||
@@ -12660,6 +12738,11 @@ lru-memoizer@^2.1.2:
|
||||
lodash.clonedeep "^4.5.0"
|
||||
lru-cache "~4.0.0"
|
||||
|
||||
lru_map@^0.3.3:
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd"
|
||||
integrity sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0=
|
||||
|
||||
lz-string@^1.4.4:
|
||||
version "1.4.4"
|
||||
resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26"
|
||||
|
||||
Reference in New Issue
Block a user