Skip to content

Instantly share code, notes, and snippets.

@williamdes
Last active May 4, 2024 13:03
Show Gist options
  • Select an option

  • Save williamdes/1d0b02c1bf3b94ee0dbaecdbc26d12c1 to your computer and use it in GitHub Desktop.

Select an option

Save williamdes/1d0b02c1bf3b94ee0dbaecdbc26d12c1 to your computer and use it in GitHub Desktop.

Revisions

  1. williamdes revised this gist May 4, 2024. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions sentry-pure-js-node-js-reporter.js
    Original file line number Diff line number Diff line change
    @@ -59,7 +59,7 @@ const LOGGER_NAME = 'my-logger';
    * @version 1.0
    * @source https://gist.github.com/williamdes/1d0b02c1bf3b94ee0dbaecdbc26d12c1
    */
    const sendToSentry = function (error, URLroute, requestMethod, requestHeaders, userId, userIP, tags) {
    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
    @@ -71,6 +71,7 @@ const sendToSentry = function (error, URLroute, requestMethod, requestHeaders, u
    message: error.message,
    transaction: URLroute,
    tags: tags,
    release: release,
    exception: {
    type: error.name,
    value: error.message,
    @@ -161,5 +162,5 @@ try {
    } catch (e) {
    sendToSentry(e, '/app', 'POST', [['Accept', 'application/json']], '1234', '127.0.0.1', {
    fooTag: 'barTag',
    });
    }, '1.2.3');
    }
  2. williamdes revised this gist May 4, 2024. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions sentry-pure-js-node-js-reporter.js
    Original file line number Diff line number Diff line change
    @@ -57,6 +57,7 @@ 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) {
    // See: https://develop.sentry.dev/sdk/envelopes/#data-model
  3. williamdes created this gist May 4, 2024.
    164 changes: 164 additions & 0 deletions sentry-pure-js-node-js-reporter.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,164 @@
    /**
    * @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
    */
    const sendToSentry = function (error, URLroute, requestMethod, requestHeaders, userId, userIP, tags) {
    // 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,
    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',
    });
    }