νμ¬ νλμ 무μμ λκΉ?
@sentry/nodeλ₯Ό μ¬μ©νμ¬ AWS λλ€ ν¨μμμ μμΈλ₯Ό μΊ‘μ²νκ³ μμ΅λλ€.
.catch(err => {
Sentry.captureException(err)
context.fail()
})
κ·Έλ¬λ context.fail()
κ° νΈμΆλκ³ μμΈκ° Sentryμμ λλμ§ μμ λ νλ‘μΈμ€λ₯Ό μ’
λ£ν©λλ€.
λ€μκ³Ό κ°μ ν΄κ²° λ°©λ²μ μνν μ μμ΅λλ€.
.catch(err => {
Sentry.captureException(err)
setTimeout(() => context.fail(), 1000)
})
μμλλ λμμ 무μμ λκΉ?
λ€μκ³Ό κ°μ΄ ν μ μλ€λ©΄ μ’μ κ²μ λλ€.
.catch(err => {
Sentry.captureException(err, () => context.fail())
})
λλ μ μμ μΌλ‘ μ½λ°±μ μ²λ¦¬νλ κ²μ΄ μμ΅λλ€.
μ΄κ²μ https://blog.sentry.io/2018/06/20/how-droplr-uses-sentry-to-debug-serverless λ₯Ό μΆμΈ‘νλ λ° λμμ΄ λ μ μμ΅λλ€(μ½λ°±μ΄ μλ μ€λλ κΉλ§κ· λ²μ μ μ¬μ©νκ³ μμ§λ§ μ λ λλΆλΆ callbackWaitsForEmptyEventLoop
νλκ·Έλ₯Ό κ°λ¦¬ν΅λλ€.
μμ§ κ³΅μμ μΈ λ°©λ²μ μμ΅λλ€. μμ§ λ² ν λ²μ μΌλ‘ ν μ€νΈ μ€μ΄λ―λ‘ λ€μ μ½λλ‘ κ°λ₯ν©λλ€.
import { init, getDefaultHub } from '@sentry/node';
init({
dsn: 'https://my-dsn.com/1337'
});
exports.myHandler = async function(event, context) {
// your code
await getDefaultHub().getClient().captureException(error, getDefaultHub().getScope());
context.fail();
}
@kamilogorek ν¬μΈν° μ£Όμ μ κ°μ¬ν©λλ€. λλ κ·Έκ²μ μλνκ³ νμ΅μ μ¬μν©λλ€.
@kamilogorek λΉμ μ μ μμ΄ ν¨κ³Όκ° μμ΅λλ€. μ’ λ 곡μμ μΈ λ°©λ²μ κΈ°λνκ³ μμ΅λλ€.
@vietbui
4.0.0-rc.1
μμ μ°λ¦¬λ close
λΌλ ν΄λΌμ΄μΈνΈμ ν¨μλ₯Ό λμ
νμΌλ©° λ€μκ³Ό κ°μ΄ νΈμΆν©λλ€.
import { getCurrentHub } from '@sentry/node';
getCurrentHub().getClient().close(2000).then(result => {
if (!result) {
console.log('We reached the timeout for emptying the request buffer, still exiting now!');
}
global.process.exit(1);
})
close
λ λͺ¨λ μμ²μ΄ μ μ‘λ λκΉμ§ κΈ°λ€λ¦¬λ©° μκ° μ΄κ³Ό(μ΄ μμμλ 2000ms)μ λλ¬ν λκΉμ§ νμ ν΄κ²°λ©λλ€(κ²°κ³Ό = false μκ° μ΄κ³Όμ λλ¬ν¨).
μ΄κ²μ μ°λ¦¬μ 곡μ APIμ
λλ€.
μ΄μ μ κ·Ό λ°©μμ μ¬μ ν ββμλνμ§λ§ close
λ°©λ²μ λͺ¨λ κ²½μ°μ μλν©λλ€.
@HazAT λ°κ°μ΅λλ€. λͺ¨λ λ Έλ ₯μ κ°μ¬λ립λλ€.
4.0.3μμλ λλ€ ν¨μμμ λ€μκ³Ό κ°μ΄ νΈμΆν©λλ€.
try {
...
} catch (err) {
await getCurrentHub().getClient().captureException(err, getCurrentHub().getScope())
throw err
}
getDefaultHub()λ λ μ΄μ μ¬μ©ν μ μμ΅λλ€.
@vietbui μ§κΈμ getCurrentHub
λΌκ³ ν©λλ€. APIλ₯Ό λ€λ₯Έ μΈμ΄ SDKμ ν΅ν©ν΄μΌ νκΈ° λλ¬Έμ
λλ€.
@kamilogorek μ€λͺ
κ°μ¬ν©λλ€. getCurrentHub
μ κ·Ό λ°©μμ λ¬Έμ κ° μμ΅λλ€. μ΄λ»κ²λ μ€μ ν λ²μκ° Sentryμμ λλμ§ μμκΈ° λλ¬Έμ
λλ€.
κ²°κ΅ λ΄ λλ€ ν¨μμμ μμΈλ₯Ό μΊ‘μ²νκΈ° μν΄ @HazAT κ° μ μν λλ‘ λ€λ₯Έ μ κ·Ό λ°©μμ μ·¨νμ΅λλ€.
try {
...
} catch (err) {
Sentry.captureException(err)
await new Promise(resolve => Sentry.getCurrentHub().getClient().close(2000).then(resolve))
throw err
}
κ·Έλ¦¬κ³ κ·Έκ²μ μλ²½νκ² μλν©λλ€.
μ΄κ²μ μΌνΈλ¦¬κ° μ΄λ²€νΈλ₯Ό 보λ΄λλ‘ λκΈ°/κ°μ νλ κΆμ₯ λ°©λ²μ λκΉ?
@albinekb λ€ - https://docs.sentry.io/learn/draining/?platform=browser
@albinekb μ β https://docs.sentry.io/learn/draining/?platform=browser
μ΄ μ루μ μ μ΄λ€ μ΄μ λ‘ μλνμ§ μμ΅λλ€. μ½λ μ€ννΈ ββμκ°μ΄ μμ λ νλ‘λμ μμ μ²μμΌλ‘ μλνκ³ κ·Έ μ΄νμλ μλνμ§ μμ΅λλ€. μ¬κΈ°μ μμ μ½λκ° μμ΅λλ€
'use strict'
const Sentry = require('@sentry/node')
Sentry.init({
dsn: 'xxx',
environment: process.env.STAGE
});
module.exports.createPlaylist = async (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false
if(!event.body) {
Sentry.captureException(error)
await new Promise(resolve => Sentry.getCurrentHub().getClient().close(2000).then(resolve))
return {
statusCode: 500,
headers: { 'Content-Type': 'text/plain' },
body: 'Missing body parameters'
}
}
return {
statusCode: 200,
}
};
@Andriy-Kulak λν λ¬Έμμ λ€μκ³Ό κ°μ΄ λͺ μλμ΄ μμ΅λλ€.
After shutdown the client cannot be used any more so make sure to only do that right before you shut down the application.
λ°λΌμ μμ© νλ‘κ·Έλ¨μ΄ μΈμ μ’ λ£λ μ§ λͺ¨λ₯΄λ λλ€μμ μ΄κ²μ μ΄λ»κ² μ²λ¦¬ν μ μλμ§ λͺ¨λ₯΄κ² μ΅λλ€. μ΄μ APIμμμ κ°μ΄ μμ²λΉ μΌνΈλ¦¬λ₯Ό λ°°μνλ κ²μ΄ κ°μ₯ μ’μ΅λκΉ?
@HazAT μ΄κ²μ λ€μ μ΄ μ μμ΅λκΉ? μ λ Lambdaμμ μ΄ μμ μ μνν μ μλ λ°©λ²μ κ°λ κ²μ΄ μ€μνλ€κ³ μκ°ν©λλ€. Lambdaλ λ°°ν¬ λμμ΄ μ μ λ λ§μμ§κ³ μμ΅λλ€.
μ΄κ²μ νμ¬ μ΅μ λ²μ μΌλ‘ μ κ·Έλ μ΄λνλ κ²μ μ°¨λ¨νκ³ μμ΅λλ€...
κ°μΈμ μΌλ‘ μ€λ₯λ₯Ό λ³΄κ³ ν λ μ½μ/μ½λ°±μ λ°μ μ μλ κ²μ μ νΈν©λλ€. λμ€μ μ€μ λ‘ λ«μ§ μκ³ λκΈ°μ΄μ λΉμΈ μμλ λ°©λ²μ΄ μμΌλ©΄ μ°¨μ μ± μ΄ λ κ²μ λλ€ ...
captureException
μμ μ½λ°±μ μ κ±°ν μ΄μ λ 무μμ
λκΉ?
@albinekb λ€μ μ€μ μ κ±°νλ©΄ μ ν μλνμ§ μμ΅λλ€
await new Promise(resolve => Sentry.getCurrentHub().getClient().close(2000).then(resolve))
@LinusU μ루μ μ΄ λ¬΄μμ΄λ©° μΌνΈλ¦¬ λλ λ μ΄λΈ μ루μ μ μ¬μ©νκ³ μμ΅λκΉ?
λμκ² κΈ°λ³Έμ μΌλ‘ λ€μμ sentry/node @4.3.0
μ ν¨κ» μλνμ§λ§ λλ€κ° μΌνΈλ¦¬κ° νμν μμ
μ μνν λκΉμ§ μΌμ μκ°(μ΄ κ²½μ° 2μ΄)μ μλμΌλ‘ κΈ°λ€λ¦¬κ² ν΄μΌ ν©λλ€. Sentryκ° captureException
μμ²μ μλ£νκΈ°λ₯Ό κΈ°λ€λ¦¬κ³ μκΈ° λλ¬Έμ μ κ±°κΈ°μ μμ΄μΌ νλμ§ μ λͺ¨λ₯΄κ² μ΅λλ€. μ΄νμ λκΈ° μκ°μ΄ μμΌλ©΄ μΌνΈλ¦¬κ° μ€λ₯λ₯Ό 보λ΄μ§ μλ κ² κ°μ΅λλ€.
'use strict'
const Sentry = require('@sentry/node')
Sentry.init({
dsn: 'xxx',
environment: process.env.STAGE
});
module.exports.createPlaylist = async (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false
if(!event.body) {
const error = new Error('Missing body parameters in createPlaylist')
await Sentry.captureException(error)
await new Promise(resolve => {setTimeout(resolve, 2000)})
return {
statusCode: 500,
headers: { 'Content-Type': 'text/plain' },
body: 'Missing body parameters'
}
}
return {
statusCode: 200,
}
};
μ°λ¦¬λ λν Lambdaμμ μ΄κ²μ λν΄ λΆνκ³ μμ΅λλ€. μ°λ¦¬λ μλ‘μ΄ libsλ‘ μμνκ³ RavenμΌλ‘ λμκ° κ²μ κ³ λ €νλ©΄μ μμ ν μμμμ λ²μ΄λ¬μ΅λλ€. μ°λ¦¬λ μ§κΈ νλΈλ₯Ό λ«κ³ λ€μ μ΄κΈ°ννκΈ° μν΄ ν μ€νΈλ₯Ό μμ±νκ³ μμ΅λλ€. νλΈμ λ¬Όμ΄ λ¨μ μλ κ²½μ° μ€ν κ°λ₯ν ν΄κ²° λ°©λ²μ΄ λ κ²μ λλ€. κ·Έλ¬λ μ¬μ ν ν΄ν€/λ‘λ μ λ¬Έμ λ₯Ό μΌμΌν¬ κ°λ₯μ±μ΄ μμ΅λλ€.
κ°μΈμ μΌλ‘ λλ μ½μμ λ°ννλ μΌμ’
μ flush()
λ₯Ό μ νΈν©λλ€. λ¨μ μ μ°ΎκΈ°κ° μ΄λ ΅μ΅λλ€. κ·Έλ° μΌμ΄ μΌμ΄λ κ±°λΌκ³ μκ°ν΄?
μ루μ μ 무μμ΄λ©° μΌνΈλ¦¬ λλ λ μ΄λΈ μ루μ μ μ¬μ©νκ³ μμ΅λκΉ?
λ€μ μ΅μ€νλ μ€ μ€λ₯ μ²λ¦¬κΈ°λ₯Ό μ¬μ©νκ³ μμ΅λλ€.
app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
let status = (err.status || err.statusCode || 500) as number
if (process.env.NODE_ENV === 'test') {
return next(err)
}
if (status < 400 || status >= 500) {
Raven.captureException(err, () => next(err))
} else {
next(err)
}
})
κ·Έλ° λ€μ μ€μΉΈλμ μ μ¬μ©νμ¬ Express μ±μ Lambdaμ λ°°ν¬ν©λλ€.
νΈμ§: μ΄κ²μ Raven "raven": "^2.6.3",
μ
λλ€.
λλ¦Ό APIλ μ΄λ κ² μ£ π
Sentry.captureException(err: Error): Promise<void>
@LinusU https://github.com/getsentry/sentry-javascript/blob/master/packages/core/src/baseclient.ts#L145 -L152 π
κ·Έλ¬λ κ·Έκ²μ μ»μΌλ €λ©΄ ν΄λΌμ΄μΈνΈ μΈμ€ν΄μ€λ₯Ό μ§μ μ¬μ©ν΄μΌν©λλ€. κ·Έ μ΄μ λ μ£Όμ μλ리μ€κ° "λ°μ¬ ν μμ΄λ²λ¦¬λ" μ νμ λμμ΄λ―λ‘ λΉλκΈ° λ°©μμ΄ μλλΌκ³ κ²°μ νκΈ° λλ¬Έμ λλ€. κ·Έλ¬λ λ΄λΆμ μΌλ‘λ μ체μ μΌλ‘ μ¬μ©νλ λΉλκΈ° APIκ° μμ΅λλ€.
λ΄κ° μ€μ λ‘ μνλ κ²μ λ€μκ³Ό κ°μ κ² κ°μ΅λλ€.
const backend = client.getBackend()
const event = await backend.eventFromException(error)
await client.processEvent(event, finalEvent => backend.sendEvent(finalEvent))
λͺ¨λ νμκ³Ό λ²νΌλ§μ 건λλ°λ €λ©΄...
λλ λμμΈμ΄ "fire and forgot"μ λ§μΆ°μ Έ μκ³ μ₯κΈ° μ€ν μλ²μμ μ€νλλ€λ κ²μ μμμ΅λλ€. λ²νΌλ§ λ±μ λ§μ΄ νκΈ° λλ¬Έμ μλ§λ κ½€ μ’μ κ²μ λλ€. λ¬Έμ λ μ΄κ²μ΄ μ λ°λλΌλ κ²μ λλ€. μ μ λ 보νΈνλκ³ μλ Lambda, App Engine λ° κΈ°ν "μλ²λ¦¬μ€" μν€ν μ²μ λν΄ μνλ κ²μ λλ€.
κ°λ₯ν ν 빨리 μ΄λ²€νΈλ₯Ό 보λ΄κ³ await
ν μ μλ Promise
λ₯Ό λ°ννλ νΉλ³ν λ©μλλ₯Ό κ°μ§ μ μμ΅λκΉ? μλ²λ¦¬μ€ μλ리μ€μ μ ν©ν©λλ€!
class Sentry {
// ...
async unbufferedCaptureException(err: Error): Promise<void> {
const backend = this.client.getBackend()
const event = await backend.eventFromException(error)
await this.client.processEvent(event, finalEvent => backend.sendEvent(finalEvent))
}
// ...
}
@LinusU μ°λ¦¬λ μ΄ μλ리μ€λ₯Ό μν νΉμ μλ²λ¦¬μ€ ν¨ν€μ§λ₯Ό μμ±ν κ°λ₯μ±μ΄ λμ΅λλ€. μ°λ§μ΄κ³ μ§κΈ μ¬λλ€μ΄ λ§μ΄ λͺ°λ¦¬κΈ° λλ¬Έμ μκ°μ μ°ΎμμΌ ν©λλ€. κ³μ μλ €λ립λλ€!
μ΄ μλ리μ€μ λν νΉμ μλ²λ¦¬μ€ ν¨ν€μ§λ₯Ό λ§λ€ κ°λ₯μ±μ΄ ν½λλ€.
κ·Έκ²μ λλΌμ΄ κ²μ λλ€! π
@mtford90
μ΄ λ λμ μ루μ μ μ νν μΈμ μ¬μ©ν©λκΉ? λ΄κ° μλ ν λλ€κ° μΈμ μ’ λ£λ μ§ μ μ μμ΅λλ€. κ²λ€κ° μΌνΈλ¦¬κ° μλν μ μλλ‘ μμμ μκ° λμ μ’ λ£λ₯Ό κΈ°λ€λ¦¬λ κ²μ μ΄λ¦¬μμ μΌμ λλ€. νΉν κ³ κ°μ λμ λ©λͺ¨λ¦¬/CPU λλ€ κΈ°λ₯μμ κ·Έλ μ΅λλ€.
(λ°°μΆμ λν΄ μ΄μΌκΈ°)
μλ² νλ‘μΈμ€λ₯Ό μ’
λ£νκΈ° μ μ λ§μ§λ§μΌλ‘ μ¬μ©νκΈ° μν κ²μ
λλ€. drain
λ©μλμ μκ° μ΄κ³Όλ νλ‘μΈμ€λ₯Ό μ’
λ£νκΈ° μ μ λκΈ°ν μ΅λ μκ°μ΄λ©°, μ΄κ²μ΄ νμ ν΄λΉ μκ°μ μ¬μ©νλ€λ μλ―Έλ μλλλ€. μλ²κ° μμ ν μλ΅νλ©΄ λλ¨Έμ§ λͺ¨λ μ΄λ²€νΈλ₯Ό μ¦μ 보λ
λλ€.
μ΄κ²μ κ·Έ μμ²΄λ‘ μ μ μλ λ°©λ²μ μμ§λ§ νΈλ€λ¬μ μ½λ°± μΈμλ₯Ό μ¬μ©νμ¬ μΈμ μ’ λ£λμ΄μΌ νλμ§ λλ€μ μ리λ λ°©λ²μ μμ΅λλ€.
λν @LinusU , κ·νμ μ΄μ μ견, νΉν μ΄ λΆλΆμ λ€μ μ½μμ΅λλ€.
κ°λ₯ν ν 빨리 μ΄λ²€νΈλ₯Ό 보λ΄κ³ μ°λ¦¬κ° κΈ°λ€λ¦΄ μ μλ Promiseλ₯Ό λ°ννλ νΉλ³ν λ©μλλ₯Ό κ°μ§ μ μμ΅λκΉ? μλ²λ¦¬μ€ μλ리μ€μ μ ν©ν©λλ€!
μ΄κ²μ΄ μ°λ¦¬κ° λ²νΌλ₯Ό ꡬνν λ°©λ²μ
λλ€. ν΄λΌμ΄μΈνΈμ λν λͺ¨λ captureX
νΈμΆμ λ²νΌμ μΆκ°ν©λλ€. λ§μ΅λλ€. νμ§λ§ μ΄λ€ μμΌλ‘λ νμ λ£μ§ μκ³ μ¦μ μ€νλλ©° μ΄ ν¨ν΄μ λͺ¨λ κ²μ΄ Sentryλ‘ μ±κ³΅μ μΌλ‘ μ μ‘λμμ΅λλ€.
μ¦, AWS Lambdaμμ μ΄μ κ°μ μμ μ μννλ κ²½μ°(κ°μ₯ κ°λ¨ν κ²½μ°μΈ κΈ°λ³Έ ν΄λΌμ΄μΈνΈλ₯Ό μ¬μ©νλ€κ³ κ°μ ):
import * as Sentry from '@sentry/browser';
Sentry.init({ dsn: '__YOUR_DSN__' });
exports.handler = (event, context, callback) => {
try {
// do something
catch (err) {
Sentry.getCurrentHub()
.getClient()
.captureException(err)
.then((status) => {
// request status
callback(null, 'Hello from Lambda');
})
}
};
μ¦μ μ μ‘λμμΌλ©° νμ΄λ°/νλ‘μΈμ± μ€λ²ν€λκ° μμμ νμΈν μ μμ΅λλ€.
@kamilogorek
μ΄κ²μ μ΄μ κ°μ κ²μ΄ λΉλκΈ°/λκΈ° μ²λ¦¬κΈ°(μ½λ°±μ μ¬μ©νμ§ μλ κ³³)μμ μλν΄μΌ ν¨μ μλ―Έν©λκΉ?
import * as Sentry from '@sentry/node';
Sentry.init({ dsn: '__YOUR_DSN__' });
exports.handler = async (event, context) => {
try {
// do something
return 'Hello from Lambda';
catch (err) {
await Sentry.getCurrentHub().getClient().captureException(err);
return 'Hello from Lambda with error';
}
};
@jviolas μμ ν! :)
λ€μ λ³κ²½ μ¬νμ΄ μ μκ² ν¨κ³Όμ μΌ κ² κ°μ΅λλ€ βΊοΈ
-import Raven = require('raven')
+import * as Sentry from '@sentry/node'
// ...
-Raven.config(config.SENTRY_DSN)
+Sentry.init({ dsn: config.SENTRY_DSN })
// ...
app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
let status = (err.status || err.statusCode || 500) as number
if (process.env.NODE_ENV === 'test') {
return next(err)
}
if (status < 400 || status >= 500) {
- Raven.captureException(err, () => next(err))
+ Sentry.getCurrentHub().getClient().captureException(err).then(() => next(err))
} else {
next(err)
}
})
μμ§ν λμ¬ νλνλκ° μ’ λͺ»μκ²Όμ΄μπ κ·Όλ° μμ λ λμκ±° κ°μμ...
@kamilogorek μΉμ¬μ΄νΈμ λ¬Έμμμ getCurrentHub()
λ₯Ό μ°Ύμ μ μμ΅λλ€. μ΄ APIκ° ν° μΆ©λ μμ΄ μ€λ¨λμ§ μλλ€κ³ 보μ₯λλμ? β€οΈ
@kamilogorek μΉ μ¬μ΄νΈμ λ¬Έμμμ getCurrentHub()λ₯Ό μ°Ύμ μ μμ΅λλ€. μ΄ APIλ ν° μΆ©λ μμ΄ μ€λ¨λμ§ μλλ€κ³ 보μ₯λ©λκΉ? β€οΈ
μ, 보μ₯λ©λλ€. μ¬κΈ°μ μ€λͺ
λ @sentry/hub
ν¨ν€μ§μ μΌλΆμ
λλ€ - https://docs.sentry.io/enriching-error-data/scopes/?platform=browser
μ°λ¦¬λ μ΄ μ€λ λμμ μΌμ’ μ "κ³ κΈ μ¬μ©"μ λν΄ λ Όμνκ³ μμΌλ©° μμ§ λ¬Έμνν λ¨κ³μ μ΄λ₯΄μ§ λͺ»νμ΅λλ€. μ°λ¦¬λ κ²°κ΅ μ΄κ²μ ν κ²μ λλ€ :)
μ¬κΈ°μ μ°λ¦¬κ° λμΉκ³ μλ κ²μ μ΄λ¬ν μ’
λ₯μ κ³ κΈ μ¬μ© μ¬λ‘μ λν λͺ κ°μ§ λ¬Έμμ λͺ¨λ² μ¬λ‘μ
λλ€. λ¬Έμνλκ±°λ λΈλ‘κ·Έ κ²μλ¬Όλ μ’μ μμμ΄ λ μ μμ λ μ λ§ μ’μ΅λλ€.
κ·Έλ μ§ μμΌλ©΄ μ SDKλ μ¬μ©νκΈ°κ° μ λ§ κ°νΈνκ³ ν΅ν©μ΄ μ λ§ μ’μ΅λλ€.
@kamilogorek
μ΄κ²μ μ΄μ κ°μ κ²μ΄ λΉλκΈ°/λκΈ° μ²λ¦¬κΈ°(μ½λ°±μ μ¬μ©νμ§ μλ κ³³)μμ μλν΄μΌ ν¨μ μλ―Έν©λκΉ?import * as Sentry from '@sentry/node'; Sentry.init({ dsn: '__YOUR_DSN__' }); exports.handler = async (event, context) => { try { // do something return 'Hello from Lambda'; catch (err) { await Sentry.getCurrentHub().getClient().captureException(err); return 'Hello from Lambda with error'; } };
μΆκ° 컨ν μ€νΈλ₯Ό μΆκ°ν μ μλ€λ μ μ μ μΈνκ³ μμμ μ μν λλ‘ μμ μ μννλ©΄ λ©λλ€. μλ₯Ό λ€μ΄ λ€μκ³Ό κ°μ΄ νλ©΄
Sentry.configureScope(scope => {
scope.setExtra('someExtraInformation', information);
});
await Sentry.getCurrentHub().getClient().captureException(err);
Sentryμμ μ€μ λ‘ 'someExtraInformation'μ λ³Ό μ μμ΅λλ€.
λκ΅°κ°κ° μ΄ μ€λ λμ 맨 μμ λ€λ₯Έ λ°©λ²μ μ μνλλ° μλνμ§λ§ ν΄νΉλ κ²μ²λΌ 보μ λλ€(μκ° μ΄κ³Ό κ°μ μ μ©).
Sentry.configureScope(scope => {
scope.setExtra('someExtraInformation', information);
});
Sentry.captureException(error);
await new Promise(resolve => Sentry.getCurrentHub().getClient().close(2000).then(resolve));
@kamilogorek @jviolas
import * as Sentry from '@sentry/node'; Sentry.init({ dsn: '__YOUR_DSN__' }); exports.handler = async (event, context) => { try { // do something return 'Hello from Lambda'; catch (err) { await Sentry.getCurrentHub().getClient().captureException(err); return 'Hello from Lambda with error'; } };
μ΄κ²μ _μ‘νμ§ μμ μμΈ_μλ μ μ©λ μ μμ΅λκΉ? Sentry.Integrations.OnUncaughtException
ν΅ν©μ μμ νλ κ²μ΄ 곡μμ μΈ λ°©λ²μΈ κ² κ°μ§λ§ λ¬Έμλ νμ¬ λ§€μ° μ΄μ
ν©λλ€.
μ΄κ²μ λν΄ +1. μ μ΄λ 곡μμ μΌλ‘ λ¬Έμν λ κ²μ΄ μμΌλ©΄ μ’μ κ²μ
λλ€. Serverlessλ 2019λ
νμ¬ λΉ λ₯΄κ² μ±μ₯νκ³ μμ΅λλ€. Sentryμ 곡μ μ§μμ μ λ§ λ³΄κ³ μΆμ΅λλ€. μ¬κΈ°μμ μ½κ³ μ λ§ λ§μμ λ€μλ μμ΄λμ΄ μ€ νλλ Sentry.flush()
μ κ°μ κ²μ μ¬μ©νμ¬ λκΈ° μ€μΈ λͺ¨λ μ΄λ²€νΈλ₯Ό 보λ΄λ κ²μ΄μμ΅λλ€.
@rdsedmundo μ΄ μ κ·Ό λ°©μμ΄ ν¨κ³Όκ° μλ μ΄μ λ₯Ό μμΈν μ€λͺ ν΄ μ£Όμκ² μ΅λκΉ?
import * as Sentry from '@sentry/node';
Sentry.getCurrentHub().getClient().close(2000).then(result => {
if (!result) {
console.log('We reached the timeout for emptying the request buffer, still exiting now!');
}
global.process.exit(1);
})
μ΄κ²μ μ°λ¦¬μ 곡μμ μΈ μ κ·Ό λ°©μμ΄λ©° κΈ°λ³Έμ μΌλ‘ Sentry.flush()
μ
λλ€.
μ°Έμ‘°: https://docs.sentry.io/error-reporting/configuration/draining/?platform=javascript
@HazAT AWS Lambda 컨ν
μ΄λ μ¬μ¬μ©μ λν΄ μκ°ν λ λ¬Έμ κ° λ°μν©λλ€. μ΄λ TL;DR μ©μ΄λ‘ μμ²μ μ²λ¦¬ν νλ‘μΈμ€κ° 짧μ μκ° λ΄μ μ΄λ£¨μ΄μ§λ©΄ μλ‘μ΄ λΈλλλ₯Ό μ 곡ν μ μμμ μλ―Έν©λλ€. λΉμ μ΄ μ 곡ν μ΄ μ€λν«κ³Όμ μ°κ²°μ λ«κ³ 컨ν
μ΄λκ° μ¬μ¬μ©λλ€λ©΄, μ μμ²μ μν μ νλΈλ₯Ό μμ±νλλ‘ κ΄λ¦¬ν΄μΌ ν κ²μ
λλ€. λλ μ΄κ²μ΄ κΉλ€λ‘μμ§λ κ²μ μ½κ² λ³Ό μ μλ€. μ΄κ²μ΄ κ°λ¨ν await Sentry.flush()
κ° λ λμ μ루μ
μΈ μ΄μ μ
λλ€.
import Sentry from './sentry'; // this calls Sentry.init under the hood
export const handler = async (event, context) => {
try {
...
} catch (error) {
Sentry.captureException(error);
await Sentry.flush(); // could even be called on the finally block
return formatError(error);
}
}
@rdsedmundo μ κ° λκ°λ₯Ό μλͺ» μ΄ν΄νκ³ μλμ§ μ λͺ¨λ₯΄κ² μ§λ§ κ·Έλ κ² νμλ©΄
import Sentry from './sentry'; // this calls Sentry.init under the hood
export const handler = async (event, context) => {
try {
...
} catch (error) {
Sentry.captureException(error);
await Sentry.getCurrentHub().getClient().close(2000);
return formatError(error);
}
}
μκ° μ νμ μ μνλ κ²μ await Sentry.flush
μ μ νν κ°μ΅λλ€.
2000ms νμ λκΈ°μ΄μ μ¬μ ν λ¬Όκ±΄μ΄ μμΌλ©΄ false
λ‘ μ½μμ΄ ν΄κ²°λ©λλ€.
κ·Έλ μ§ μμΌλ©΄ close
λ μκ° μ΄κ³Όμ λλ¬νκΈ° μ μ λκΈ°μ΄μ΄ λΉμμ§λ©΄ true
λ‘ ν΄κ²°λ©λλ€.
μλλ©΄ λͺ¨λ μ½μμ΄ ν΄κ²°λκΈ° μ μ 컨ν μ΄λκ° μ¬μ¬μ©λ©λκΉ? (그건 μμλ λͺ»ν¨)
@HazAT λ close(...)
μ΄ ν΄λΌμ΄μΈνΈλ₯Ό λ€μ μ¬μ©νμ§ λͺ»νκ² νλ λ¬Έμ κ° μλκ°μ? Lambdaλ λμΌν Node νλ‘μΈμ€λ₯Ό μ¬μ¬μ©νλ―λ‘ close
μ λν 첫 λ²μ§Έ νΈμΆ νμ μλμ΄ μ€μ§λ κ² κ°μ΅λλ€.
Sentry.init()
Sentry.captureException()
Sentry.getCurrentHub().getClient().close()
Sentry.captureException()
Sentry.getCurrentHub().getClient().close()
Sentry.captureException()
Sentry.getCurrentHub().getClient().close()
Sentry.captureException()
Sentry.getCurrentHub().getClient().close()
μλμ, close
λ ν΄λΌμ΄μΈνΈλ₯Ό μμ νμ§ μμΌλ©° μ μ‘ λκΈ°μ΄μ λΉμ°κΈ° μν κ²μ
λλ€.
μ΄ μ»¨ν
μ€νΈμμ close
λΌλ μ΄λ¦μ΄ μ€ν΄μ μμ§κ° μμ§λ§ μ μ΄λ JS/Nodeμμλ close
λΌλ μ΄λ¦μ΄ ν΄λΌμ΄μΈνΈμ μ무 κ΄κ³κ° μμΌλ©° λμ€μ κ³μ μ¬μ©νλ κ²μ΄ μ’μ΅λλ€.
νΈμ§: κ·Έκ²μ΄ μ€μ λ‘ "λ¬Έμ "μλ€λ©΄ μ΄λ₯Ό λͺ νν νκΈ° μν΄ λ¬Έμλ₯Ό μ λ°μ΄νΈνκ² μ΅λλ€.
μμν. κ·Έλ¬λ λ¬Έμκ° μλͺ»λμμ΅λλ€.
After shutdown the client cannot be used any more so make sure to only do that right before you shut down the application.
μ’μ΅λλ€. μ°λ¦¬λ μ΄ λ¬Έμ λ₯Ό ν λ΄λΆμμ λ
Όμνμ΅λλ€.
μ¬λ¬λΆμ΄ μ³μκ³ μ§κΈ JavaScriptλ μ°λ¦¬κ° λ¬Έμνν λ°©μμΌλ‘ μλνμ§ μμ§λ§ π μ¬λ¬λΆμ΄ κΈ°λνλ κ²κ³Ό μ νν μΌμΉνλ flush
ν¨μλ₯Ό μκ°ν κ²μ
λλ€.
λ°λΌμ μ§κΈ λΉμ₯μ μ무 λ¬Έμ μμ΄ close
λ₯Ό μ¬μ©ν μ μμ΅λλ€(ν₯ν ν΄λΌμ΄μΈνΈλ₯Ό μμ /λΉνμ±ννκΈ° μν΄ λ³κ²½ν κ²μΈμ§ νμ€νμ§ μμ).
νμ§λ§ flush
ν¨μλ _just_ flush
λκΈ°μ΄μ μμ΅λλ€.
κΈ°λ₯μ΄ μΆμλλ©΄ μ΄ λ¬Έμ λ₯Ό μ λ°μ΄νΈνκ² μ΅λλ€.
μ΄ λͺ¨λ μ£Όμμμ μ½κ° μμ΄λ²λ ΈκΈ° λλ¬Έμ Express μ€λ₯ μ²λ¦¬κΈ°(μ΄ λ¦¬ν¬μ§ν 리μ μ€λ₯ μ²λ¦¬κΈ° λͺ¨λ°©)λ λ€μκ³Ό κ°μ΄ νμλμ΄μΌ ν©λκΉ?
function getStatusCodeFromResponse(error) {
const statusCode = error.status || error.statusCode || error.status_code || (error.output && error.output.statusCode);
return statusCode ? parseInt(statusCode, 10) : 500;
}
app.use(async (err, req, res, next) => {
const status = getStatusCodeFromResponse(err);
if (status >= 500) {
Sentry.captureException(err)
await Sentry.getCurrentHub().getClient().close(2000)
}
next(err)
})
κ·Έκ²μ μλνλ κ²μ²λΌ 보μ΄λ©° @rreynier μ μ½λμμμ κ°μ΄ μΆκ° λ°μ΄ν°λ₯Ό μμ§ μμ΅λλ€.
κ°μΈμ μΌλ‘ κ·Έλ κ² λλλ€.
await Sentry.getCurrentHub().getClient().captureException(err)
λ€μλ³΄λ€ κΉ¨λν©λλ€.
Sentry.captureException(err)
await Sentry.getCurrentHub().getClient().close(2000)
close
μ λ§ ν΄λΌμ΄μΈνΈλ₯Ό λ«μ κ²μ²λΌ μ½μ΅λλ€...
μ 체 μ:
import * as Sentry from '@sentry/node'
// ...
Sentry.init({ dsn: config.SENTRY_DSN })
// ...
app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
let status = (err.status || err.statusCode || 500) as number
if (process.env.NODE_ENV === 'test') {
return next(err)
}
if (status < 400 || status >= 500) {
Sentry.getCurrentHub().getClient().captureException(err).then(() => next(err))
} else {
next(err)
}
})
@LinusU μλνλλ° μ΄λ€ μ΄μ λ‘ μ€ν μΆμ κ³Ό ν¨κ» μΆκ° λ°μ΄ν°λ₯Ό 보λ΄μ§ μμ΅λλ€. κΈ°λ³Έμ μΌλ‘ μ€ν μΆμ λ§ λ³΄λ λλ€. μ¬μ©μ, OS λ±μ λν μ λ³΄κ° μμ΅λλ€.
μ, μ ν μ’μ§ μμ π
flush
λ₯Ό κΈ°λ€λ¦¬λ λμ μμ λ μ΅μ
λ³΄λ€ λ μμ μ μΈ ν΄κ²° λ°©λ²μΌλ‘ λ³΄κ³ νκ³ κ²°κ³Όλ₯Ό κΈ°λ€λ¦΄ μ μμ΅λλ€. μλ μ€λν«μ μ¬μ©νμ¬ λ²μλ₯Ό _λ°_ ν¬ν¨ν©λλ€.
const scope = Sentry.getCurrentHub().getScope();
await Sentry.getCurrentHub().getClient().captureException(error, scope);
λλ μ΄κ²μ μ¬μ©νκ³ μμΌλ©° λ΄κ° κΈ°λνλ λͺ¨λ κ²μ ν¬ν¨νμ¬ λ³΄κ³ λ μ€λ₯μ ν¨κ» μμ μ μΌλ‘ μλνλ κ² κ°μ΅λλ€.
μ λ μ€μ λ‘ μ΄ λͺ¨λ κ²μ Netlify Functionsμ ν¨κ» μ¬μ©νκ³ μμ§λ§ μ΄λ‘ μ Lambda λ±μμλ λμΌν©λλ€. κ΄μ¬ μλ μ¬λμ΄ μμΌλ©΄ https://httptoolkitμμ μ΄ μμ μ μννλ λ°©λ²μ λν μμΈν λ΄μ©μ΄ ν¬ν¨λ κ²μλ¬Όμ μμ±νμ΅λλ€. tech/blog/netlify-function-error-reporting-with-sentry/
νμ¬ λͺ¨λ λλ€μμ μ΄ λμ°λ―Έ λ₯Ό μ¬μ©ν©λλ€.
@pimterry μ΄κ²μ κΈ°λ³Έμ μΌλ‘ @LinusU κ° μ μν κ²κ³Ό λμΌν μ루μ μ΄ μλλκΉ? λλ κ·Έκ²μ μλνμ§λ§ μΆκ° λ°μ΄ν°λ 보λ΄μ§ μμ΅λλ€.
μ΄ μ κ·Ό λ°©μ μ μ§κΈκΉμ§ @ondrowanμ ν¨κ³Όκ° μμμ΅λλ€.
@ondrowan λμΌνμ§λ§ μλμΌλ‘ νμ¬ λ²μλ₯Ό μ‘κ³ ν¬ν¨ν©λλ€. μ μκ°μλ μμΈ μμ μ μννκΈ°μ μΆ©λΆν΄μΌν©λλ€. μ΄μ λ²μ μμλ λ μ΄λΈμ΄ μ§μ λμ§ μμ μ΄λ²€νΈκ° λ°μνμΌλ©° μ΄μ μ΄ λ³κ²½μΌλ‘ μΈν΄ μμΈκ° λͺ¨λ μΆκ° μΌλ° μΈλΆ μ 보μ ν¨κ» λ°μν©λλ€.
@vietbui @albinekb @Andriy-Kulak @LinusU @dwelch2344 @jviolas @rreynier @guillaumekh @rdsedmundo @ondrowan @pimterry @zeusdeux λκ° μ¬μ ν μ΄ μ¬μ© μ¬λ‘μ κ΄μ¬μ΄ μλμ§ μ λͺ¨λ₯΄κ² μΌλ―λ‘ μ ν νμ§ μμλ λλ μ μν΄ λΆνλ립λλ€.
4.6.0
μμνλ©΄ λ μ΄μ client/hub
λμ€κ° μμ΅λλ€. captureX
λ©μλλ₯Ό νΈμΆν λ€μ Sentry.flush()
λ₯Ό μ¬μ©νμ¬ λͺ¨λ κ²μ΄ μλ²λ‘ μ μ‘λλ©΄ μλ΅μ κΈ°λ€λ¦΄ μ μμ΅λλ€. λͺ¨λ λ²μ/μΆκ° λ°μ΄ν°λ κ°λ°μ μνΈ μμ© μμ΄ λ³΄μ‘΄λμ΄μΌ ν©λλ€.
λ€μμ μ±κ³΅/μκ° μ΄κ³Ό μμ²μ΄ μλ μμ λλ€.
λμμ΄ λκΈ°λ₯Ό λ°λλλ€! :)
λ©μ§!
Lambda λ° κΈ°ν μλ²λ¦¬μ€ μ루μ μμ μμΈλ₯Ό μΊ‘μ²νκΈ° μν μ΅μνμ ν¨ν€μ§λ₯Ό λ§λ€ κ³νμ΄ μμ΅λκΉ? λλ κ·Έκ²μ΄ μ¬μ ν μ λ§ μ’μ μΆκ°κ° λ κ²μ΄λΌκ³ μκ°ν©λλ€ β€οΈ
@LinusU ν¬λ§μ μΌλ‘ μ, νμ§λ§ μ°λ¦¬λ μ§κΈ λ€λ₯Έ μΈμ΄ SDKλ‘ κ°λ μ°¨ μμ΅λλ€ π
κ°λ₯ν λͺ¨λ μ루μ μ κ°μ¬λ립λλ€. μ¬κΈ° μμ£Όμ λͺ¨λ λΆλ€κ» κ°μ¬λ립λλ€.
await Sentry.flush()
λ₯Ό μ¬μ©νμ¬ λ³΄λ₯ μ€μΈ λͺ¨λ μμ²μ 보λ
λλ€. μ΄κ²μ 4.6.x
μ λμ
λμμ΅λλ€.
μ΄ κΈμ λ«κ³ λλ½λ κ²μ΄ μλ κ²½μ°λ₯Ό λλΉνμ¬ μμ λ‘κ² μ νΈλ₯Ό μ¬μμμ€(κ·Έλ¬λ μ΄ μ€λ λλ μ΄λ―Έ λ§€μ° κΉλλ€).
건배 π π
@kamilogorek μλ
νμΈμ! μ°Έκ³ λ‘ μ λ μ΄μ ν΄κ²° λ°©λ² λμ λ΄ μ±μμ Sentry.flush
λ₯Ό μ¬μ©νκ³ μμΌλ©° μ€λ₯κ° λ³΄κ³ λμ§ μμ΅λλ€. νμ¬ μ
λ°μ΄νΈλ flush
λ©μλ μμ μ΄μ ν΄κ²° λ°©λ²μΌλ‘ λλλ¦¬κ³ μμ΅λλ€.
@zeusdeux μ΄μ λν λλ²κ·Έ μ 보/μ¬ν μ¬λ‘λ₯Ό μ 곡ν μ μλ λ°©λ²μ΄ μμ΅λκΉ?
λ²νΌμ μ΄λ²€νΈλ₯Ό μΆκ°νλ captureException
λ©μλλ₯Ό μ¬μ μνκ³ flush
λ°ν κ°μ await
λ₯Ό μΆκ°ν΄μΌ ν©λλ€. "μΌλ°μ μΈ λ°©λ²"μΌλ‘ μ¬μ©ν΄ 보μ
¨μ΅λκΉ?
@kamilogorek λλ²κ·Έ μ λ³΄κ° μμΌλ©΄ μ’κ² μ§λ§ λ‘κ·Έμ μ무κ²λ μμ΅λλ€. λλ νμ μ¬μ μλ captureException
μμ await
μ νμ΅λλ€ . μΌλ°μ μΈ λ°©λ²μΌλ‘ captureException
λ₯Ό μ¬μ μνμ§ μκ³ μλ―Έν©λκΉ?
@zeusdeux μ νν, μ¬μ μ μμ΄ κΈ°λ³Έ Sentry.captureException(error)
λ₯Ό νΈμΆνλ©΄ λ©λλ€.
λ°λΌμ λμ°λ―Έλ λ€μκ³Ό κ°μ΅λλ€.
import * as Sentry from '@sentry/node'
export function init({ host, method, lambda, deployment }) {
const environment = host === process.env.PRODUCTION_URL ? 'production' : host
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment,
beforeSend(event, hint) {
if (hint && hint.originalException) {
// eslint-disable-next-line
console.log('Error:', hint.originalException);
}
return event;
}
})
Sentry.configureScope(scope => {
scope.setTag('deployment', deployment)
scope.setTag('lambda', lambda)
scope.setTag('method', method)
})
}
μ½λμμ λ€μκ³Ό κ°μ΄ νΈμΆν©λλ€.
import * as Sentry from '@sentry/node'
try {
// ...
} catch (err) {
Sentry.captureException(err);
await Sentry.flush(2000);
return respondWithError('Something went wrong', 500);
}
@kamilogorek ν΄λ³΄κ³ λ€μ λ³΄κ³ νκ² μ΅λλ€. λν beforeSend
μ λν νμ μ£Όμ
μ κ°μ¬ν©λλ€ ^_^
await Sentry.flush(2000);
λ ~not~ λλ₯Ό μν΄ μΌνκ³ μμ΅λλ€.
@tanduong μ¬ν μΌμ΄μ€λ₯Ό μ 곡ν μ μμ΅λκΉ? ν¨κ³Όκ° μλ€κ³ λ§νλ κ²λ§μΌλ‘λ λμμ΄ λμ§ μμ΅λλ€ π
@kamilogorek μ¬μ€, λλ κ·Έκ²μ λ°©κΈ μμλ€.
await Sentry.getCurrentHub().getClient().close(2000)
λ΄ λλ€ ν¨μκ° VPCμ μ°κ²°λμ΄ μκΈ° λλ¬Έμ μλνμ§ μμ΅λλ€.
λλ κ·Έκ²μ νμΈνλ€
await Sentry.flush(2000);
μ€μ λ‘ μλνκ³ μμ΅λλ€.
BTW, κ·Έλ¬λ©΄ VPCμμ λλ€λ₯Ό μ΄λ»κ² μ²λ¦¬ν κΉμ? NAT κ²μ΄νΈμ¨μ΄μ μ°κ²°νμκ² μ΅λκΉ? λλ λ¨μ§ Sentryλ₯Ό μνμ§λ§ κ³΅μ© μΈν°λ·μ μνμ§ μμ΅λλ€.
@tanduong Sentryλ κ³΅μ© μΈν°λ·μ μμΌλ―λ‘ λλ€κ° VPC λ΄μμ μ€νλλ κ²½μ° NAT κ²μ΄νΈμ¨μ΄κ° μμ΄μΌ ν©λλ€. κ·Έλ μ§ μμΌλ©΄ νΈμ€ν λ Sentry μ΅μ μ νμν΄μΌ ν©λλ€.
flush(2000)
μ μ€μ λ‘ λ¬΄μμ νκ³ μμ΅λκΉ? μ΄ μ½λλ λλΆλΆ μ μλνμ§λ§ μ§κΈμ λͺ captureMessage
νΈμΆμ΄ λμμ λ°μνκ³ μμ΅λλ€. λ§€λ² μκ°μ΄ μ΄κ³Όλ©λλ€!
μ μ μ ν΅ν΄ λ΄λΆ λ©μμ§ λκΈ°μ΄ νλ¬μ
μκ² μ΅λλ€. λ΄ λ¬Έμ λ νλ¬μ ν λ€λ₯Έ κ²μ΄ μμ λμ΄ μ½μμ΄ λ°νλμ§ μλλ€λ κ²μ
λλ€. λνλ captureException
fnμ λμμ μ€νν λλ§λ€ νΈλ€λ¬κ° μκ° μ΄κ³Όλ©λλ€.
export const captureMessage = async (
message: string,
extras?: any,
): Promise<boolean> =>
new Promise((resolve) => {
Sentry.withScope(async (scope) => {
if (typeof extras !== 'undefined') {
scope.setExtras(extras)
}
Sentry.captureMessage(message)
await Sentry.flush(2000)
resolve(true)
})
})
await Sentry.flush()
λ 첫 λ²μ§Έ captureMessage νΈμΆ νμ μ€μ λ‘ μλ£λμ§ μμ΅λλ€.
@enapupeμ λΉμ·ν λ¬Έμ κ° μλ€κ³ μκ°ν©λλ€. await client.flush(2000);
λ₯Ό λ³λ ¬λ‘ νΈμΆνλ©΄ 첫 λ²μ§Έ μ½μλ§ ν΄κ²°λ©λλ€. μ΄λ νΈλ€λ¬μ λν μ¬λ¬ λμ νΈμΆ μ¬μ΄μμ ν΄λΌμ΄μΈνΈκ° μ¬μ¬μ©λλ AWS λλ€ μ»¨ν
μ€νΈμμ λ°μν μ μμ΅λλ€.
λ€μκ³Ό κ°μ μ½λλ₯Ό μ¬μ©νκ³ μμ΅λλ€.
let client = Sentry.getCurrentHub().getClient();
if (client) {
// flush the sentry client if it has any events to send
log('begin flushing sentry client');
try {
await client.flush(2000);
} catch (err) {
console.error('sentry client flush error:', err);
}
log('end flushing sentry client');
}
κ·Έλ¬λ λΉ λ₯΄κ² λλ€ ν¨μλ₯Ό λ λ² νΈμΆνλ©΄ λ€μκ³Ό κ°μ κ²°κ³Όκ° λνλ©λλ€.
app begin flushing sentry client +2ms
app begin flushing sentry client +0ms
app end flushing sentry client +2ms
λ λ²μ§Έ μ½μμ μ λ ν΄κ²°λμ§ μλ κ²μ λ³Ό μ μμ΅λλ€.
@esetnik μ΄μ λν λ¬Έμ λ₯Ό μ μΆνμ΅λλ€: https://github.com/getsentry/sentry-javascript/issues/2131
νμ¬ ν΄κ²° λ°©λ²μ νμ ν΄κ²°λλ λνΌ νλ¬μ fnμ
λλ€(μκ° μ΄κ³Ό κΈ°μ€).
const resolveAfter = (ms: number) =>
new Promise((resolve) => setTimeout(resolve, ms))
const flush = (timeout: number) =>
Promise.race([resolveAfter(timeout), Sentry.flush(timeout)])
@enapupe #2131μμ ν΄κ²° λ°©λ²μ λν λ©λͺ¨λ₯Ό μΆκ°νμ΅λλ€. λλ κ·Έκ²μ΄ λμ νλ¬μμμ μ±λ₯ μ νλ₯Ό μΌμΌν¬ κ²μ΄λΌκ³ λ―Ώμ΅λλ€.
λκ΅°κ° λ¬Έμ κ° μλ κ²½μ°.
μ΄κ²μ μλ¦λ΅κ² μλν©λλ€.
@SarasArya @HazAT
μ°μ ... μ루μ
μ 곡μ ν΄ μ£Όμ
μ κ°μ¬ν©λλ€! :)
configureScope λ©μλμ μ½λ°±μ΄ νλ μλλ° captureException μ μ νΈμΆλμ΄μΌ νμ§λ§ λμΌν "μ€λ λ"μμ μνλμ§ μμ΅λλ€.
μ΄κ²μ κ²½μ 쑰건μ μΆνμΌλ‘ μ΄μ΄μ§ μ μμμ΅λκΉ?
@cibergarri κ·Έλ κ² μκ°νμ§ μμ΅λλ€. μ μκ² λκΈ°μ μΌλ‘ 보μ
λλ€. κ±°κΈ°μ λΉλκΈ° λ©μλκ° μλ κ²½μ° κ²½μ μ‘°κ±΄μ΄ μμ μ μμ΅λλ€.
μ¬κΈ°μμ λμΌν μΌμ΄ λ°μνλ λ°°μ΄μ .mapκ³Ό κ°λ€κ³ μκ°νμμμ€. μ£Όμμ 머리λ₯Ό κ°μΈλ λ¬Έμ κ° μλ κ²½μ°. λμμ΄ λκΈ°λ₯Ό λ°λλλ€.
λ€, κ·Έλ κ² νλ κ²μ΄ μ’μ΅λλ€.
μ λ°μ΄νΈ: Sentryλ μ΄μ Node/Lambda νκ²½μ λν μλνλ μ€λ₯ μΊ‘μ²λ₯Ό μ§μν©λλ€. https://docs.sentry.io/platforms/node/guides/aws-lambda/
λ€μκ³Ό κ°μ΄ @sentry/serverlessλ₯Ό μ¬μ©νκ³ μμ΅λλ€.
const Sentry = require("@sentry/serverless");
Sentry.AWSLambda.init({
dsn: process.env.SENTRY_DSN,
tracesSampleRate: 1.0,
environment: appEnv
});
exports.main = Sentry.AWSLambda.wrapHandler(async (event, context) => {
try{
//my code
}catch(error){
Sentry.captureException(error);
await Sentry.flush(3000);
}
});
λλ€μμλ μλνμ§ μμ΅λλ€.
λ΄ ν
μ€νΈ νκ²½μμλ μλνμ§λ§ λμ μ€νμ΄ λ§κ³ 컨ν
μ΄λκ° μ¬μ¬μ©λλ μ νμμλ μ΄ μμ μ½ 10%λ§ λ‘κΉ
ν©λλ€.
μ΄λ€ μΆ©κ³ ?
@armando25723
μμΈ μ΄λ²€νΈλ₯Ό μλ κ²μ μ΄λ»κ² μΈ‘μ νλμ§ μλ €μ£Όμμμ€. κ·Έλ¬ν μμ€λ μμΈκ° μ΄λ»κ² λ°μνλμ§μ λν μ½λ μνμ΄ μμ΅λκΉ? λ λ§μ 컨ν μ€νΈκ° νμν©λλ€.
const Sentry = require("@sentry/serverless"); // "version": "5.27.3"
Sentry.AWSLambda.init({
dsn: process.env.SENTRY_DSN,
tracesSampleRate: 1.0,
environment: appEnv
});
exports.main = Sentry.AWSLambda.wrapHandler(async (event, context) => {
try{
throw new Error('Test Error');
}catch(error){
Sentry.captureException(error);
await Sentry.flush(3000);
}
});
λ¬΄μ¨ μΌμ΄μΌ?
νΈμΆ μ¬μ΄μ 짧μ κ°κ²©μΌλ‘ ν¨μκ° μ¬λ¬ λ² νΈμΆλλ©΄ μ΄λ²€νΈλ ν λ²λ§ κΈ°λ‘λ©λλ€.
νΈμΆ μ¬μ΄μ μκ° κ°κ²©μ΄ λ ν¬λ©΄ λͺ¨λ μ΄λ²€νΈκ° κΈ°λ‘λ©λλ€.
νΈμΆμ΄ μ¬μ¬μ©λ 컨ν μ΄λμ λν΄ λ¬Έμ κ° μλ€κ³ κ°μ ν©λλ€.
λλ λν μλνλ€
await Sentry.captureException(error);
κ·Έλ¦¬κ³ :
await Sentry.flush();
κ·Έλ¦¬κ³ νλ¬μ± μμ΄
κ°μ κ²°κ³Ό
@marshall-lee 무μμ μΆμ²νμλμ? λ¬Έμ λ₯Ό λ§λ€λ©΄ μ¬κΈ°μμ λ©μΆ₯λλ€.
@armando25723 μ΄ μ΄λ²€νΈλ₯Ό 보λ΄λ λμ μλ²κ° 429(μμΈκ° λ무 λ§μ)λ‘ μλ΅νλ κ² κ°μ΅λλ€. ν λΉλ/μλ μ ν μλ리μ€λ₯Ό μ΄κ³Όνλ κ²½μ° μ΄λ₯Ό λμ§λλ€. μμ°¨μ μΌλ‘ μ€λ₯λ₯Ό 보λ΄λμ§ μλλ©΄ ν λΉλμ μ΄κ³Όνλμ§ μκ³ μμ΅λκΉ? μ΄κ²μ΄ μ€μ μ€λ₯ μ΄λ²€νΈκ° μμ λκ³ ν리 ν°μ΄μ λν 5k μ ν λ―Έλ§μ΄λΌκ³ μκ°νλ κ²½μ° μΆκ°λ‘ λλ²κ·Έν μ μμ΅λλ€.
@ajjindal λ€λ₯Έ λͺ¨λ νλ‘μ νΈλ sentryμ μ μλν©λλ€. μ‘°μ§ μ¬λ¬κ·Έλ "alegra"μ΄κ³ νλ‘μ νΈ μ΄λ¦μ #mail-micros μλμ mail-dispatch-serverlessμ
λλ€. μ°λ¦¬λ μ€λ«λμ μΌνΈλ¦¬λ₯Ό μ¬μ©ν΄ μμ§λ§ μλ²λ¦¬μ€λ μ²μμ
λλ€. μ΄κ²μ ν리 ν°μ΄κ° μλλ―λ‘ μ νν μ΄λ€ νλμ μ¬μ©νκ³ μλμ§ λ§μλ릴 μλ μμ§λ§ μ λ£μ
λλ€.
λ λλ²κΉ
νλ λ° λμμ΄ λλ€λ©΄ μ’μ κ²μ
λλ€.
λ΅λ³ κ°μ¬ν©λλ€ : )
PD: ννλ
κ°μ₯ μ μ©ν λκΈ
@LinusU μ°λ¦¬λ μ΄ μλ리μ€λ₯Ό μν νΉμ μλ²λ¦¬μ€ ν¨ν€μ§λ₯Ό μμ±ν κ°λ₯μ±μ΄ λμ΅λλ€. μ°λ§μ΄κ³ μ§κΈ μ¬λλ€μ΄ λ§μ΄ λͺ°λ¦¬κΈ° λλ¬Έμ μκ°μ μ°ΎμμΌ ν©λλ€. κ³μ μλ €λ립λλ€!