Last active
May 4, 2024 13:03
-
-
Save williamdes/1d0b02c1bf3b94ee0dbaecdbc26d12c1 to your computer and use it in GitHub Desktop.
Pure NodeJs Sentry reporter compatible with AWS lambda
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @source https://github.com/errwischt/stacktrace-parser/blob/9b2d5b6114e7a3b3596f7092f0d1160738125374/src/stack-trace-parser.js | |
* @copyright Copyright (c) 2014-2019 Georg Tavonius | |
* @license MIT | |
* This is the same code but only with removed parsing for all browsers or JS platforms else than NodeJS | |
*/ | |
const StackTraceParser = { | |
UNKNOWN_FUNCTION: '<unknown>', | |
/** | |
* This parses the different stack traces and puts them into one format | |
* This borrows heavily from TraceKit (https://github.com/csnover/TraceKit) | |
*/ | |
parse(stackString) { | |
const lines = stackString.split('\n'); | |
return lines.reduce((stack, line) => { | |
const parseResult = StackTraceParser.parseNode(line); | |
if (parseResult) { | |
stack.push(parseResult); | |
} | |
return stack; | |
}, []); | |
}, | |
nodeRe: /^\s*at (?:((?:\[object object\])?[^\\/]+(?: \[as \S+\])?) )?\(?(.*?):(\d+)(?::(\d+))?\)?\s*$/i, | |
parseNode(line) { | |
const parts = StackTraceParser.nodeRe.exec(line); | |
if (!parts) { | |
return null; | |
} | |
return { | |
file: parts[2], | |
methodName: parts[1] || StackTraceParser.UNKNOWN_FUNCTION, | |
arguments: [], | |
lineNumber: +parts[3], | |
column: parts[4] ? +parts[4] : null, | |
}; | |
}, | |
}; | |
const https = require('https'); | |
const crypto = require('crypto'); | |
const os = require('os'); | |
const SENTRY_HOST = 'sentry.io'; | |
const SENTRY_PROJECTID = 123456; | |
const SENTRY_KEY = 'xxxxxxxxxxx'; | |
const LOGGER_NAME = 'my-logger'; | |
/** | |
* @copyright Copyright (c) 2024 William Desportes <[email protected]> | |
* @license MIT | |
* @version 1.0 | |
* @source https://gist.github.com/williamdes/1d0b02c1bf3b94ee0dbaecdbc26d12c1 | |
*/ | |
const sendToSentry = function (error, URLroute, requestMethod, requestHeaders, userId, userIP, tags, release) { | |
// See: https://develop.sentry.dev/sdk/envelopes/#data-model | |
const sentryData = { | |
// See: https://stackoverflow.com/a/69358886/5155484 | |
event_id: crypto.randomBytes(16).toString('hex'), | |
timestamp: new Date().getTime(), //.toISOString(), | |
logger: LOGGER_NAME, | |
platform: 'javascript', | |
level: 'error', | |
message: error.message, | |
transaction: URLroute, | |
tags: tags, | |
release: release, | |
exception: { | |
type: error.name, | |
value: error.message, | |
handled: true, // Best guess depending on the code | |
stacktrace: { | |
frames: StackTraceParser.parse(error.stack).map((traceBit) => { | |
return { | |
in_app: traceBit.file.indexOf('node:') === -1, | |
filename: traceBit.file, | |
function: traceBit.methodName, | |
vars: traceBit.arguments, | |
lineno: traceBit.lineNumber, | |
}; | |
}), | |
}, | |
}, | |
user: { | |
id: userId, | |
ip_address: userIP, | |
}, | |
sdk: { | |
name: 'Mini-Sentry-JS', | |
version: '1.0', | |
}, | |
contexts: { | |
// See: https://github.com/getsentry/develop/blob/24.4.2/src/docs/sdk/event-payloads/contexts.mdx#os-context | |
os: { | |
name: process.platform, | |
type: 'os', | |
version: os.release(), | |
}, | |
runtime: { | |
name: process.release.name, | |
type: 'runtime', | |
version: process.version, | |
}, | |
device: { | |
arch: process.arch, | |
memory_size: os.totalmem(), | |
free_memory: os.freemem(), | |
}, | |
hostname: os.hostname(), | |
}, | |
request: { | |
url: URLroute, | |
method: requestMethod, | |
headers: requestHeaders, | |
}, | |
}; | |
const sentryUrl = 'https://' + SENTRY_HOST + '/api/' + SENTRY_PROJECTID + '/store/'; | |
const data = JSON.stringify(sentryData); | |
const httpOptions = { | |
method: 'POST', | |
headers: { | |
'User-Agent': 'Mini-Sentry-JS/1.0', | |
'Content-Type': 'application/json', | |
'X-Sentry-Auth': 'Sentry sentry_version=7, sentry_key=' + SENTRY_KEY + ', sentry_client=mini-sentry-js/1.0', | |
Accept: 'application/json', | |
'Content-Length': data.length, // Thank you https://flaviocopes.com/node-http-post/ | |
}, | |
}; | |
const request = https.request(sentryUrl, httpOptions, (res) => { | |
//console.log(`statusCode: ${res.statusCode}`); | |
res.on('data', (d) => { | |
// Enable to inspect the received data | |
// console.log('sentry said: ' + d); | |
}); | |
}); | |
request.on('error', (error) => { | |
console.error(error); | |
}); | |
request.write(data); | |
request.end(); | |
// Enable to inspect the sent data | |
//console.log(sentryData); | |
}; | |
// ----------- Example -------------- | |
try { | |
throw new Error('Invalid foo bar'); | |
} catch (e) { | |
sendToSentry(e, '/app', 'POST', [['Accept', 'application/json']], '1234', '127.0.0.1', { | |
fooTag: 'barTag', | |
}, '1.2.3'); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment