UNPKG

edgerender

Version:
121 lines 4.03 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Sentry = exports.setupSentry = void 0; function setupSentry(dsn, environment, release) { const m = dsn.match(/^https:\/\/(.+?)@(.+?)\.ingest\.sentry\.io\/(.+)/); if (m) { const [, key, server, app] = m; return new Sentry(key, server, app, environment, release); } else { console.warn('invalid sentry DSN', dsn); } } exports.setupSentry = setupSentry; class Sentry { key; server; app; release; environment; constructor(key, server, app, environment, release) { this.key = key; this.server = server; this.app = app; this.environment = environment || 'production'; this.release = release; } captureMessage(event, message, { level = 'info', extra = {} } = {}) { event.waitUntil(this.capture(event.request, { message, level, extra })); } captureException(event, exc, { level = 'error', extra = {} } = {}) { const message = exc.toString() || exc.message || 'Unknown error'; event.waitUntil(this.capture(event.request, { exception: { mechanism: { handled: true, type: 'generic' }, values: [ { type: 'Error', value: message, stacktrace: { frames: get_frames(exc.stack) }, }, ], }, message, level, extra, })); } async capture(request, data) { const sentry_data = Object.assign({ platform: 'javascript', logger: 'cloudflare', environment: this.environment, fingerprint: [`${request.method}-${request.url}-${data.message || 'null'}`], user: { ip_address: request.headers.get('CF-Connecting-IP'), }, request: { url: request.url, method: request.method, headers: Object.fromEntries(request.headers), }, extra: {}, }, data); sentry_data.extra.cloudflare = request.cf; // console.log('sentry data:', sentry_data) // if (this.release) { // defaults.release = this.release // } const params = { sentry_key: this.key, sentry_version: 7, sentry_client: 'edgerender; https://github.com/samuelcolvin/edgerender', }; const args = Object.entries(params) .map(([k, v]) => `${k}=${encodeURIComponent(v)}`) .join('&'); const sentry_url = `https://sentry.io/api/${this.app}/store/?${args}`; return await fetch(sentry_url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(sentry_data), }); } } exports.Sentry = Sentry; function get_frames(stack) { if (!stack) { return []; } const lines = stack.split('\n'); lines.splice(0, 1); return lines .reverse() .filter(line => line.match(/^ {4}at /)) .map(extract_frame); } const frame_regexes = [ /^ +at (?<func>.+?) \((?<filename>.+?):(?<lineno>\d+):(?<colno>\d+)\)/, /^ +at (?<func>.+?):(?<lineno>\d+):(?<colno>\d+)/, /^ +at (?<func>.+?) \(/, ]; function extract_frame(line) { for (const regex of frame_regexes) { const m = line.match(regex); if (m) { const { func, filename, lineno, colno } = m.groups; const f = { in_app: true, filename: `~/${filename || '__unknown__.js'}`, function: func, }; if (lineno) { Object.assign(f, { lineno: parseInt(lineno), colno: parseInt(colno) }); } return f; } } throw Error(`no frame found in stack line: "${line}"`); } //# sourceMappingURL=sentry.js.map