Giter VIP home page Giter VIP logo

raygun4node's Introduction

Raygun4Node

GitHub CI

Raygun.com package for Node, written in TypeScript.

Where is my app API key?

When sending exceptions to the Raygun service, an app API key is required to map the messages to your application.

When you create a new application in your Raygun dashboard, your app API key is displayed within the instructions page. You can also find the API key by clicking the "Application Settings" button in the side bar of the Raygun dashboard.

Getting Started

Install the module with: npm install raygun

const raygun = require('raygun');

const raygunClient = new raygun.Client().init({
  apiKey: 'YOUR_API_KEY'
});

You can also use import, which is useful for loading TypeScript definitions. In order to load type definitions, you can use import * as Raygun from 'raygun', or import the Client class directly from the module.

import * as Raygun from 'raygun';

const raygunClient = new Raygun.Client().init({
  apiKey: 'YOUR_API_KEY'
});

You can directly send errors to Raygun, either by making the error yourself or passing a caught error.

raygunClient.send(new Error('Something impossible happened!'));

If you use express, you can report the errors that express catches to Raygun by using the middleware.

// Add at the end of the middleware definitions, just above app.listen:
app.use(raygunClient.expressHandler);

You can directly catch errors in your application code and report them to Raygun.

try {
  // run some code that might throw an error we want to report
} catch (e) {
  raygunClient.send(e);
}

A similar example for Node style callbacks:

function handleResult(error, result) {
  if (error) {
    raygunClient.send(error);
    return;
  }

  // process result
}

If you're working directly with promises, you can pass raygunClient.send directly to .catch.

const axios = require('axios');

axios
  .get('example.com')
  .then(handleResponse)
  .catch(raygunClient.send);

Expressjs 4.0 and above

The Express documentation says Though not strictly required, by convention you define error-handling middleware last, after other app.use() calls, but that is incorrect. If the app.use(raygunClient.expressHandler); call is not immediately before the app.listen call, then errors will not be handled by Raygun.

Note that the Express middleware handler will pick up and transmit any err objects that reach it. If the app code itself chooses to handle states that result in 4xx/5xx status codes, these will not result in an error payload sent to Raygun.

Documentation

Send

The send() function is asynchronous and returns a Promise of type IncomingMessage.

Note that IncomingMessage can be null if the request was stored because the application was offline.

IncomingMessage is the response from the Raygun API - there's nothing in the body, it's just a status code response. If everything went ok, you'll get a 202 response code. Otherwise, we throw 401 for incorrect API keys, 403 if you're over your plan limits, or anything in the 500+ range for internal errors.

We use the nodejs http/https library to make the POST to Raygun, you can see more documentation about that callback here: https://nodejs.org/api/http.html#http_http_request_options_callback

You can await the call to obtain the result, or use then/catch.

Using await

Use await to obtain the IncomingMessage, remember to catch any possible thrown errors from the send() method.

try {
  let message = await client.send(error);
} catch (e) {
  // error sending message
}

Using then/catch

You can also use then() to obtain the IncomingMessage, as well, use catch() to catch any possible thrown errors from the send() method.

client.send(error)
  .then((message) => {
    // message sent to Raygun
  })
  .catch((error) => {
      // error sending message
  });

Send Parameters

The send() method accepts a series of optional named parameters, defined as follows:

client.send(error, { customData, request, tags, timestamp, userInfo });

Each one of these parameters is optional. They are explained in detail the following sections.

Sending custom data

You can pass custom data in on the Send() function, as the customData parameter. For instance (based off the call in test/raygun_test.js):

client.send(new Error(), { customData: { 'mykey': 'beta' } });

Sending custom data with Expressjs

If you're using the raygunClient.expressHandler, you can send custom data along by setting raygunClient.expressCustomData to a function. The function will get two parameters, the error being thrown, and the request object.

const raygunClient = new raygun.Client().init({apiKey: "YOUR_API_KEY"});

raygunClient.expressCustomData = function (err, req) {
  return { 'level': err.level };
};

Sending request data

You can send the request data in the Send() function, as the request parameter. For example:

client.send(new Error(), { request: request });

If you want to filter any of the request data then you can pass in an array of keys to filter when you init the client. For example:

const raygun = require('raygun');
const raygunClient = new raygun.Client().init({ apiKey: 'YOUR_API_KEY', filters: ['password', 'creditcard'] });

Tags

You can add tags to your error in the Send() function, as the tags parameter. For example:

client.send(new Error(), { tags: ['Custom Tag 1', 'Important Error'] });

Tags can also be set globally using setTags

client.setTags(['Tag1', 'Tag2']);

Timestamp

