рд╡рд░реНрддрдорд╛рди рд╡реНрдпрд╡рд╣рд╛рд░ рдХреНрдпрд╛ рд╣реИ?
рдореИрдВ рдПрдбрдмреНрд▓реНрдпреВрдПрд╕ рд▓реИрдореНрдмреНрдбрд╛ рд╕рдорд╛рд░реЛрд╣ рдкрд░ рдЕрдкрд╡рд╛рдж рдХреЛ рдкрдХрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП @ рд╕рдВрддрд░реА/рдиреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдБред
.catch(err => {
Sentry.captureException(err)
context.fail()
})
рд╣рд╛рд▓рд╛рдВрдХрд┐, рдпрд╣ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдорд╛рд░ рджреЗрддрд╛ рд╣реИ рдЬрдм context.fail()
рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЕрдкрд╡рд╛рдж рд╕рдВрддрд░реА рдореЗрдВ рд╕рдорд╛рдкреНрдд рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред
рдореИрдВ рдПрдХ рдХрд╛рдордХрд╛рдЬ рдХрд░ рд╕рдХрддрд╛ рдерд╛ рдЬреИрд╕реЗ:
.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)ред
рдпрд╣ рд╣рдорд╛рд░рд╛ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рдПрдкреАрдЖрдИ рд╣реИред
рдЬрдмрдХрд┐ рдкрд┐рдЫрд▓рд╛ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдЕрднреА рднреА рдХрд╛рдо рдХрд░реЗрдЧрд╛, close
рд╡рд┐рдзрд┐ рд╕рднреА рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддреА рд╣реИред
@HazAT рдЕрдЪреНрдЫрд╛ рд▓рдЧрд╛ред рд╕рд╛рд░реА рдХрдбрд╝реА рдореЗрд╣рдирдд рдХреЗ рд▓рд┐рдП рд╢реБрдХреНрд░рд┐рдпрд╛ред
4.0.3 рдореЗрдВ рдореИрдВ рдЗрд╕реЗ рдЕрдкрдиреЗ рд▓реИрдореНрдмреНрдбрд╛ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдЗрд╕ рддрд░рд╣ рдХрд╣рддрд╛ рд╣реВрдВ:
try {
...
} catch (err) {
await getCurrentHub().getClient().captureException(err, getCurrentHub().getScope())
throw err
}
getDefaultHub() рдЕрдм рдЙрдкрд▓рдмреНрдз рдирд╣реАрдВ рд╣реИред
@vietbui рдЗрд╕реЗ рдЕрдм getCurrentHub
рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдореЗрдВ рдЕрдкрдиреЗ рдПрдкреАрдЖрдИ рдХреЛ рдЕрдиреНрдп рднрд╛рд╖рд╛рдУрдВ рдХреЗ рдПрд╕рдбреАрдХреЗ рдХреЗ рд╕рд╛рде рдПрдХреАрдХреГрдд рдХрд░рдирд╛ рдерд╛ред
@kamilogorek рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред getCurrentHub
рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рд╕рд╛рде рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдХрд┐рд╕реА рддрд░рд╣ рдореИрдВрдиреЗ рдЬреЛ рджрд╛рдпрд░рд╛ рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рд╣реИ рд╡рд╣ рд╕рдВрддрд░реА рдореЗрдВ рд╕рдорд╛рдкреНрдд рдирд╣реАрдВ рд╣реБрдЖред
рдЕрдВрдд рдореЗрдВ рдореИрдВрдиреЗ рдЕрдкрдиреЗ рд▓реИрдореНрдмреНрдбрд╛ рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рдЕрдкрд╡рд╛рдж рдХреЛ рдкрдХрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП @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,
}
};
@ рдПрдВрдбреНрд░реА-рдХреБрд▓рдХ рдиреЗ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реЛрдВ рдореЗрдВ рднреА рдХрд╣рд╛ рд╣реИ:
After shutdown the client cannot be used any more so make sure to only do that right before you shut down the application.
рддреЛ рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рдХрд┐ рд╣рдо рдЗрд╕реЗ рд▓реИрдореНрдмреНрдбрд╛ рдореЗрдВ рдХреИрд╕реЗ рд╕рдВрднрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд╣рд╛рдВ рд╣рдо рдирд╣реАрдВ рдЬрд╛рдирддреЗ рдХрд┐ рдЖрд╡реЗрджрди рдХрдм рдорд╛рд░рд╛ рдЬрд╛рдПрдЧрд╛ред рдкреНрд░рддрд┐ рдЕрдиреБрд░реЛрдз рд╕рдВрддрд░реА рдХреЛ рдирд┐рдХрд╛рд▓рдирд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ рдЬреИрд╕реЗ рд╣рдо рдкреБрд░рд╛рдиреЗ рдПрдкреАрдЖрдИ рдХреЗ рд╕рд╛рде рдХрд░ рд╕рдХрддреЗ рдереЗ?
@HazAT рдХреНрдпрд╛ рд╣рдо рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рдЦреЛрд▓ рд╕рдХрддреЗ рд╣реИрдВ? рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд▓реИрдореНрдмреНрдбрд╛ рдкрд░ рдЗрд╕рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рд╣реЛрдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ, рдЬреЛ рдХрд┐ рддреИрдирд╛рддреА рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрдо рд▓рдХреНрд╖реНрдп рдмрдирддрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИред
рдпрд╣ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдореБрдЭреЗ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдЕрдкрдЧреНрд░реЗрдб рдХрд░рдиреЗ рд╕реЗ рд░реЛрдХ рд░рд╣рд╛ рд╣реИ...
рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ, рдореИрдВ рдХрд┐рд╕реА рддреНрд░реБрдЯрд┐ рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХрд░рддреЗ рд╕рдордп рдПрдХ рд╡рд╛рджрд╛/рдХреЙрд▓рдмреИрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдкрд╕рдВрдж рдХрд░реВрдВрдЧрд╛ред рдХрддрд╛рд░ рдХреЛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдмрд╛рдж рдореЗрдВ рдмрдВрдж рдХрд┐рдП рдмрд┐рдирд╛ рдирд┐рдХрд╛рд▓рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рд╣реЛрдирд╛ рдЕрдЧрд▓реА рд╕рдмрд╕реЗ рдЕрдЪреНрдЫреА рдмрд╛рдд рд╣реЛрдЧреА ...
рдХреЙрд▓рдмреИрдХ рдХреЛ captureException
рд╕реЗ рд╣рдЯрд╛рдиреЗ рдХрд╛ рдФрдЪрд┐рддреНрдп рдХреНрдпрд╛ рдерд╛?
@albinekb рдЕрдЧрд░ рдореИрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкрдВрдХреНрддрд┐ рдХреЛ рд╣рдЯрд╛рддрд╛ рд╣реВрдВ рддреЛ рдпрд╣ рдмрд┐рд▓реНрдХреБрд▓ рднреА рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ
await new Promise(resolve => Sentry.getCurrentHub().getClient().close(2000).then(resolve))
@LinusU рдХреНрдпрд╛ рд╕рдорд╛рдзрд╛рди рд╣реИ рдФрд░ рд╕рдВрддрд░реА рдпрд╛ рд░реЗрд╡реЗрди рд╕рдорд╛рдзрд╛рди рдХреНрдпрд╛ рдЖрдк рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ?
рдореЗрд░реЗ рд▓рд┐рдП рдореВрд▓ рд░реВрдк рд╕реЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ sentry/node @4.3.0
, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓реИрдореНрдмреНрдбрд╛ рдХреЛ рдХреБрдЫ рд╕рдордп рдХреЗ рд▓рд┐рдП рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдиреА рд╣реЛрдЧреА (рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдореИрдВ 2 рд╕реЗрдХрдВрдб рд▓рдЧрд╛рддрд╛ рд╣реВрдВ) рд╕рдВрддрд░реА рдХреЛ рд╡рд╣ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬреЛ рдЙрд╕реЗ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЬреЛ рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЗрд╕реЗ рд╡рд╣рд╛рдВ рдХреНрдпреЛрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдХреНрдпреЛрдВрдХрд┐ рд╣рдо 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,
}
};
рд╣рдо рд▓реИрдореНрдмреНрдбрд╛ рдкрд░ рднреА рдЗрд╕ рдкрд░ рдЬрд▓ рд░рд╣реЗ рд╣реИрдВред рд╣рдордиреЗ рдирдП рдХрд╛рдореЛрдВ рдХреЗ рд╕рд╛рде рд╢реБрд░реБрдЖрдд рдХреА рдФрд░ рд░реЗрд╡реЗрди рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рдиреЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рддреЗ рд╣реБрдП рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдмреЙрдХреНрд╕рд┐рдВрдЧ рдЖрдЙрдЯ рд╣реЛ рдЧрдПред рд╣рдм рдХреЛ рдмрдВрдж рдХрд░рдиреЗ рдФрд░ рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рдкреНрд░рдпрд╛рд╕ рдХреЗ рд▓рд┐рдП рд╣рдо рдЕрднреА рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦ рд░рд╣реЗ рд╣реИрдВ, рдЬреЛ рдкрд╛рдиреА рд░рдЦрдиреЗ рдкрд░ рдПрдХ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рд╕рдорд╛рдзрд╛рди рд╣реЛрдЧрд╛ред рд▓реЗрдХрд┐рди рдЕрднреА рднреА рд╣реИрдХреА/рд▓реЛрдб рдХреЗ рддрд╣рдд рд╕рдорд╕реНрдпрд╛рдПрдВ рдкреИрджрд╛ рдХрд░рдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИред
рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ рдореИрдВ рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХрд╛ 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)
}
})
рдореИрдВ рддрдм рд▓реИрдореНрдмреНрдбрд╛ рдореЗрдВ рдПрдХреНрд╕рдкреНрд░реЗрд╕ рдРрдк рдХреЛ рддреИрдирд╛рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрдХреИрдВрдбрд┐рдпрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ
рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: рдпрд╣ рд░реЗрд╡реЗрди рдХреЗ рд╕рд╛рде рд╣реИ "raven": "^2.6.3",
рдбреНрд░реАрдо рдПрдкреАрдЖрдИ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд╣реЛрдЧрд╛
Sentry.captureException(err: Error): Promise<void>
@LinusU https://github.com/getsentry/sentry-javascript/blob/master/packages/core/src/baseclient.ts#L145 -L152
рд╣рд╛рд▓рд╛рдВрдХрд┐ рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рд╕реАрдзреЗ рдХреНрд▓рд╛рдЗрдВрдЯ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЗрд╕рдХрд╛ рдХрд╛рд░рдг рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рддрдп рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдореБрдЦреНрдп рдкрд░рд┐рджреГрд╢реНрдп "рдЖрдЧ рдФрд░ рднреВрд▓" рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╡реНрдпрд╡рд╣рд╛рд░ рд╣реИ, рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдпрд╣ рдПрдХ рдПрд╕рд┐рдВрдХ рд╡рд┐рдзрд┐ рдирд╣реАрдВ рд╣реИред рдЖрдВрддрд░рд┐рдХ рд░реВрдк рд╕реЗ рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрд╕рд┐рдВрдХ рдПрдкреАрдЖрдИ рд╣реИ рдЬрд┐рд╕рдХрд╛ рд╣рдо рд╕реНрд╡рдпрдВ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред
рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЬреЛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рд╡рд╣ рдХреБрдЫ рдФрд░ рд╣реИ:
const backend = client.getBackend()
const event = await backend.eventFromException(error)
await client.processEvent(event, finalEvent => backend.sendEvent(finalEvent))
рд╕рднреА рдХрддрд╛рд░рдмрджреНрдз рдФрд░ рдмрдлрд╝рд░рд┐рдВрдЧ рдХреЛ рдЫреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП...
рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдбрд┐рдЬрд╛рдЗрди "рдЖрдЧ рдФрд░ рднреВрд▓" рдХреЗ рдЕрдиреБрд░реВрдк рд╣реИ, рдФрд░ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдЪрд▓рдиреЗ рд╡рд╛рд▓реЗ рд╕рд░реНрд╡рд░ рдореЗрдВ рдЪрд▓рдиреЗ рдХреЗ рд▓рд┐рдП, рдФрд░ рдпрд╣ рд╢рд╛рдпрдж рдЙрд╕ рдкрд░ рдХрд╛рдлреА рдЕрдЪреНрдЫрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдмрдлрд░рд┐рдВрдЧ рдХрд░рддрд╛ рд╣реИред рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рдмрд┐рд▓реНрдХреБрд▓ рд╡рд┐рдкрд░реАрдд рд╣реИ рдХрд┐ рдЖрдк рд▓реИрдореНрдмреНрдбрд╛, рдРрдк рдЗрдВрдЬрди рдФрд░ рдЕрдиреНрдп "рд╕рд░реНрд╡рд░ рд░рд╣рд┐рдд" рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХреЗ рд▓рд┐рдП рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдЬреЛ рдЕрдзрд┐рдХ рд╕реЗ рдЕрдзрд┐рдХ рд╕рд╛рдорд╛рдиреНрдп рд╣реЛрддреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВред
рдХреНрдпрд╛ рдпрд╣ рд╕рдВрднрд╡ рд╣реЛрдЧрд╛ рдХрд┐ рдПрдХ рд╡рд┐рд╢реЗрд╖ рд╡рд┐рдзрд┐ рд╣реЛ рдЬреЛ рдШрдЯрдирд╛ рдХреЛ рдЬрд┐рддрдиреА рдЬрд▓реНрджреА рд╣реЛ рд╕рдХреЗ рднреЗрдЬ рджреЗ, рдФрд░ рдПрдХ Promise
рд▓реМрдЯрд╛рдП рдЬрд┐рд╕реЗ рд╣рдо await
рдХрд░ рд╕рдХреЗрдВ? рдпрд╣ рд╕рд░реНрд╡рд░ рд░рд╣рд┐рдд рдкрд░рд┐рджреГрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХрджрдо рд╕рд╣реА рд╣реЛрдЧрд╛!
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
рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрд╕ рдмреЗрд╣рддрд░ рд╕рдорд╛рдзрд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрдм рдХрд░реВрдВрдЧрд╛? рдЬрд╣рд╛рдВ рддрдХ тАЛтАЛтАЛтАЛрдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЬрд╛рдирдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИ рдХрд┐ рд▓реИрдореНрдмреНрдбрд╛ рдХрдм рдмрдВрдж рд╣реЛ рдЬрд╛рдПрдЧрд╛ - рд╕рд╛рде рд╣реА рд╕рдВрддрд░реА рдХреЛ рдЕрдкрдиреА рдмрд╛рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рд╢рдЯрдбрд╛рдЙрди рдХреЗ рд▓рд┐рдП рдордирдорд╛рдиреЗ рдврдВрдЧ рд╕реЗ рд╕рдордп рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдирд╛ рдореВрд░реНрдЦрддрд╛рдкреВрд░реНрдг рд▓рдЧрддрд╛ рд╣реИ - рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдорд╣рдВрдЧреА рдЙрдЪреНрдЪ рдореЗрдореЛрд░реА/рд╕реАрдкреАрдпреВ рд▓реИрдореНрдмреНрдбрд╛ рдлрд╝рдВрдХреНрд╢рдВрд╕ рдкрд░ред
(рдЬрд▓ рдирд┐рдХрд╛рд╕реА рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ)
рдпрд╣ рд╕рд░реНрд╡рд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдмрдВрдж рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЖрдЦрд┐рд░реА рдЪреАрдЬ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИред drain
рдкрджреНрдзрддрд┐ рдореЗрдВ рд╕рдордпрдмрд╛рд╣реНрдп рд╡рд╣ рдЕрдзрд┐рдХрддрдо рд╕рдордп рд╣реИ рдЬрд┐рд╕рдХрд╛ рд╣рдо рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдмрдВрдж рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░реЗрдВрдЧреЗ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рдпрд╣ рдирд╣реАрдВ рд╣реИ рдХрд┐ рд╣рдо рд╣рдореЗрд╢рд╛ рдЙрд╕ рд╕рдордп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рдпрджрд┐ рд╕рд░реНрд╡рд░ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ рд╣реИ, рддреЛ рдпрд╣ рд╢реЗрд╖ рд╕рднреА рдИрд╡реЗрдВрдЯ рдХреЛ рддреБрд░рдВрдд рднреЗрдЬ рджреЗрдЧрд╛ред
рдЗрд╕реЗ рдкреНрд░рддрд┐ рд╕реЗ рдЬрд╛рдирдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рд▓реИрдореНрдмреНрдбрд╛ рдХреЛ рдпрд╣ рдмрддрд╛рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ рд╣реИрдВрдбрд▓рд░ рдХреЗ рдХреЙрд▓рдмреИрдХ рддрд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрдм рдмрдВрдж рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ @LinusU , рдореИрдВрдиреЗ рдЖрдкрдХреА рдкрд┐рдЫрд▓реА рдЯрд┐рдкреНрдкрдгреА, рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдЗрд╕ рднрд╛рдЧ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрдврд╝рд╛:
рдХреНрдпрд╛ рдпрд╣ рд╕рдВрднрд╡ рд╣реЛрдЧрд╛ рдХрд┐ рдПрдХ рд╡рд┐рд╢реЗрд╖ рд╡рд┐рдзрд┐ рд╣реЛ рдЬреЛ рдШрдЯрдирд╛ рдХреЛ рдЬрд┐рддрдиреА рдЬрд▓реНрджреА рд╣реЛ рд╕рдХреЗ рднреЗрдЬ рджреЗ, рдФрд░ рдПрдХ рд╡рд╛рджрд╛ рд▓реМрдЯрд╛рдП рдЬрд┐рд╕рдХрд╛ рд╣рдо рдЗрдВрддрдЬрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ? рдпрд╣ рд╕рд░реНрд╡рд░ рд░рд╣рд┐рдд рдкрд░рд┐рджреГрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХрджрдо рд╕рд╣реА рд╣реЛрдЧрд╛!
рдЗрд╕ рддрд░рд╣ рд╣рдордиреЗ рдЕрдкрдиреЗ рдмрдлрд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ред рдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░ рдкреНрд░рддреНрдпреЗрдХ captureX
рдХреЙрд▓, рдЗрд╕реЗ рдмрдлрд░ рдореЗрдВ рдЬреЛрдбрд╝ рджреЗрдЧрд╛, рдпрд╣ рд╕рд╣реА рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдХрд┐рд╕реА рднреА рддрд░рд╣ рд╕реЗ рдХрддрд╛рд░рдмрджреНрдз рдирд╣реАрдВ рд╣реИ, рдЗрд╕реЗ рддреБрд░рдВрдд рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЗрд╕ рдкреИрдЯрд░реНрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреЗрд╡рд▓ рдЗрд╕рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рддрд╛рдХрд┐ рд╣рдо рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХреЗрдВ рдпрджрд┐ рд╕рдм рдХреБрдЫ рдерд╛ рд╕рдВрддрд░реА рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рднреЗрдЬрд╛ рдЧрдпрд╛ред
рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рдпрджрд┐ рдЖрдк AWS рд▓реИрдореНрдмреНрдбрд╛ рдореЗрдВ рдРрд╕рд╛ рдХреБрдЫ рдХрд░рддреЗ рд╣реИрдВ (рдпрд╣ рдорд╛рдирддреЗ рд╣реБрдП рдХрд┐ рдЖрдк рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдХреНрд▓рд╛рдЗрдВрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдЬреЛ рдХрд┐ рд╕рдмрд╕реЗ рд╕рд░рд▓ рдорд╛рдорд▓рд╛ рд╣реИ):
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');
})
}
};
рдЖрдк рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЗрд╕реЗ рддреБрд░рдВрдд рднреЗрдЬ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рдХреЛрдИ рд╕рдордп/рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдУрд╡рд░рд╣реЗрдб рдирд╣реАрдВ рдерд╛ред
@ рдХрд╛рдорд┐рд▓реЛрдЧреЛрд░реЗрдХ
рдХреНрдпрд╛ рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рдРрд╕рд╛ рдХреБрдЫ рдПрд╕рд┐рдВрдХ/рдкреНрд░рддреАрдХреНрд╖рд╛ рд╣реИрдВрдбрд▓рд░ рдореЗрдВ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП (рдЬрд╣рд╛рдВ рдЖрдк рдХреЙрд▓рдмреИрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ)?
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()
рдирд╣реАрдВ рдорд┐рд▓рд╛, рдХреНрдпрд╛ рдпрд╣ рдПрдкреАрдЖрдИ рдЧрд╛рд░рдВрдЯреА рд╣реИ рдХрд┐ рдмрд┐рдирд╛ рдХрд┐рд╕реА рдмрдбрд╝реЗ рд╕реЗрдорд░ рдЯрдХреНрдХрд░ рдХреЗ рдЯреВрдЯрдиреЗ рдХреА рдЧрд╛рд░рдВрдЯреА рд╣реИ? тЭдя╕П
@kamilogorek рдореБрдЭреЗ рдЖрдкрдХреА рд╡реЗрдмрд╕рд╛рдЗрдЯ рдкрд░ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реЛрдВ рдореЗрдВ getCurrentHub() рдирд╣реАрдВ рдорд┐рд▓рд╛, рдХреНрдпрд╛ рдпрд╣ рдПрдкреАрдЖрдИ рдЧрд╛рд░рдВрдЯреА рд╣реИ рдХрд┐ рдмрд┐рдирд╛ рдХрд┐рд╕реА рдмрдбрд╝реЗ рд╕реЗрдорд░ рдЯрдХреНрдХрд░ рдХреЗ рдЯреВрдЯрдиреЗ рдХреА рдЧрд╛рд░рдВрдЯреА рдирд╣реАрдВ рд╣реИ? тЭдя╕П
рд╣рд╛рдБ, рдЗрд╕рдХреА рдЧрд╛рд░рдВрдЯреА рд╣реИред рдпрд╣ @sentry/hub
рдкреИрдХреЗрдЬ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИ рдЬрд┐рд╕рдХрд╛ рд╡рд░реНрдгрди рдпрд╣рд╛рдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ - https://docs.sentry.io/enriching-error-data/scopes/?platform=browser
рд╣рдо рдпрд╣рд╛рдВ рдЗрд╕ рд╕реВрддреНрд░ рдореЗрдВ рдереЛрдбрд╝реЗ "рдЙрдиреНрдирдд рдЙрдкрдпреЛрдЧреЛрдВ" рдкрд░ рдЪрд░реНрдЪрд╛ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдФрд░ рд╣рдо рдЕрднреА рддрдХ рдЙрдиреНрд╣реЗрдВ рджрд╕реНрддрд╛рд╡реЗрдЬ рдХрд░рдиреЗ рдХреЗ рдмрд┐рдВрджреБ рдкрд░ рдирд╣реАрдВ рдкрд╣реБрдВрдЪреЗ рд╣реИрдВред рд╣рдо рдЗрд╕реЗ рдЕрдВрддрддрдГ рдХрд░реЗрдВрдЧреЗ :)
рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╣рдо рдпрд╣рд╛рдВ рдЬреЛ рдХреБрдЫ рдЦреЛ рд░рд╣реЗ рд╣реИрдВ рд╡рд╣ рд╣реИ рдЗрд╕ рддрд░рд╣ рдХреЗ рдЙрдиреНрдирдд рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдХреБрдЫ рджрд╕реНрддрд╛рд╡реЗрдЬ рдФрд░ рдЕрдЪреНрдЫрд╛ рдЕрднреНрдпрд╛рд╕ред рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ рдЬрдм рдЗрд╕реЗ рдкреНрд░рд▓реЗрдЦрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдпрд╛ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдПрдХ рдмреНрд▓реЙрдЧ рдкреЛрд╕реНрдЯ рднреА рдПрдХ рдЕрдЪреНрдЫреА рд╢реБрд░реБрдЖрдд рд╣реЛ рд╕рдХрддреА рд╣реИред
рдЕрдиреНрдпрдерд╛, рдирдпрд╛ рдПрд╕рдбреАрдХреЗ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдореЗрдВ рдЖрд╕рд╛рди рд╣реИ рдФрд░ рдПрдХреАрдХрд░рдг рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЕрдЪреНрдЫрд╛ рд╣реИред
@ рдХрд╛рдорд┐рд▓реЛрдЧреЛрд░реЗрдХ
рдХреНрдпрд╛ рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рдРрд╕рд╛ рдХреБрдЫ рдПрд╕рд┐рдВрдХ/рдкреНрд░рддреАрдХреНрд╖рд╛ рд╣реИрдВрдбрд▓рд░ рдореЗрдВ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП (рдЬрд╣рд╛рдВ рдЖрдк рдХреЙрд▓рдмреИрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ)?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);
рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╕рдВрддрд░реА рдореЗрдВ '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ред рдХрдо рд╕реЗ рдХрдо рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рддреМрд░ рдкрд░ рдХреБрдЫ рдкреНрд░рд▓реЗрдЦрд┐рдд рд╣реЛрдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ред 2019 рддрдХ рд╕рд░реНрд╡рд░ рд░рд╣рд┐рдд рддреЗрдЬреА рд╕реЗ рдмрдврд╝ рд░рд╣рд╛ рд╣реИ, рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрд╕ рдкрд░ рд╕рдВрддрд░реА рд╕реЗ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рд╕рдорд░реНрдерди рджреЗрдЦрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рдЬрд┐рди рд╡рд┐рдЪрд╛рд░реЛрдВ рдХреЛ рдореИрдВрдиреЗ рдпрд╣рд╛рдВ рдкрдврд╝рд╛ рдФрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдкрд╕рдВрдж рдХрд┐рдпрд╛ рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ рдпрд╣ рдерд╛ рдХрд┐ рдХрддрд╛рд░рдмрджреНрдз рд╕рднреА рдШрдЯрдирд╛рдУрдВ рдХреЛ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП 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 рд▓реИрдореНрдмреНрдбрд╛ рдХрдВрдЯреЗрдирд░ рдХреЗ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрддреЗ рд╣реИрдВред рдЬреЛ рдЯреАрдПрд▓; рдбреАрдЖрд░ рд╢рдмреНрджреЛрдВ рдореЗрдВ рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдПрдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдЬрд┐рд╕рдиреЗ рдЕрднреА-рдЕрднреА рдЕрдиреБрд░реЛрдз рдХрд┐рдпрд╛ рд╣реИ, рд╡рд╣ рдПрдХ рдирдП рдмреНрд░рд╛рдВрдб рдХреА рд╕реЗрд╡рд╛ рдХрд░ рд╕рдХрддреА рд╣реИ рдпрджрд┐ рдпрд╣ рд╕рдордп рдХреА рдПрдХ рдЫреЛрдЯреА рдЦрд┐рдбрд╝рдХреА рдкрд░ рдмрдирд╛рдИ рдЧрдИ рд╣реЛред рдЕрдЧрд░ рдореИрдВ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рджрд┐рдП рдЧрдП рдЗрд╕ рд╕реНрдирд┐рдкреЗрдЯ рдХреЗ рд╕рд╛рде рдХрдиреЗрдХреНрд╢рди рдмрдВрдж рдХрд░ рджреВрдВ, рдФрд░ рдХрдВрдЯреЗрдирд░ рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдП, рддреЛ рдореБрдЭреЗ рдирдП рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рдПрдХ рдирдпрд╛ рд╣рдм рдмрдирд╛рдиреЗ рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдореИрдВ рдЗрд╕реЗ рдЖрд╕рд╛рдиреА рд╕реЗ рдореБрд╢реНрдХрд┐рд▓ рд╣реЛрддреЗ рджреЗрдЦ рд╕рдХрддрд╛ рд╣реВрдВред рдЗрд╕рд▓рд┐рдП рдПрдХ рд╕рд╛рдзрд╛рд░рдг 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(...)
рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдлрд┐рд░ рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рд░реЛрдХреЗрдЧрд╛? рд▓реИрдореНрдмреНрдбрд╛ рдЙрд╕реА рдиреЛрдб рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдХреЙрд▓ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд╣реЛрдЧреА, рдЬреЛ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдкрд╣рд▓реА рдХреЙрд▓ рдХреЗ рдмрд╛рдж 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.
рдареАрдХ рд╣реИ, рд╣рдордиреЗ рдЕрднреА рдЗрд╕ рдорд╛рдорд▓реЗ рдкрд░ рдЯреАрдо рдореЗрдВ рдЖрдВрддрд░рд┐рдХ рд░реВрдк рд╕реЗ рдЪрд░реНрдЪрд╛ рдХреА рд╣реИред
рдЖрдк рд▓реЛрдЧ рд╕рд╣реА рдереЗ рдФрд░ рдЬрдмрдХрд┐ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЕрднреА рдЙрд╕ рддрд░рд╣ рд╕реЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдЬреИрд╕рд╛ рд╣рдордиреЗ рдЗрд╕реЗ рдкреНрд░рд▓реЗрдЦрд┐рдд рдХрд┐рдпрд╛ рд╣реИ рд╣рдо рдПрдХ flush
рдлрд╝рдВрдХреНрд╢рди рдкреЗрд╢ рдХрд░реЗрдВрдЧреЗ рдЬреЛ рдареАрдХ рд╡рд╣реА рдХрд░реЗрдЧрд╛ рдЬреЛ рдЖрдк рдЙрдореНрдореАрдж рдХрд░рддреЗ рд╣реИрдВред
рддреЛ рдЕрднреА рдЖрдк рдмрд┐рдирд╛ рдХрд┐рд╕реА рд╕рдорд╕реНрдпрд╛ рдХреЗ close
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реИ рдХрд┐ рд╣рдо рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдЧреНрд░рд╛рд╣рдХ рдХреЛ рдирд┐рдкрдЯрд╛рдиреЗ/рдЕрдХреНрд╖рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рдмрджрд▓рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ)ред
рд▓реЗрдХрд┐рди рдПрдХ flush
рдлрд╝рдВрдХреНрд╢рди рд╣реЛрдЧрд╛ рдЬреЛ _just_ flush
рдХрддрд╛рд░ рдореЗрдВ рд╣реИред
рдлреАрдЪрд░ рдЖрдиреЗ рдХреЗ рдмрд╛рдж рдореИрдВ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░ рджреВрдВрдЧрд╛ред
рдЪреВрдВрдХрд┐ рдореИрдВ рдЗрди рд╕рднреА рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рдереЛрдбрд╝рд╛ рдЦреЛ рдЧрдпрд╛ рд╣реВрдВ, рдХреНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдПрдХреНрд╕рдкреНрд░реЗрд╕ рддреНрд░реБрдЯрд┐ рд╣реИрдВрдбрд▓рд░ (рдЗрд╕ рд░реЗрдкреЛ рд╕реЗ рдПрдХ рдХреА рдирдХрд▓ рдХрд░рдирд╛) рдХреИрд╕рд╛ рджрд┐рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП?
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 рдореИрдВрдиреЗ рдХреЛрд╢рд┐рд╢ рдХреА рдФрд░ рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ, рдпрд╣ рд╕реНрдЯреИрдХ рдЯреНрд░реЗрд╕ рдХреЗ рд╕рд╛рде рдЕрддрд┐рд░рд┐рдХреНрдд рдбреЗрдЯрд╛ рдирд╣реАрдВ рднреЗрдЬрддрд╛ рд╣реИред рдпрд╣ рдореВрд▓ рд░реВрдк рд╕реЗ рд╕рд┐рд░реНрдл рд╕реНрдЯреИрдХ рдЯреНрд░реЗрд╕ рднреЗрдЬрддрд╛ рд╣реИред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛, рдУрдПрд╕ рдпрд╛ рдХреБрдЫ рднреА рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреЛрдИ рдЬрд╛рдирдХрд╛рд░реА рдирд╣реАрдВред
рдЖрд╣, рдпрд╣ рдмрд┐рд▓реНрдХреБрд▓ рднреА рдЕрдЪреНрдЫрд╛ рдирд╣реАрдВ рд╣реИ
рдЬрдмрдХрд┐ рд╣рдо flush
рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рддреЗ рд╣реИрдВ, рдЙрдкрд░реЛрдХреНрдд рджреЛрдиреЛрдВ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдзрд┐рдХ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд╕рдорд╛рдзрд╛рди рдХреЗ рд░реВрдк рдореЗрдВ рдЖрдк рд░рд┐рдкреЛрд░реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдкрд░рд┐рдгрд╛рдо рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, _рдФрд░_ рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рд╕реНрдирд┐рдкреЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рджрд╛рдпрд░рд╛ рд╢рд╛рдорд┐рд▓ рдХрд░реЗрдВ:
const scope = Sentry.getCurrentHub().getScope();
await Sentry.getCurrentHub().getClient().captureException(error, scope);
рдореИрдВ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рдФрд░ рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореЗрд░реЗ рд▓рд┐рдП рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд░реВрдк рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд░рд┐рдкреЛрд░реНрдЯ рдХреА рдЧрдИ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдЬреЛ рдХреБрдЫ рднреА рдореИрдВ рдЙрдореНрдореАрдж рдХрд░рддрд╛ рд╣реВрдВред
рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдиреЗрдЯрд▓рд┐рдлрд╛рдИ рдлрдВрдХреНрд╢рдВрд╕ рдХреЗ рд╕рд╛рде рдпрд╣ рд╕рдм рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рд╕рд┐рджреНрдзрд╛рдВрдд рд▓реИрдореНрдмреНрдбрд╛ рдЖрджрд┐ рдХреЗ рд╕рд╛рде рд╕рдорд╛рди рд╣реИред рдореИрдВрдиреЗ рдПрдХ рдкреЛрд╕реНрдЯ рд▓рд┐рдЦрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдпрд╣ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкреВрд░реА рдЬрд╛рдирдХрд╛рд░реА рд╣реИ, рдЕрдЧрд░ рдХреЛрдИ рджрд┐рд▓рдЪрд╕реНрдкреА рд▓реЗрддрд╛ рд╣реИ: https://httptoolkitред рддрдХрдиреАрдХ/рдмреНрд▓реЙрдЧ/netlify-рдлрд╝рдВрдХреНрд╢рди-рддреНрд░реБрдЯрд┐-рд░рд┐рдкреЛрд░реНрдЯрд┐рдВрдЧ-рд╕рд╛рде-рд╕рдВрддрд░реА/
рдореИрдВ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдЕрдкрдиреЗ рд╕рднреА рд▓реИрдореНрдмреНрдбрд╛ рдореЗрдВ рдЗрд╕ рд╕рд╣рд╛рдпрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВред
@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()
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╕рднреА рджрд╛рдпрд░реЗ/рдЕрддрд┐рд░рд┐рдХреНрдд рдбреЗрдЯрд╛ рдХреЛ рдмрд┐рдирд╛ рдХрд┐рд╕реА рджреЗрд╡ рд╕рд╣рднрд╛рдЧрд┐рддрд╛ рдХреЗ рд╕рдВрд░рдХреНрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
рд╕рдлрд▓/рд╕рдордп рд╕рдорд╛рдкреНрдд рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рд╕рд╛рде рдпрд╣рд╛рдВ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
рдЖрд╢рд╛ рд╣реИ рдпреЗ рдорджрдж рдХрд░реЗрдЧрд╛! :)
рдЕрдЪреНрдЫрд╛!
рдХреНрдпрд╛ рдЕрднреА рднреА рд▓реИрдореНрдмреНрдбрд╛ рдФрд░ рдЕрдиреНрдп рд╕рд░реНрд╡рд░ рд░рд╣рд┐рдд рд╕рдорд╛рдзрд╛рдиреЛрдВ рд╕реЗ рдЕрдкрд╡рд╛рджреЛрдВ рдХреЛ рдкрдХрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдиреНрдпреВрдирддрдо рдкреИрдХреЗрдЬ рдмрдирд╛рдиреЗ рдХреА рдпреЛрдЬрдирд╛ рд╣реИ? рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЕрднреА рднреА рдПрдХ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рдЬреЛрдбрд╝ рд╣реЛрдЧрд╛ тЭдя╕П
@LinusU рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рд╣рд╛рдБ, рд▓реЗрдХрд┐рди рд╣рдо рдЕрднреА рдЕрдиреНрдп рднрд╛рд╖рд╛рдУрдВ рдХреЗ рдПрд╕рдбреАрдХреЗ рдХреЗ рд╕рд╛рде рдмрд╣ рдЧрдП рд╣реИрдВ
рд╕рднреА рд╕рдВрднрд╛рд╡рд┐рдд рд╕рдорд╛рдзрд╛рдиреЛрдВ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рдпрд╣рд╛рдВ рдЖрдиреЗ рд╡рд╛рд▓реЗ рд╕рднреА рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЯреАрдПрд▓; рдбреЙ
рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ: await Sentry.flush()
рд╕рднреА рд▓рдВрдмрд┐рдд рдЕрдиреБрд░реЛрдз рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП, рдЗрд╕реЗ 4.6.x
рдореЗрдВ рдкреЗрд╢ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
рдЗрд╕реЗ рдмрдВрдж рдХрд░рддреЗ рд╣реБрдП, рдХреГрдкрдпрд╛ рдмреЗрдЭрд┐рдЭрдХ рдПрдХ рдирдпрд╛ рдЕрдВрдХ рдЦреЛрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣реЗрдВ, рдЕрдЧрд░ рдХреБрдЫ рднреА рдЧрд╛рдпрдм рд╣реИ (рд▓реЗрдХрд┐рди рдпрд╣ рдзрд╛рдЧрд╛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмрд╣реБрдд рд▓рдВрдмрд╛ рд╣реИ)ред
рдЪреАрдпрд░реНрд╕
@kamilogorek рдЕрд░реЗ! рдПрдХ рддреНрд╡рд░рд┐рдд fyi, рдореИрдВ рдкреБрд░рд╛рдиреЗ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдХреЗ рд╕реНрдерд╛рди рдкрд░ рдЕрдкрдиреЗ рдРрдк рдореЗрдВ Sentry.flush
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдХрд┐рд╕реА рднреА рддреНрд░реБрдЯрд┐ рдХреА рд╕реВрдЪрдирд╛ рдирд╣реАрдВ рджреА рдЬрд╛ рд░рд╣реА рд╣реИред рдореИрдВ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдЕрджреНрдпрддрди flush
рдкрджреНрдзрддрд┐ рд╕реЗ рдкреБрд░рд╛рдиреЗ рд╕рдорд╛рдзрд╛рди рдкрд░ рд╡рд╛рдкрд╕ рд▓реМрдЯ рд░рд╣рд╛ рд╣реВрдВред
@zeusdeux рдХреНрдпрд╛ рдЗрд╕рдХреЗ рд▓рд┐рдП рдЖрдк рдХреБрдЫ рдбреАрдмрдЧ рдЬрд╛рдирдХрд╛рд░реА/рд░реЗрдкреНрд░реЛ рдХреЗрд╕ рдкреНрд░рджрд╛рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ?
рдЖрдк captureException
рд╡рд┐рдзрд┐ рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдЬреЛ рдИрд╡реЗрдВрдЯ рдХреЛ рдмрдлрд░ рдореЗрдВ рдЬреЛрдбрд╝рддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рдЖрдкрдХреЛ flush
await
рдЪрд╛рд╣рд┐рдПред рдХреНрдпрд╛ рдЖрдкрдиреЗ рдЗрд╕реЗ "рдирд┐рдпрдорд┐рдд рддрд░реАрдХреЗ рд╕реЗ" рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд┐рдпрд╛ рд╣реИ?
@kamilogorek рдореЗрд░реА рдЗрдЪреНрдЫрд╛ рд╣реИ рдХрд┐ рдореЗрд░реЗ рдкрд╛рд╕ рдбреАрдмрдЧ рдЬрд╛рдирдХрд╛рд░реА рд╣реЛ рд▓реЗрдХрд┐рди рд▓реЙрдЧ рдореЗрдВ рдХреБрдЫ рднреА рдирд╣реАрдВ рд╣реИред рдореИрдВрдиреЗ рд╣рдореЗрд╢рд╛ await
рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб captureException
рдкрд░ рдХрд┐рдпрд╛ ред рдирд┐рдпрдорд┐рдд рд░реВрдк рд╕реЗ, рдХреНрдпрд╛ рдЖрдкрдХрд╛ рдорддрд▓рдм 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);
рдореЗрд░реЗ рд▓рд┐рдП рднреА ~ рдирд╣реАрдВ ~ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИред
@tanduong рдХреНрдпрд╛ рдЖрдк рд░реЗрдкреНрд░реЛ рдХреЗрд╕ рдкреНрд░рджрд╛рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ? рдХреЗрд╡рд▓ рдпрд╣ рдХрд╣рдирд╛ рдХрд┐ рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдмрд╣реБрдд рдорджрджрдЧрд╛рд░ рдирд╣реАрдВ рд╣реИ
@kamilogorek рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдореБрдЭреЗ рдЕрднреА рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐
await Sentry.getCurrentHub().getClient().close(2000)
рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдореЗрд░рд╛ рд▓реИрдореНрдмреНрдбрд╛ рдлрд╝рдВрдХреНрд╢рди рд╡реАрдкреАрд╕реА рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рд╣реИред
рдореИрдВ рдкреБрд╖реНрдЯрд┐ рдХрд░рддрд╛ рд╣реВрдБ рдХрд┐
await Sentry.flush(2000);
рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИред
BTW, рддреЛ рдЖрдк VPC рдореЗрдВ рд▓реИрдореНрдмреНрдбрд╛ рд╕реЗ рдХреИрд╕реЗ рдирд┐рдкрдЯреЗрдВрдЧреЗ? NAT рдЧреЗрдЯрд╡реЗ рд╕реЗ рдЕрдЯреИрдЪ рдХрд░реЗрдВ? рдореБрдЭреЗ рд╕рд┐рд░реНрдл рд╕рдВрддрд░реА рдЪрд╛рд╣рд┐рдП рд▓реЗрдХрд┐рди рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдЗрдВрдЯрд░рдиреЗрдЯ рдирд╣реАрдВред
@tanduong рд╕рдВрддрд░реА рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдЗрдВрдЯрд░рдиреЗрдЯ рдкрд░ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрджрд┐ рдЖрдкрдХрд╛ рд▓реИрдореНрдмреНрдбрд╛ рдЖрдкрдХреЗ VPC рдХреЗ рднреАрддрд░ рдЪрд▓ рд░рд╣рд╛ рд╣реИ, рддреЛ рд╣рд╛рдБ рдЖрдкрдХреЗ рдкрд╛рд╕ NAT рдЧреЗрдЯрд╡реЗ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЕрдиреНрдпрдерд╛ рдЖрдкрдХреЛ рд╣реЛрд╕реНрдЯреЗрдб рд╕рдВрддрд░реА рд╡рд┐рдХрд▓реНрдк рддрд▓рд╛рд╢рдирд╛ рд╣реЛрдЧрд╛ред
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()
рдкрд╣рд▓реЗ рдХреИрдкреНрдЪрд░ рдореИрд╕реЗрдЬ рдХреЙрд▓ рдХреЗ рдмрд╛рдж рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╕рдорд╛рдкреНрдд рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред
рдореЗрд░реЗ рдкрд╛рд╕ рд╡рд╣реА рд╣реИ рдЬреЛ рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛтАЛтАЛрд╣реИ рдХрд┐ @enapupe рдЬреИрд╕рд╛ рд╣реА рдореБрджреНрджрд╛ рд╣реИред рдпрджрд┐ рдЖрдк рд╕рдорд╛рдирд╛рдВрддрд░ рдореЗрдВ await client.flush(2000);
рдкрд░ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдХреЗрд╡рд▓ рдкрд╣рд▓рд╛ рд╡рд╛рджрд╛ рд╣рд▓ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рдПрдбрдмреНрд▓реНрдпреВрдПрд╕ рд▓реИрдореНрдмреНрдбрд╛ рд╕рдВрджрд░реНрднреЛрдВ рдореЗрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдЬрд╣рд╛рдВ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рд╣реИрдВрдбрд▓рд░ рдХреЛ рдХрдИ рд╕рдорд╡рд░реНрддреА рдХреЙрд▓реЛрдВ рдХреЗ рдмреАрдЪ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдореИрдВ рдЗрд╕ рддрд░рд╣ рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдБ:
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 рдореЗрдВ рдЖрдкрдХреЗ рд╕рдорд╛рдзрд╛рди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рдиреЛрдЯ рдЬреЛрдбрд╝рд╛ред рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛтАЛтАЛрд╣реИ рдХрд┐ рдпрд╣ рд╕рдорд╡рд░реНрддреА рдлреНрд▓рд╢ рдкрд░ рдкреНрд░рджрд░реНрд╢рди рд░рд┐рдЧреНрд░реЗрд╢рди рдХрд╛ рдХрд╛рд░рдг рдмрди рдЬрд╛рдПрдЧрд╛ред
рдЕрдЧрд░ рдХрд┐рд╕реА рдХреЛ рдХреЛрдИ рдкрд░реЗрд╢рд╛рдиреА рд╣реЛ рд░рд╣реА рд╣реИред
рдпрд╣ рдЦреВрдмрд╕реВрд░рддреА рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ
@рд╕рд░рд╕рдЖрд░реНрдпрд╛ @HazAT
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ... рдЕрдкрдирд╛ рд╕рдорд╛рдзрд╛рди рд╕рд╛рдЭрд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж! :)
configScope рд╡рд┐рдзрд┐ рдХрд╛ рдПрдХ рдХреЙрд▓рдмреИрдХ рд╣реИ рдЬреЛ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ рдХреИрдкреНрдЪрд░ рдЕрдкрд╡рд╛рдж рд╕реЗ рдкрд╣рд▓реЗ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рд▓реЗрдХрд┐рди рдпрд╣ рдЙрд╕реА "рдереНрд░реЗрдб" рдореЗрдВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИред
рдХреНрдпрд╛ рдпрд╣ рджреМрдбрд╝ рдХреА рд╕реНрдерд┐рддрд┐ рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдХрд╛ рдХрд╛рд░рдг рдирд╣реАрдВ рдмрди рд╕рдХрд╛?
@cibergarri рдореБрдЭреЗ рдРрд╕рд╛ рдирд╣реАрдВ рд▓рдЧрддрд╛, рдореЗрд░реЗ рд▓рд┐рдП рддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рджрд┐рдЦрддрд╛ рд╣реИ, рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рд╡рд╣рд╛рдВ рдПрдХ рдПрд╕рд┐рдВрдХ рд╡рд┐рдзрд┐ рд╣реИ, рддреЛ рджреМрдбрд╝ рдХреА рд╕реНрдерд┐рддрд┐ рд╣реЛрдЧреАред
рд╡рд┐рдЪрд╛рд░ рд╕рд░рдгреА рдХреЗ рдорд╛рдирдЪрд┐рддреНрд░ рдЬреИрд╕рд╛ рд╣реИ рдХрд┐ рд╡рд╣реА рдмрд╛рдд рдпрд╣рд╛рдВ рд╣реЛ рд░рд╣реА рд╣реИред рдпрджрд┐ рдЖрдкрдХреЛ рдЗрд╕рдХреЗ рдЪрд╛рд░реЛрдВ рдУрд░ рдЕрдкрдирд╛ рд╕рд┐рд░ рд▓рдкреЗрдЯрдиреЗ рдореЗрдВ рд╕рдорд╕реНрдпрд╛ рд╣реИред рдореБрдЭреЗ рдЖрд╢рд╛ рд╣реИ рдХрд┐ рд╡рд╣ рдорджрдж рдХрд░реЗрдВрдЧреЗред
рд╣рд╛рдБ, рдРрд╕рд╛ рдХрд░рдирд╛ рдмрд┐рд▓рдХреБрд▓ рдареАрдХ рд╣реИ
рдЕрдкрдбреЗрдЯ: рд╕рдВрддрд░реА рдЕрдм рдиреЛрдб/рд▓реИрдореНрдмреНрдбрд╛ рд╡рд╛рддрд╛рд╡рд░рдг рдХреЗ рд▓рд┐рдП рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рддреНрд░реБрдЯрд┐ рдХреИрдкреНрдЪрд░ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ: https://docs.sentry.io/platforms/node/guides/aws-lambda/
рдореИрдВ рдЗрд╕ рддрд░рд╣ @ рд╕рдВрддрд░реА/рд╕рд░реНрд╡рд░ рд░рд╣рд┐рдд рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ:
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% рд▓реЙрдЧрд┐рдВрдЧ рдХрд░ рд░рд╣рд╛ рд╣реИред
рдХреЛрдИ рд╕рд▓рд╛рд╣?
@ рдЕрд░рдорд╛рдВрдбреЛ25723
рдХреГрдкрдпрд╛ рдмрддрд╛рдПрдВ рдХрд┐ рдЖрдкрдиреЗ рдпрд╣ рдХреИрд╕реЗ рдорд╛рдк рд▓рд┐рдпрд╛ рдХрд┐ рдпрд╣ рдЕрдкрд╡рд╛рдж рдШрдЯрдирд╛рдУрдВ рдХреЛ рдЦреЛ рджреЗрддрд╛ рд╣реИ? рдХреНрдпрд╛ рдЖрдкрдХреЗ рдкрд╛рд╕ рдПрдХ рдХреЛрдб рдирдореВрдирд╛ рд╣реИ рдХрд┐ рдЗрд╕ рддрд░рд╣ рдХреЗ рдЦреЛрдП рд╣реБрдП рдЕрдкрд╡рд╛рдж рдХреЛ рдХреИрд╕реЗ рдлреЗрдВрдХрд╛ рдЧрдпрд╛? рдЕрдзрд┐рдХ рд╕рдВрджрд░реНрдн рдЪрд╛рд╣рд┐рдПред
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();
рдФрд░ рдирд┐рд╕реНрддрдмреНрдзрддрд╛ рдХреЗ рдмрд┐рдирд╛
рд╡рд╣реА рдкрд░рд┐рдгрд╛рдо
@ рдорд╛рд░реНрд╢рд▓-рд▓реА рдЖрдк рдХреНрдпрд╛ рд╕рд▓рд╛рд╣ рджреЗрддреЗ рд╣реИрдВ? рдХреНрдпрд╛ рдореБрдЭреЗ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдкреИрджрд╛ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдП, рдореИрдВ рдпрд╣рд╛рдБ рдлрдВрд╕ рдЧрдпрд╛ рд╣реВрдБред
@ armando25723 рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╕рд░реНрд╡рд░ рдЗрди рдШрдЯрдирд╛рдУрдВ рдХреЛ рднреЗрдЬрддреЗ рд╕рдордп 429 (рдмрд╣реБрдд рдЕрдзрд┐рдХ рдЕрдкрд╡рд╛рдж) рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рджреЗ рд░рд╣рд╛ рд╣реИред рд╣рдо рдЗрд╕реЗ рдЕрдзрд┐рдХ рдХреЛрдЯрд╛/рджрд░ рд╕реАрдорд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдкрд░рд┐рджреГрд╢реНрдпреЛрдВ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдлреЗрдВрдХ рджреЗрддреЗ рд╣реИрдВред рдХреНрдпрд╛ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдЖрдк рдХреНрд░рдорд┐рдХ рд░реВрдк рд╕реЗ рддреНрд░реБрдЯрд┐рдпрд╛рдБ рднреЗрдЬ рд░рд╣реЗ рд╣реИрдВ рдпрд╛ рдХреЛрдЯрд╛ рд╕реЗ рдЕрдзрд┐рдХ? рд╣рдо рдЖрдЧреЗ рдбрд┐рдмрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрджрд┐ рдЖрдкрдХреЛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпреЗ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рддреНрд░реБрдЯрд┐ рдШрдЯрдирд╛рдПрдВ рд╣реИрдВ рдФрд░ рдЖрдк рдлреНрд░реА рдЯрд┐рдпрд░ рдХреЗ рд▓рд┐рдП рд╣рдорд╛рд░реА 5k рд╕реАрдорд╛ рдХреЗ рдЕрдВрддрд░реНрдЧрдд рд╣реИрдВред
@ajjindal рдЕрдиреНрдп рд╕рднреА рдкрд░рд┐рдпреЛрдЬрдирд╛рдПрдВ рд╕рдВрддрд░реА рдХреЗ рд╕рд╛рде рдареАрдХ рдХрд╛рдо рдХрд░ рд░рд╣реА рд╣реИрдВред рд╕рдВрдЧрдарди рд╕реНрд▓рдЧ "рдПрд▓реЗрдЧреНрд░рд╛" рд╣реИ, рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХрд╛ рдирд╛рдо рдореЗрд▓-рдбрд┐рд╕реНрдкреИрдЪ-рд╕рд░реНрд╡рд░ рд░рд╣рд┐рдд рд╣реИ #mail-micros рдХреЗ рдЕрдВрддрд░реНрдЧрддред рд╣рдо рд▓рдВрдмреЗ рд╕рдордп рд╕реЗ рд╕рдВрддрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдкрд╣рд▓реА рдмрд╛рд░ рд╕рд░реНрд╡рд░ рд░рд╣рд┐рддред рдпрд╣ рдлреНрд░реА рдЯрд┐рдпрд░ рдирд╣реАрдВ рд╣реИ, рдореИрдВ рдЖрдкрдХреЛ рдпрд╣ рдирд╣реАрдВ рдмрддрд╛ рд╕рдХрддрд╛ рдХрд┐ рд╣рдо рдХрд┐рд╕ рдкреНрд▓рд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рд▓реЗрдХрд┐рди рдпрд╣ рдкреЗрдб рд╣реИред
рдпрд╣ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ рдпрджрд┐ рдЖрдк рдореБрдЭреЗ рдФрд░ рдбреАрдмрдЧ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░ рд╕рдХреЗрдВред
рдЬрд╡рд╛рдм рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж : )
рдкреАрдбреА: рдЯреАрдо рдкреНрд▓рд╛рди рд╣реИ
рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА
@LinusU рд╣рдо рдЗрд╕ рдкрд░рд┐рджреГрд╢реНрдп рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕рд░реНрд╡рд░ рд░рд╣рд┐рдд рдкреИрдХреЗрдЬ рдмрдирд╛рдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рд░рдЦрддреЗ рд╣реИрдВред рд╣рдореЗрдВ рдмрд╕ рдХреБрдЫ рд╕рдордп рдирд┐рдХрд╛рд▓рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╕рд╛рд▓ рдХрд╛ рдЕрдВрдд рд╣реИ рдФрд░ рдЪреАрдЬреЗрдВ рдЕрдм рднреАрдбрд╝рднрд╛рдбрд╝ рд╡рд╛рд▓реА рд╣реЛ рд░рд╣реА рд╣реИрдВред рдЖрдкрдХреЛ рд╕реВрдЪрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд░рд╣реЗрдЧрд╛!