You can specify the exact time your error occurred in the Send() function with the timestamp parameter. Otherwise, the current time will be used.

This can be useful when combining Raygun together with other logger tools that provide a timestamp.

In milliseconds since epoch:

client.send(new Error(), { timestamp: 1718268992929 });

As Date object:

client.send(new Error(), { timestamp: new Date(2024, 5, 13, 10, 0, 0) });

Customers

You can attach user information to every Raygun Crash Report.

It will be transmitted with the error sent, and a count of affected customers will appear on the dashboard in the error group view. If you provide an email address, and the user has associated a Gravatar with it, their picture will be also displayed.

This package offers two different ways to do that:

  1. Provide the userInfo parameter in the send() method.
  2. Implement the user(request) method.

User information object

The following properties can be provided as user information:

  • identifier: Unique identifier for the user is the user identifier.
  • email: User's email address.
  • isAnonymous: Flag indicating if the user is anonymous or not.
  • firstName: User's first name (what you would use if you were emailing them - "Hi {{firstName}}, ...")
  • fullName: User's full name.
  • uuid: Device unique identifier. Useful if sending errors from a mobile device.

All properties are strings except isAnonymous, which is a boolean. As well, they are all optional. Any other properties will be discarded.

Example:

userInfo = {
    identifier: "123",
    email: "[email protected]",
    isAnonymous: false,
    firstName: "First name",
    fullName: "Fullname",
    uuid: "a25dfe58-8db3-496c-8768-375595139375",
}

For legacy support reasons, you can also provide the string identifier directly as the user information:

raygunClient.send(error, { userInfo: "123" });

userInfo parameter in send()

Provide the userInfo optional parameter in the send() method call:

client.send(new Error(), { userInfo });

This provided user information will take priority over the user(request) method.

Implement raygunClient.user(req)

You can set raygunClient.user to a function that returns the user name or email address of the currently logged in user.

An example, using the Passport.js middleware:

const raygunClient = new raygun.Client().init({apiKey: "YOUR_API_KEY"});

raygunClient.user = function (req) {
  if (req.user) {
    return {
      identifier: req.user.username,
      email: req.user.email,
      isAnonymous: false,
      fullName: req.user.fullName,
      firstName: req.user.firstName,
      uuid: req.user.deviceID
    };
  }
}

Param: req: the current request. Returns: The current user's identifier, or an object that describes the user.

Version tracking

Call setVersion(string) on a RaygunClient to set the version of the calling application. This is expected to be of the format x.x.x.x, where x is a positive integer. The version will be visible in the dashboard.

Inner Errors

Starting from 0.10.0 support for inner errors was added. Provide option innerErrorFieldName to specify a field or a function on the error object to use for retrieval of an inner error. Inner errors will be retrieved recursively until there is no more errors. Option innerErrorFieldName defaults to cause which is used in VError, therefore VError is supported out of the box.

Reporting uncaught exceptions

You can enable reporting uncaught exceptions to Raygun by setting the reportUncaughtExceptions option to true when initializing the client.

const {Raygun} = require('raygun');

const raygunClient = new Raygun.Client().init({
  apiKey: 'YOUR_API_KEY',
  reportUncaughtExceptions: true
});

This will cause any uncaught exceptions to be sent to Raygun prior to the process exiting.

Please note that this feature requires raygun>=0.13.0 and at least Node v12.17.0 or v13.7.0. This is due to the use of the uncaughtExceptionMonitor event, which allows monitoring uncaught exceptions without impacting standard process exit logic.

This feature is preferable to using the domains module for this purpose, as domains is both deprecated and carries a heavy performance overhead.

Changing the API endpoint

You can change the endpoint that error messages are sent to by specifying the host, port, and useSSL properties in the raygunClient.init() options hash. By default, host is api.raygun.com, port is 443, and useSSL is true.

onBeforeSend

Call Raygun.onBeforeSend(), passing in a function which takes up to 5 parameters (see the example below). This callback function will be called immediately before the payload is sent. The first parameter it gets will be the payload that is about to be sent. Thus from your function you can inspect the payload and decide whether or not to send it.

You can also pass this in as an option to init() like this: raygunClient.init({ onBeforeSend: function(payload) { return payload; } });

From the supplied function, you should return either the payload (intact or mutated as per your needs), or null.

If your function returns a truthy object, Raygun4Node will attempt to send it as supplied. Thus, you can mutate it as per your needs - preferably only the values if you wish to filter out data that is not taken care of by the filters. You can also of course return it as supplied.

If, after inspecting the payload, you wish to discard it and abort sending it to Raygun, simply return null.

For example:

const myBeforeSend = function (payload, exception, customData, request, tags) {
  console.log(payload); // Modify the payload here if necessary
  return payload; // Return null here instead of payload to abort the send
}

Raygun.onBeforeSend(myBeforeSend);

Breadcrumbs

Breadcrumbs can be sent to Raygun to provide additional information to look into and debug issues stemming from crash reports.

Breadcrumbs can be created in two ways.

Simple string:

Call client.addBreadcrumb(message), where message is just a string:

client.addBreadcrumb('test breadcrumb');

Using BreadcrumbMessage:

Create your own BreadcrumbMessage object and send more than just a message with client.addBreadcrumb(BreadcrumbMessage).

The structure of the type BreadcrumbMessage is as shown here:

BreadcrumbMessage: {
    level: "debug" | "info" | "warning" | "error";
    category: string;
    message: string;
    customData?: CustomData;
}

Sending Breadcrumbs

When an error message is sent to Raygun Crash Reporting, all the registered Breadcrumbs will be attached automatically.

After the error message has been sent, the registered Breadcrumbs list be cleared automatically.

Otherwise, you can also clear Breadcrumbs with client.clearBreadcrumbs().

Breadcrumbs and ExpressJS

Raygun4Node provides a custom ExpressJS middleware that helps to scope Breadcrumbs to a specific request. As well, this middleware will add a Breadcrumb with information about the performed request.

To set up, add the Raygun Breadcrumbs ExpressJS handler before configuring any endpoints.

// Add the Raygun Breadcrumb ExpressJS handler
app.use(raygunClient.expressHandlerBreadcrumbs);

// Setup the rest of the app, e.g.
app.use("/", routes);

This middleware can be used together with the provided ExpressJS error handler expressHandler. The order in which the middlewares are configured is important. expressHandlerBreadcrumbs must go first to scope breadcrumbs correctly.

app.use(raygunClient.expressHandlerBreadcrumbs);
app.use(raygunClient.expressHandler);

Batched error transport

You can enable a batched transport mode for the Raygun client by passing {batch: true} when initializing.

const raygunClient = new raygun.Client().init({
  apiKey: 'YOUR_API_KEY',
  batch: true,
  batchFrequency: 5000 // defaults to 1000ms (every second)
});

The batch transport mode will collect errors in a queue and process them asynchronously. Rather than sending each error one at a time as they occur, errors will be batched and sent at regular intervals.

If your application generates and reports large volumes of errors, especially in a short duration, the batch transport mode will perform better and operate with less network overhead.

You can control how often batches are processed and sent by providing a batchFrequency option, which is a number in milliseconds.

In a future version the batch transport will likely be enabled by default.

Offline caching

Raygun can cache errors thrown by your Node application when it's running in 'offline' mode. By default the offline cache is disabled. Raygun4Node doesn't detect network state change, that is up to the application using the library.

Raygun includes an on-disk cache provider out of the box, which required write permissions to the folder you wish to use. You cal also pass in your own cache storage.

Getting setup with the default offline provide

When creating your Raygun client you need to pass through a cache path

const raygunClient = new raygun.Client().init({
  apiKey: 'YOUR_API_KEY',
  isOffline: false,
  offlineStorageOptions: {
    cachePath: 'raygunCache/',
    cacheLimit: 1000 // defaults to 100 errors if you don't set this
  }
});
Changing online/offline state

The Raygun client allows you to set it's online state when your application is running.

To mark as offline

raygunClient.offline();

To mark as online

raygunClient.online();

When marking as online any cached errors will be forwarded to Raygun.

Custom cache provider

You're able to provide your own cache provider if you can't access to the disk. When creating your Raygun client, pass in the storage provider on the offlineStorage property

Example:

const sqlStorageProvider = new SQLStorageProvider();

const raygunClient = new raygun.Client().init({
  apiKey: 'YOUR_API_KEY',
  isOffline: false,
  offlineStorage: sqlStorageProvider,
  offlineStorageOptions: {
    table: 'RaygunCache'
  }
});

Required methods

  • init(offlineStorageOptions) - Called when Raygun is marked as offline. offlineStorageOptions is an object with properties specific to each offline provider
  • save(transportItem, callback) - Called when marked as offline
  • retrieve(callback) - Returns an array of cached item filenames/ids
  • send(callback) - Sends the backlog of errors to Raygun

See lib/raygun.offline.ts for an example.

We recommend that you limit the number of errors that you are caching so that you don't swamp the clients internet connection sending errors.

Custom error grouping

You can provide your own grouping key if you wish. We only recommend this you're having issues with errors not being grouped properly.

When initializing Raygun, pass through a groupingKey function.

const raygunClient = new raygun.Client().init({
  apiKey: 'YOUR_API_KEY',
  groupingKey: function(message, exception, customData, request, tags) {
    return "CUSTOMKEY";
  }
});

Custom error objects

By default Raygun4Node tries to convert unknown objects into a human readable string to help with grouping, this doesn't always make sense.

To disable it:

const raygunClient = new raygun.Client().init({
  apiKey: 'YOUR_API_KEY',
  useHumanStringForObject: false
});

If your custom error object inherits from Error as its parent prototype, this isn't necessary however and these will be sent correctly.

Report column numbers

By default Raygun4Node doesn't include column numbers in the stack trace. To include column numbers add the option reportColumnNumbers set to true to the configuration.

const raygunClient = new raygun.Client().init({
  apiKey: 'YOUR_API_KEY',
  reportColumnNumbers: true
});

Including column numbers can enable source mapping if you have minified or transpiled code in your stack traces.

Source maps

Raygun supports source mapping for Node.js stacktraces which include column numbers. To enable this feature you will need to upload your map files to the JavaScript Source Map Center and enable the processing of Node.js error stacktraces.

Using Private Source Maps with Node.js apps

Raygun supports source mapping for Node.js stacktraces which include column numbers. To enable this feature simply upload your map files as per the instructions on this page and enable the processing of Node.js errors with this setting in Raygun.

Node.js source maps

Managing files in the JavaScript Source Map Center Files in the JavaScript Source Map Center can be managed via a few API calls.

A GET request to https://app.raygun.com/jssymbols/[applicationIdentifier] will return a JSON object listing all files within the center. eg.

curl
  -X GET
  -u [email protected]:mypassword
  https://app.raygun.com/jssymbols/[applicationIdentifier]

Returns:

{
  "Count": totalNumberOfItems,
  "Items": [
    {
       "Url": "https://urlOfItem",
       "FileName": "fileName.js",
       "UploadedOn": "2016-01-01..."
    },
    ...
  ]
}

A DELETE request to https://app.raygun.com/jssymbols/[applicationIdentifier]/all will remove all files within the center. eg.

curl
  -X DELETE
  -u [email protected]:mypassword
  https://app.raygun.com/jssymbols/[applicationIdentifier]/all

A DELETE request to https://app.raygun.com/jssymbols/[applicationIdentifier] will remove files with the specified URLS from the center. eg.

curl
  -X DELETE
  -u [email protected]:mypassword
  -F "url=https://example.com/js/myjs.min.map"
  https://app.raygun.com/jssymbols/[applicationIdentifier]

All requests use the same authentication methods as the upload call (Basic Authentication and Token Authentication).

Known Issues

  • Node will show compilation warnings when using Raygun4Node in Webpack applications.
  • Although Breadcrumbs report the source filename, code line and function name, these are not processed using source maps like with stack traces.

Examples

View a screencast on creating an app with Node.js and Express.js, then hooking up the error handling and sending them at https://raygun.com/blog/2013/07/video-nodejs-error-handling-with-raygun/

Debug Logging

You can enable logging of debug information from the Raygun client by setting the environment variable DEBUG=raygun. The client will then log information about transporting and storing errors, including timing information.

Contributing

In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using "npm test".

Release History

View the changelog here

License

Copyright (c) 2016 Raygun Limited

Licensed under the MIT license.

raygun4node's People

Contributors

arjenvanderende avatar crystalqdm avatar danielcondemarin avatar dependabot[bot] avatar dwnz avatar ffflorian avatar fjakobs avatar jamiepenney avatar josephambe avatar lee-houghton avatar liath avatar loveandcoding avatar martin308 avatar miquelbeltran avatar mvhenten avatar sumitramanga avatar therealagentk avatar timjrobinson avatar ubermouse avatar widdershin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

raygun4node's Issues

No JSON.stringify protection when sending errors to raygun

in raygun.transport the module stringifies the payload before sending.

var data = JSON.stringify(options.message);

If the consumer provides any custom data here that cannot serialize, a new error is thrown and then neither one is reported. That user would have no idea they were losing error logs (unless they were watching the raw logs).

Cannot import Raygun class into typescript - makes it difficult to create a typed member variable to keep a ref to teh instantiated object

I'd like to write some code like this

import Raygun from "raygun";

class MyErrorReporter {
    private _raygun: Raygun;
    
    constructor() {
        this._raygun = new Raygun().init(...);
    }

    ...
}

but because the latest raygun.d.ts exports the following

declare class Raygun {
   ...
}
export declare const Client: typeof Raygun;
declare const _default: {
    Client: typeof Raygun;
};
export default _default;

I have to write this

import Raygun from "raygun";

class MyErrorReporter {
    private _raygun: any; // there seems to be no way to get Raygun.Client or Raygun to actually be recognised as a type
    
    constructor() {
        this._raygun = new Raygun.Client().init(...);
    }
    ...
}

This kind of makes typing pointless

... if the typescript exports were a bit simpler like this: -

declare namespace Raygun {
   export class Client { 
       ...
   }  
}
export = Raygun

it would be trivial

We're using typescript 3.8.3 as we cannot move to 3.9 just yet

nock should be marked as a dev dependency

Adding raygun as a dependency pulls in nock, lodash, et all because nock is marked as a dependency instead of a dev dependency in this package. Please move this in the package.json

Support providing own timestamp

In order to be better integrated with logging system, such as winston, it will be nice if raygun4node allows user to provide their own timestamp (from winston) when reporting errors

Getting "Error is too large to send to Raygun"

The package appears not to log errors with bigger strings. And the truncated chars aren't as helpful. Makes finding the cause of the error impossible. Is there any way to increase the maximum allowed bytes? Thanks for any info!

Raygun not getting any error properties

When I send an error to raygun, I lose all properties and meta data for that error. It looks like you do this intentionally in setErrorDetails() (L#63), but lots of libraries will append additional, essential information as error properties. This is a serious issue for us because it renders many of our serious postgres conflicts and errors useless.

console.log(err);

{ [error: duplicate key value violates unique constraint "short_urls_pkey"]
  name: 'error',
  length: 198,
  severity: 'ERROR',
  code: '23505',
  detail: 'Key (id)=(THE_SAME_ID) already exists.',
  hint: undefined,
  position: undefined,
  internalPosition: undefined,
  internalQuery: undefined,
  where: undefined,
  file: 'nbtinsert.c',
  line: '406',
  routine: '_bt_check_unique' }

raygunClient.send(error, //...

From "Raw Data" (different error, but sent through the same formatter with the same properties):
screen shot 2015-04-17 at 12 16 18 pm

raygun useSSL in options hash not working

Hi,

Looks like useSSL property always evaluates to truthy.

Ln 25 in raygun.js:

_useSSL = options.useSSL || true;

No matter what value is passed on the options useSSL will always be truthy.

Raygun Generating Invalid URL on Client.send() Call

I am using Raygun on a frontend app, built with Vue, hosted off of a Express server. I traced this through my browser.

httpOptions is set as such:

var httpOptions = {
      host: options.host || API_HOST,
      port: options.port || 443,
      path: fullPath,
      ...

I am not passing a host or port, so I get stuck with
host = api.raygun.io
port = 443

We eventually get to:

var request = httpLib.request(httpOptions, cb);

which makes a call after validating params

https.get = function (params, cb) {
  params = validateParams(params)
  return http.get.call(this, params, cb)
}

...and we eventually get to this point:

// This may be a relative url. The browser should always be able to interpret it correctly.
opts.url = (host ? (protocol + '//' + host) : '') + (port ? ':' + port : '') + path

At this point,
host = api.raygun.io
protocol = https:
port = 443
path = https://api.raygun.io:443/entries

So, the opts.url = ... call resolves to:

https://api.raygun.io:443https://api.raygun.io:443/entries

which later fails, with message:

Raygun: error Failed to execute 'fetch' on 'Window': Failed to parse URL from https://api.raygun.io:443https://api.raygun.io:443/entries occurred while attempting to send error with message: [object Object]

I was not using the Raygun Express Handler because I wanted more fine-grain control (i.e., maybe call succeeded, but was empty, or some Javascript failed? I want to log and be alerted of those kinds of things). Also, I tried it anyway, and nothing happened when I generated 404s.

Error: is not a valid URL.

Raygun failed then I try to send the error.

Code:

const raygun = require('raygun')

export default {
  install(Vue, { id = null }) {
    if (!id) {
      throw new Error('raygun id is missing')
    }

    Vue.prototype.$raygun = new raygun.Client().init({
      apiKey: id
    })
  }
}

this.$raygun.send(new Error('error de test'), { mykey: 'beta' })

Error:
Raygun: error Window.fetch: https://api.raygun.io:443https://api.raygun.io:443/entries is not a valid URL. occurred while attempting to send error with message: [object Object

Can we pass custom data in the middleware error reporter?

We can pass custom data in the client.send method, but the middleware does not allow this. Would be nice to set custom data when initializing the client (similar to the way client.setVersion keeps it) and then add these settings to the middleware exception.

expressHandler does not catch error

Hi,

i tried to catch errors by expressHandler. But it did not work in any case.

This is my implementation.

app.use(function(err, req, res, next) {
   res.status(err.status || 500);
   
   var query = req.url.split('/');
   if(query[1] && query[1] == 'api')
	/* error page for api */
	res.json({
	    "status": 401,
	    "message": err.message
	});
   else
	res.render('error', {
	     message: err.message,
            error: {}
	});
});

var port = process.env.PORT || config.get('port');
var server, type;
if(process.env.NODE_ENV == 'production') {
	server = http.createServer(app);
	type = 'http';
}
else {
	server = https.createServer(credentials,app);
	type = 'https';
}

var io = socketIo(server, {transports: ['polling'], 'polling duration': 10});

app.use(raygunClient.expressHandler);

server.listen(port);

log.info('***** exp listening on port: ' + port +' type: '+type);

module.exports = app;

Sending custom data

You could include an example of how to send custom data. I figured it out seeing the code of the module, but there are no examples on the README or on the web and it would be useful for other users.

Thank you for this nice service!

sendSync for handling errors before a crash

To handle sending errors to raygun before an application crashes I suggest adding a sendSync method to the raygun client. This will allow the code to be wrapped in a domain, send the error to raygun and exit preventing any additional code to be run. For example, an async loop where an error you want to prevent any further execution.

async.each(images, function(image, next) {
  optimiseImage(image, function (err) {
    if (err) {
      raygunClient.sendSync(err);
      process.exit(1);
    }

    next();
  }
}, callback);

The code above will cause the error to be sent and prevent all other async optimiseImage calls to be blocked. https://github.com/ForbesLindesay/sync-request could be used to create this function.

Let me know your thoughts.

expressHandler does not work

It doesn't send any errors.

I don't understand this Express error handling thing, how does Express now that some function I register with .use is an error handler? It could be a normal request handler, couldn't it?

Setup code formatting (prettier)

Please describe your new feature request

  • Ensure code is properly formatted using prettier for JavaScript.

Describe the solution you'd like

  • Format with npm run prettier.
  • Check in GitHub actions if the format is correct, fail if formatting issues found.

Describe alternatives you've considered

  • Not sure if there are better formatting options. Prettier was already setup in the project.

Additional context

https://prettier.io/

Is this still maintained?

I'm trying to evaluate error reporting SaaS offerings and it doesn't appear that this project gets much attention from Raygun.

setTags property does not exist on Client type

When using the setTags property in a Typescript file, I receive the following type error:

Property 'setTags' does not exist on type 'Client'.ts(2339)

Here is my code:

import raygun from 'raygun'

type UserSettings = {
  identifier: string,
  isAnonymous: boolean
}

const apiKey: string = process.env.RAYGUN_API_KEY || ''
const client: Client = new raygun.Client().init({ apiKey })

const raygunServerWrapper = (tags: string[], userSettings: UserSettings) => {
  client.setVersion(process.env.APP_VERSION || '')
  client.user = () => ({
    ...userSettings
  })

  if (tags) {
    client.setTags(tags)
  }

  return client
}

export default raygunServerWrapper

When checking the Client type file, it looks like setTags is missing. Not sure if this is by design or a small bug?

Screenshot 2021-03-29 at 11 42 22

I'm happy to make a PR to add it in if required.

`.send()` does not with without async/await.

Documentation leads you to believe that the .send() method can simply be called and data will be sent to your dashboard.

Using 0.13.2, this does not seem to be the case. I only get errors in my dashboard if I await the .send() method.

Are the docs out of date? Am I doing something wrong?

Here is my basic code, ran inside a Vitest test

    const foo = new Raygun.Client().init(
      {
        apiKey: '<MY_API_KEY>',
        reportColumnNumbers: true,
        reportUncaughtExceptions: true,
        batch: false,
        tags: ['vitest'],
      },
    );

    foo.send('test', {}, (res) => {
      console.log(res);
    });

Fix warning "module.parent.require is not supported by webpack"

I have a repro of this issue at https://github.com/tansongyang/raygun-webpack-issue-repro.

Run npm run build in the console. Here's the output:

> next build

   ▲ Next.js 14.1.0

   Creating an optimized production build ...
 ⚠ Compiled with warnings

./node_modules/raygun/build/raygun.js
module.parent.require is not supported by webpack.

Import trace for requested module:
./node_modules/raygun/build/raygun.js
./app/raygun.ts
./app/page.tsx

./node_modules/raygun/build/raygun.js
Module not found: Can't resolve 'raygun-apm/lib/src/crash_reporting' in '/Users/frank/Code/raygun-webpack-issue-repro/node_modules/raygun/build'

Import trace for requested module:
./node_modules/raygun/build/raygun.js
./app/raygun.ts
./app/page.tsx

Source appears to be here: https://github.com/MindscapeHQ/raygun4node/blob/v0.13.0/lib/raygun.ts#L51

Not sure what the fix is, but if I navigate to the file in VS Code, I get a warning that module.parent is deprecated:

image

Memory Spikes when we use Raygun

We have a node app that we wanted to put onto Raygun, but every time we hook it up, our nodejs processes chew up all available RAM and our servers start to swap.

Are there any known issues of this? Is there any way we can pinpoint the issue further?

Request handler can causes 404 regardless of error

We had a problem that took some time to track down and a lot of frustration.
We are using express in azure functions.
When an error occurred, it seemed like Azure was turning it into a 404 with an HTML response every time and swallowing the detail.

Eventually we found that by moving the raygun error handler to the very end of our middleware pipeline, the problem went away.

I think the culprit may be in this line

next();

Where the end of the handler is next() instead of next(err).

If it was the latter, then the error could be captured separately or bubbled up to (in our case Azure functions logging). I don't think raygun should be swallowing the error.

eslint: remove ignored rules and fix issues

Please describe your new feature request

In the PR #156 we setup eslint to be the linter platform for the project.

However, the configuration file contains several rules set to "off" in order to pass the lint checks without changing the project.

We should eventually enable them and cleanup the code as well.

Describe the solution you'd like

Remove the rules' definition from eslint.config.mjs:

  • @typescript-eslint/no-explicit-any
  • @typescript-eslint/no-this-alias
  • @typescript-eslint/no-unused-vars
  • @typescript-eslint/no-var-requires
  • no-undef
  • no-unreachable
  • no-useless-catch

In case there are rules that should be there, document why in the eslint.config.mjs file.

Describe alternatives you've considered

We should not leave those rules there if we plan to continue development with the plugin, as they prevent us from detecting possible issues earlier on.

Additional context

There are around ~120 warnings when removing the rules.

Incorrect docs

The setup docs suggest that the .send() method is synchronous because the example doesn't provide a callback, but in fact it's async (as it should be). If there's a slow connection then the example code will exit before the error is sent. Also, the exit code in the example code is wrong. This should be:

d.on('error', function(err){
  setTimeout(function() {
    process.exit(1);
  }, 5000).unref();

  raygunClient.send(err, null, function() {
    process.exit(1); // use the correct exit code
  });
});

Also, I think that the interface for the RaygunClient#user method is unexpected. Here's my working implementation:

    raygunClient.user = function (req) {
      return () => {
        if (req && req.auth) {
          return req.auth.serialize();
        }
      };
    };

I think that returning a function is unnecessary and I should be able to just return the object hash:

    raygunClient.user = function (req) {
      if (req && req.auth) {
        return req.auth.serialize();
      }
    };

Automatically capture uncaught exceptions and rejections

Currently, capturing and sending uncaught exceptions and rejections needs to be done manually. Having a helper function that attaches the event handlers would greatly improve the developer experience, and remove the need to use the deprecated Domain API.

Scope

  • Add a helper function to allow uncaught exceptions and rejections to be sent to Raygun automatically (e.g. raygunClient.reportUncaughtExceptions())
    • Use the uncaughtExceptionMonitor with a fallback for older versions of Node (Added in: v13.7.0, v12.17.0)
    • Add support for unhandled rejections
  • The Domain API is deprecated, so we should remove/replace the using-domains sample app.

utf8 characters causing 400 response from raygun

The send function in raygun.transport.js has the following:

  var data = JSON.stringify(options.message);
  ...
    headers: {
        'Content-Type': 'application/json',
        'Content-Length': data.length,

The Content-Length header should be length in bytes, not in characters. One way to fix it is to replace the first line above with:

var data = new Buffer(JSON.stringify(options.message), "utf8");

Add ability to opt out from sending environment details

When using raygun4node for client applications build with NW.js or Electron, the environment details also contain the users machine name. Would be nice to have the ability to prevent raygun from send this information.

Node process does not exit when batch mode is used

Hello,

Im migrating from sentry to raygun our CLI tool and it goes well up until the end.
Events arrive in GUI, nothing errors, but process is not exiting as it was before.

Im not sure if sentry was too eager to quit the process, but i decided to ask experts for help.

At the end of the day im replacing Sentry.captureMessage(message); with raygunClient.send(message); and this happens (currently) always when something has ended and process can be terminated (think process.exit(x)).

Now my question is: Should i manually exit process with error code that i determine, or there is some better way of dealing with it in raygun4node?

Update nock from version 8.2.2 to 9.6.1

there is a security issue reported on lodash version 4.9.0.
Nock version 8.2.2 that is used by raygun is build on version 4.9.0.
To fix this issue an update to nock to version 9.6.1 is recommended. this version uses lodash 4.17.10.

Can't pass user to error.

Hi,

I would like to set a user in every event when there are send. I build my reporter function like that:

const raygunClient = new raygun.Client().init({
  apiKey: process.env.ERROR_REPORTER_KEY!,
  filters: ['password'],
  useHumanStringForObject: false,
});
raygunClient.user = function (req) {
  console.log('>>>>>>>>>>>');
  const request = (req as unknown) as IRequest;
  if (request.auth?.credentials?.currentUser) {
    return {
      identifier: request.auth.credentials.currentUser.id,
      email: request.auth.credentials.currentUser.email,
      username: request.auth.credentials.currentUser.username,
    };
  }
  return {};
};

When I execute raygunClient.send(error) the raygunClient.user is never executed. What am I doing wrong?

Add browserify support

It would be awesome if raygun4node could be browserified so that it worked in the browser too. A lot of my javascript is shared between the server and the browser, making it difficult to toggle between using ragun4js and raygun4node.

No breadcrumb support?

We are using raygun4node inside AWS Lambda functions. I would love to use the breadcrumbs feature of Raygun. It's in the Ruby library but I see it nowhere in here. Am I missing something? I can't use raygun4js because it can't run inside node.

Development and Test environments

Hey guys, nice work on the module.

It'd be awesome if I could mock the raygunTransport on the client: Use case, it'd be awesome if I could log and notify through node-notifier in a development environment, and perhaps be stubbed out in a test environment.

Cheers 😄

Can't Handle Symbol() Attribute On Error Object

We attach Symbol() type attributes to our known error conditions in our Express application. When Raygun tries to serialize these attributes the following error is raised:

TypeError: Cannot convert a Symbol value to a string
    at toHumanString (/Users/myusername/Projects/myProjectName/node_modules/object-to-human-string/lib/index.js:29:63)
    at RaygunMessageBuilder.setErrorDetails (/Users/myusername/Projects/myProjectName/node_modules/raygun/lib/raygun.messageBuilder.js:54:15)
    at Raygun.raygun.send (/Users/myusername/Projects/myProjectName/node_modules/raygun/lib/raygun.js:98:14)
    at Raygun.raygun.expressHandler (/Users/myusername/Projects/myProjectName/node_modules/raygun/lib/raygun.js:144:16)
    at WebFrameworkShim.applySegment (/Users/myusername/Projects/myProjectName/node_modules/newrelic/lib/shim/shim.js:1332:17)
    at _applyRecorderSegment (/Users/myusername/Projects/myProjectName/node_modules/newrelic/lib/shim/shim.js:949:20)
    at _doRecord (/Users/myusername/Projects/myProjectName/node_modules/newrelic/lib/shim/shim.js:928:17)
    at /Users/myusername/Projects/myProjectName/node_modules/newrelic/lib/shim/shim.js:913:24
    at Layer.handle_error (/Users/myusername/Projects/myProjectName/node_modules/express/lib/router/layer.js:71:5)
    at trim_prefix (/Users/myusername/Projects/myProjectName/node_modules/express/lib/router/index.js:315:13)

It appears that object-to-human-string tries to concatenate strings using the + operator, which specifically throws the above type error. It seems to me that attaching Symbol() metadata to error objects should not cause an error to be thrown.

Thanks for a great tool!

Dated library

Kia ora team, we are hoping to switch over from Sentry to Raygun, but are bumping into the fact that this Node library seems to be very dated and not really up to speed with modern best practices. The guide for using this library that the Sentry app links to has been written in 2013, and the code examples show it.

Are there any plans to modernise this library in the near future?

It will be very hard for us to rewrite our current Sentry error handling boilerplate code to migrate this to the Raygun library, which still uses callbacks, and it seems we will lose a lot of vital functionality and ease of implementation in the process.

We really would like to migrate, but this seems to be a show stopper 😢

SDK: Document public methods

Please describe your new feature request

Currently, public methods on raygun.ts and other parts of the SDK are not documented.

This documentation exists in the repository README.md but not in code.

Describe the solution you'd like

My idea would be to use https://tsdoc.org/ format to add documentation to all these methods.

We can also use the packages from that site to generate documentation pages in the future if we want so.

We can also install https://www.npmjs.com/package/eslint-plugin-tsdoc to ensure that documentation comments follow the right format.

Describe alternatives you've considered

TBD

Additional context

TBD

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.