Coder Social home page Coder Social logo

mindscapehq / raygun4js Goto Github PK

View Code? Open in Web Editor NEW
143.0 29.0 60.0 5.2 MB

JavaScript provider for Raygun

Home Page: https://raygun.com

License: Other

JavaScript 98.20% CSS 0.68% HTML 1.12%
raygun breadcrumbs error-handler unhandled-errors real-user-monitoring stack-traces sourcemaps user-tracking javascript raygun4js

raygun4js's Introduction

Raygun4js

Raygun.com provider for client-side JavaScript

Getting Started

Asynchronous method - Highly recommended

Step 1

No installation via a package manager is required. Just add the following snippet to the beginning of the <head> tag within your markup. Please include this snippet before any other <script> tag references are made to ensure that Raygun has the best chance to capture all error events on the page.

<script type="text/javascript">
    !function(a,b,c,d,e,f,g,h){a.RaygunObject=e,a[e]=a[e]||function(){
    (a[e].o=a[e].o||[]).push(arguments)},f=b.createElement(c),g=b.getElementsByTagName(c)[0],
    f.async=1,f.src=d,g.parentNode.insertBefore(f,g),h=a.onerror,a.onerror=function(b,c,d,f,g){
    h&&h(b,c,d,f,g),g||(g=new Error(b)),a[e].q=a[e].q||[],a[e].q.push({
    e:g})}}(window,document,"script","//cdn.raygun.io/raygun4js/raygun.min.js","rg4js");
</script>

The above snippet will fetch the Raygun4JS script from our CDN asynchronously, so it doesn't block other scripts from being loaded. It will also catch errors that are thrown while the page is loading, and send them when the script is ready.

Note: If you encounter a situation where no events are appearing within Raygun, you may need to hard code the URL protocol so that the CDN matches your hosting environment. This could look like one of the following -

  • https://cdn.raygun.io/raygun4js/raygun.min.js
  • http://cdn.raygun.io/raygun4js/raygun.min.js

This will be in replacement of //cdn.raygun.io/raygun4js/raygun.min.js.

Via package manager installation

For installations and usage via a package manager, refer to the Synchronous methods section of this document.

Step 2

Add the following lines to your JS site code and paste in your API key (from your Raygun Application Settings), to set up the provider to automatically send errors to your Raygun app:

<script type="text/javascript">
    rg4js('apiKey', 'paste_your_api_key_here');
    rg4js('enableCrashReporting', true);
</script>

This will configure the provider to send to your Raygun app, and to automatically send all unhandled errors.

That's it for the basic setup! See Usage below for more info on how to send errors.

Snippet without page load error handler

If you do not want errors to be caught while the page is loading, use this snippet here.

Synchronous methods

Note that using these methods will not catch errors thrown while the page is loading. The script needs to be referenced before your other site/app scripts and will block the page load while it is being downloaded/parsed/executed.

This will also disrupt RUM timings, making them erroneous. For RUM, it is especially important that the async snippet method above is used, instead of one of the following.

With Bower

Run bower install raygun4js

With NPM

npm install raygun4js --save

This lets you require the library with tools such as Webpack or Browserify.

From NuGet

Visual Studio users can get it by opening the Package Manager Console and typing Install-Package raygun4js

React Native/as a UMD module

React Native and other bundled app frameworks that use packaging/module loading libraries can use Raygun4JS as a UMD module:

// Install the library

npm install raygun4js --save

// In a central module, reference and install the library

import rg4js from 'raygun4js'; // Import the library with this syntax
var rg4js = require('raygun4js'); // Or this syntax

rg4js('enableCrashReporting', true);
rg4js('apiKey', 'paste_your_api_key_here');
// Any other config options you want such as rg4js('setUser', ...) [see below]
rg4js('boot'); // For React Native only: add this after all other config options have been called

All unhandled errors will then be sent to Raygun. You can also require('raygun4js') in any other modules and use the rest of the V2 API below - including rg4js('send', error) for manual error sending.

If you use this approach, we appreciate your feedback as this is a new feature for the library.

Manual download

Download the production version or the development version. You can also download a version without the jQuery hooks if you are not using jQuery or you wish to provide your own hooks. Get this as a production version or development version.

Usage

If you are using the CDN, be sure to call these usage methods after the installation.

To send errors manually:

try {
  throw new Error('oops');
}
catch(e) {
  rg4js('send', e);
}

In order to get stack traces, you need to wrap your code in a try/catch block like above. Otherwise the error hits window.onerror handler and may only contain the error message, line number, and column number.

You also need to throw errors with throw new Error('foo') instead of throw 'foo'.

To automatically catch and send unhandled errors, you can attach the automatic window.onerror handler callback:

rg4js('enableCrashReporting', true);

If you need to detach it (this will disable automatic unhandled error sending):

rg4js('detach');

Documentation

Initialization Options

To configure the provider, call this and pass in an options object:

rg4js('options', {
  // Add some or all of the options below
});

The second parameter should contain one or more of these keys and a value to customize the behavior:

ignoreAjaxAbort - User-aborted Ajax calls result in errors - if this option is true, these will not be sent.

ignoreAjaxError - Ajax requests that return error codes will not be sent as errors to Raygun if this options is true.

debugMode - Raygun4JS will log to the console when sending errors.

wrapAsynchronousCallbacks - if set to false, async callback functions triggered by setTimeout/setInterval will not be wrapped when attach() is called. Defaults to true

ignore3rdPartyErrors - ignores any errors that have no stack trace information. This will discard any errors that occur completely within 3rd party scripts - if code loaded from the current domain called the 3rd party function, it will have at least one stack line and will still be sent. Errors that occur in browser extensions or that have been triggered by bots/crawlers that appear to come from your website will also be ignored. Note: IE 9 and below have no stacktrace information and errors will be discarded with this enabled.

excludedHostnames - Prevents errors from being sent from certain hostnames (domains) by providing an array of strings or RegExp objects (for partial matches). Each should match the hostname or TLD that you want to exclude. Note that protocols are not tested.

excludedUserAgents - Prevents errors from being sent from certain user agents by providing an array of strings. This is very helpful to exclude errors reported by certain browsers or test automation with CasperJS, PhantomJS or any other testing utility that sends a custom user agent. If a part of the client's navigator.userAgent matches one of the given strings in the array, then the client will be excluded from error reporting.

disableErrorTracking - Stops all errors from being sent to Raygun. This includes errors automatically picked up by global error handlers as well as errors manually sent.

disablePulse - Stops real user monitoring events from being sent.

apiEndpoint - A string URI containing the protocol, domain and port (optional) where all payloads will be sent to. This can be used to proxy payloads to the Raygun API through your own server. When not set this defaults internally to the Raygun API, and for most usages you won't need to set this.

clientIp - A string containing the client's IP address. RUM requests will be associated to this IP address when set. Particularly useful when proxying payloads to the Raygun API using the apiEndpoint option and maintaining RUM's geographic lookup feature.

Note: navigator.sendBeacon is used to send RUM payloads when a page is unloading. As such the clientIp feature will not associate this last payload.

pulseMaxVirtualPageDuration - The maximum time a virtual page can be considered viewed, in milliseconds (defaults to 30 minutes).

pulseIgnoreUrlCasing - Ignore URL casing when sending data to RUM.

captureUnhandledRejections - Automatically catch send errors relating to unhandled promise rejections. See MDN for browser support.

setCookieAsSecure - If the cookies are being used (only used on browsers which don't support localStorage or sessionStorage) then they will be created using the ; secure flag and thus cookies only work on HTTPS.

captureMissingRequests - RUM uses the window.performance API to track XHR timing information and (depending on the browser) not all non-2XX XHR timings are recorded by this API. This option enables the tracking of these missing XHR's calls by tracking the difference between send & success XHR handlers. This is not enabled by default due these timings being as accurate as the performance API.

automaticPerformanceCustomTimings - When enabled Raygun4JS will track each window.performance.measure call as a custom timing entry. This enables developers to use a more native API for tracking performance timings. More information about performance.measure can be found on MDN.

trackCoreWebVitals - When enabled, Raygun4JS will automatically track and report Core Web Vitals. This is enabled by default.

trackViewportDimensions - When enabled, Raygun4JS will send the browser's viewport dimensions with each RUM session payload. This is enabled by default.

An example raygun4js configuration:

rg4js('options', {
  ignoreAjaxAbort: true,
  ignoreAjaxError: true,
  debugMode: true,
  ignore3rdPartyErrors: false,
  wrapAsynchronousCallbacks: true,
  excludedHostnames: ['\.local'],
  excludedUserAgents: ['Mosaic'],
  disableErrorTracking: false,
  disablePulse: false,
  pulseMaxVirtualPageDuration: 1800000,
  pulseIgnoreUrlCasing: false,
  captureUnhandledRejections: true,
  setCookieAsSecure: false,
  captureMissingRequests: false,
  automaticPerformanceCustomTimings: false
});

RUM API

Tracking Single Page Application (SPA) events

Raygun RUM supports client-side SPAs through the trackEvent function:

rg4js('trackEvent', {
    type: 'pageView',
    path: '/' + window.location.pathname // Or perhaps window.location.hash
});

When a route or view change is triggered in your SPA, this function should be called with type being pageView and path set to a string representing the new view or route. RUM will collect up all timing information that is available and send it to the dashboard. These are then viewable as 'virtual pages'.

The following are a couple of configuration examples that you can use or adapt for your client-side view library/framework. Naturally, if you are using a more full-featured routing system, you should trigger a pageView inside there when the route changes.

jQuery

$(window).hashchange(function() {
  rg4js('trackEvent', {
      type: 'pageView',
      path: '/' + location.hash
  });
});

Angular

export class AppModule implements OnInit {
  constructor(private router: Router) {}
  ngOnInit() {
    this.router.events.subscribe(event => {
      // Track page views when the NavigationEnd event occurs
      if (event instanceof NavigationEnd) {
        rg4js('trackEvent', {
          type: 'pageView',
          path: event.url
        });
      }
    });
  }
}

Tracking custom timings

Custom timings allow you to track custom performance measurements across your website and application. For example, you can track the time it takes for a video to play after the user clicks a button or the time for a component to mount.

  rg4js('trackEvent', {
      type: 'customTiming',
      name: 'firstInput',
      duration: 1200,
  });

You can read more about custom timings on its documentation page here.

Legacy custom timings API

Note: This API has since been deprecated and will be removed in a future version of the provider. We recommend developers upgrade to using the latest version which is both easier to setup and works for single page applications.

rg4js('options', {
  pulseCustomLoadTimeEnabled: true
  // Plus any other configuration options
});

rg4js('trackEvent', {
  type: 'customTimings',
  timings: {
    custom1: 10,
    custom2: 20,
    custom3: 30,
    custom4: 40,
    custom5: 50,
    custom6: 60,
    custom7: 70,
    custom8: 80,
    custom9: 90,
    custom10: 10,
  }
});

Breadcrumbs API

Breadcrumbs initialization commands

These should be called if needed during your page's lifecycle:

rg4js('one-of-the-below-options')

rg4js('disableAutoBreadcrumbs') - Disable all the automatic breadcrumb integrations (clicks, requests, console logs and navigation events). This has an inverse enableAutoBreadcrumbs which is the default

rg4js('disableAutoBreadcrumbsConsole') - Disable just automatic breadcrumb creation from console messages

rg4js('disableAutoBreadcrumbsNavigation') - Disable just automatic breadcrumb creation from navigation events

rg4js('disableAutoBreadcrumbsClicks') - Disable just automatic breadcrumb creation from element clicks

rg4js('disableAutoBreadcrumbsXHR') - Disable just automatic breadcrumb creation XMLHttpRequests

All of the above have an inverse enableAutoBreadcrumbs<type> which is the default

rg4js('setAutoBreadcrumbsXHRIgnoredHosts', []) - This can be set to an array of hostnames to not create a breadcrumb for requests/responses to. The values inside the array can either be strings that an indexOf check against the host is made, or regexes which is matched against the host.

rg4js('setBreadcrumbLevel', 'warning') - Set the minimum level of breadcrumb to record. This works the same as log levels, you may set it to debug, info, warning and error and it will only keep breadcrumbs with a level equal or above what this is set to. Valid values are one of ['debug', 'info', 'warning', 'error']. Defaults to info.

rg4js('logContentsOfXhrCalls', true) - If set to true will include the body contents of XHR request and responses in Breadcrumb metadata, defaults to false

Logging a breadcrumb

Breadcrumbs can be manually logged via rg4js('recordBreadcrumb', ...)

There are two argument formats

rg4js('recordBreadcrumb', 'breadcrumb-message', {object: 'that will be attached to the breadcrumb custom data'})

This is the quickest way to log basic breadcrumbs, requiring only a message and optionally an object to attach some metadata

If you wish to have further control of the breadcrumb and configure the level (debug, info, warning, error) or set the class/method the breadcrumb was logged from

rg4js('recordBreadcrumb', {message: 'breadcrumb-message', metadata: {goes: 'here'}, level: 'info', location: 'class:method'})

You may use the above argument format

Unhandled Promise Rejection

As of 2.10.0 Raygun4JS captures unhandled promise rejections automatically. Browser support for this feature is currently spotty and you can view browser support at MDN.

To disable this functionality by default you can set the captureUnhandledRejections key in the [Initialization Options](Initialization Options).

If you are using a Promise library which contains a global hook for capturing errors you can manually send errors inside of that global hook.

RSVP.js example:

RSVP.on('error', function(reason) {
    rg4js('send', {
      error: reason
    });
});

Promise libraries which report unhandled rejections to a global unhandledrejection DOM event, like Bluebird, are automatically picked up when you have captureUnhandledRejections set.

Dynamic code splitting / loading with Webpack

If you are using Webpack to perform dynamic code splitting / loading and you are loading your bundles off of a separate domain (ie a cdn) you will need to ensure that you have set the output.crossOriginLoading configuration option to anonymous to have Raygun4JS pick up your errors without CORS issues. Without this setting the dynamic script tags will be created without a crossorigin attribute and be treated by the browser as private information in Raygun4JS's execution context.

Example Webpack config

module.exports = {
  // Other webpack config options
  output: {
    // Other output options
    crossOriginLoading: 'anonymous'
  },
};

Payload size conservation

To help ensure your payload does not become too large only the most recent 32 breadcrumbs are kept, as well as limiting the size of recorded network request/response texts to 500 characters.

Multiple Raygun objects on a single page

You can have multiple Raygun objects in global scope. This lets you set them up with different API keys for instance, and allow you to send different errors to more than one application in the Raygun web app.

To create a new Raygun object and use it call:

var secondRaygun = rg4js('getRaygunInstance').constructNewRaygun();
secondRaygun.init('apikey');
secondRaygun.send(...);

Only one Raygun object can be attached as the window.onerror handler at one time, as onerror can only be bound to one function at once. Whichever Raygun object had attach() called on it last will handle the unhandle errors for the page. Note that you should use the V1 API to send using the second Raygun object, and it should be created and called once the page is loaded (for instance in an onload callback).

NoConflict mode

If you already have an variable called Raygun attached to window, you can prevent the provider from overwriting this by enabling NoConflict mode:

rg4js('noConflict', true);

To then get an instance of the Raygun object when using V2, call this once the page is loaded:

var raygun = rg4js('getRaygunInstance');

You can also provide a callback with 'getRaygunInstance' and it will be called after raygun4js has loaded with the Raygun instance as an argument:

rg4js('getRaygunInstance', raygun => {
});

Callback Events

onBeforeSend

rg4js('onBeforeSend', function (payload) {
  return payload;
});

Call this function and pass in a function which takes one parameter (see the example below). This callback function will be called immediately before the payload is sent. The one 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.

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

If your function returns a truthy object, Raygun4JS 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 filterSensitiveData(). You can also of course return it as supplied.

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

By example:

var myBeforeSend = function (payload) {
  console.log(payload); // Modify the payload here if necessary
  return payload; // Return false here to abort the send
}

rg4js('onBeforeSend', myBeforeSend);

onBeforeSendRUM

rg4js('onBeforeSendRUM', function (payload) {
  return payload;
});

Call this function and pass in a function which takes one parameter (see the example below). This callback function will be called immediately before any Real User Monitoring events are sent. The one 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.

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

If your function returns a truthy object, Raygun4JS will attempt to send it as supplied. Thus, you can mutate it as per your needs. You can also of course return it as supplied.

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

By example:

var myBeforeSend = function (payload) {
  console.log(payload); // Modify the payload here if necessary
  return payload; // Return false here to abort the send
}

rg4js('onBeforeSendRUM', myBeforeSend);

onAfterSend

rg4js('onAfterSend', function (xhrResponse) {
  // Inspect the XHR response here
});

Call this function and pass in a function which takes one parameter (see the example below). This callback function will be immediately called after the XHR request for a Crash Reporting or RUM event responds successfully, or errors out (its onerror was called). You can inspect the one parameter, which is the XHR object containing the HTTP response data.

onBeforeXHR

rg4js('onBeforeXHR', function (xhr) {
  // Mutate the xhr parameter as per your needs
});

Call this function when you want control over the XmlHttpRequest object that is used to send error payloads to the API. Pass in a callback that receives one parameter (which is the XHR object). Your callback will be called after the XHR object is opened, immediately before it is sent.

For instance, you can use this to add custom HTTP headers.

Note: navigator.sendBeacon is used to send RUM payloads when a page is unloading. In these cases the onBeforeXHR method will not be executed as there is no XHR to reference and no additional headers can be attached.

Custom error grouping

You can control custom grouping for error instances by passing in a callback. This will override the automatic grouping and be used to group error instances together. Errors with the same key will be placed within the same error group. The callback's signature should take in the error payload, stackTrace and options and return a string, ideally 64 characters or less. If the callback returns null or or a non-string the error will be grouped using Raygun's server side grouping logic (this can be useful if you only wish to use custom grouping for a subset of your errors).

var groupingKeyCallback = function (payload, stackTrace, options) {
  // Inspect the above parameters and return a hash derived from the properties you want

  return payload.Details.Error.Message; // Naive message-based grouping only
};

rg4js('groupingKey', groupingKeyCallback);

Sending custom data

On initialization:

Custom data variables (objects, arrays etc) can be added by calling the withCustomData function on the Raygun object:

rg4js('withCustomData', { foo: 'bar' });

During a send:

You can also pass custom data with manual send calls, with an options object. This lets you add variables that are in scope or global when handled in catch blocks. For example:

rg4js('send', {
  error: e,
  customData: [{ foo: 'bar' }]
});

Providing custom data with a callback

To send the state of variables at the time an error occurs, you can pass withCustomData a callback function. This needs to return an object. By example:

var desiredNum = 1;

function getMyData() {
 return { num: desiredNum };
}

rg4js('withCustomData', getMyData);

getMyData will be called when Raygun4JS is about to send an error, which will construct the custom data. This will be merged with any custom data provided on a Raygun.send() call.

Adding tags

The Raygun dashboard can also display tags for errors. These are arrays of strings or Numbers. This is done similar to the above custom data, like so:

On initialization:

rg4js('withTags', ['tag1', 'tag2']);

During a send:

Pass tags in using an options object:

rg4js('send', {
  error: e,
  tags: ['tag3'];
});

Adding tags with a callback function

As above for custom data, withTags can now also accept a callback function. This will be called when the provider is about to send, to construct the tags. The function you pass to withTags should return an array (ideally of strings/Numbers/Dates).

Customers

By default Raygun4JS assigns a unique anonymous ID for the current user. This is stored in local storage and will default back to using a cookie if local storage is not supported. You can remove the ID from storage by calling:

rg4js('getRaygunInstance').resetAnonymousUser();

Disabling anonymous user tracking

rg4js('options', { disableAnonymousUserTracking: true });

Rich user data/user tracking

You can provide additional information about the currently logged in user to Raygun by calling:

rg4js('setUser', {
  identifier: '[email protected]',
  isAnonymous: false,
  email: '[email protected]',
  firstName: 'Foo',
  fullName: 'Foo Bar',
  uuid: 'BAE62917-ACE8-ab3D-9287-B6A33B8E8C55'
});

Only identifier or the first parameter is required. This method takes additional parameters that are used when reporting over the affected users. The full method signature of the public function and the options object above is:

setUser: function (user, isAnonymous, email, fullName, firstName, uuid)

user|identifier is the user identifier. This will be used to uniquely identify the user within Raygun. This is the only required parameter, but is only required if you are using Customers.

isAnonymous is a bool indicating whether the user is anonymous or actually has a user account. Even if this is set to true, you should still give the user a unique identifier of some kind.

email is the user's email address.

fullName is the user's full name.

firstName is the user's first or preferred name.

uuid is the identifier of the device the app is running on. This could be used to correlate user accounts over multiple machines.

This will be transmitted with each message. A count of unique users will appear on the dashboard in the individual error view. If you provide an email address, the user's Gravatar will be displayed (if they have one). This method is optional; if it is not called, the Customers feature is disabled. Note that if the user context changes (such as in an SPA), you should call this method again to update it.

Resetting the user

You can now pass in empty strings (or false to isAnonymous) to reset the current user for login/logout scenarios.

Ending a session

To end a user's current session:

rg4js('endSession');

This will end the session for a user and start a new one. The new session will remain attached to the current user.

Version filtering

You can set a version for your app by calling:

rg4js('setVersion', '1.0.0.0');

This will allow you to filter the errors in the dashboard by that version. You can also select only the latest version, to ignore errors that were triggered by ancient versions of your code. The parameter should be a string in the format x.x.x if you want to get the version sorting in Raygun to work nicely, where x is a non-negative integer.

Filtering sensitive data

You can blacklist keys to prevent their values from being sent it the payload by providing an array of key names:

rg4js('filterSensitiveData', ['password', 'credit_card']);

If any key matches one in the input array, its value will be replaced with [removed by filter].

You can also pass RegExp objects in the array to filterSensitiveData, for controllable matching of keys:

var creditCardDataRegex = /credit\D*/; // Remove any keys that begin with 'credit'

rg4js('filterSensitiveData', [creditCardDataRegex]);

Change filter scope

By default this is applied to the UserCustomData object only (legacy behavior). To apply this to any key-value pair, you can change the filtering scope:

rg4js('setFilterScope', 'all'); // Filter any key in the payload
rg4js('setFilterScope', 'customData'); // Just filter the custom data (default)

Source maps support

Raygun4JS now features source maps support through the transmission of column numbers for errors, where available. This is confirmed to work in recent version of Chrome, Safari and Opera, and IE 10 and 11. See the Raygun souce maps documentation for more information.

Offline saving

The provider has a feature where if errors are caught when there is no network activity they can be saved (in Local Storage). When an error arrives and connectivity is regained, previously saved errors are then sent. This is useful in environments like WinJS, where a mobile device's internet connection is not constant.

Offline saving is disabled by default. To change it:

rg4js('saveIfOffline', true);

If an error is caught and no network connectivity is available (the Raygun API cannot be reached), or if the request times out after 10s, the error will be saved to LocalStorage. This is confirmed to work on Chrome, Firefox, IE10/11, Opera and WinJS.

Limited support is available for IE 8 and 9 - errors will only be saved if the request times out.

Errors in scripts on other domains

Browsers have varying behavior for errors that occur in scripts located on domains that are not the origin. Many of these will be listed in Raygun as 'Script Error', or will contain junk stack traces. You can filter out these errors by settings this:

rg4js('options', { ignore3rdPartyErrors: true });

Whitelisting domains

There is also an option to whitelist domains which you do want to allow transmission of errors to Raygun, which accepts the domains as an array of strings:

rg4js('options', { ignore3rdPartyErrors: true });
rg4js('whitelistCrossOriginDomains', ['code.jquery.com']);

This can be used to allow errors from remote sites and CDNs.

The provider will default to attempt to send errors from subdomains - for instance if the page is loaded from foo.com, and a script is loaded from cdn.foo.com, that error will be transmitted on a best-effort basis.

To get full stack traces from cross-origin domains or subdomains, these requirements should be met:

  • The remote domain should have Access-Control-Allow-Origin set (to include the domain where raygun4js is loaded from).

  • For Chrome the script tag must also have crossOrigin="Anonymous" set.

  • Recent versions of Firefox (>= 31) will transmit errors from remote domains will full stack traces if the header is set (crossOrigin on script tag not needed).

In Chrome, if the origin script tag and remote domain do not meet these requirements the cross-origin error will not be sent.

Other browsers may send on a best-effort basis (version dependent) if some data is available but potentially without a useful stacktrace. The provider will cancel the send if no data is available.

Angular

You can extend the Angular error handler to send errors directly to Raygun.

// Create a new ErrorHandler and report an issue straight to Raygun
export class RaygunErrorHandler implements ErrorHandler {
  handleError(e: any) {
    rg4js('send', {
      error: e,
    });
  }
}

Vue.js

You can use the Vue.js error handler to send errors directly to Raygun.

For Vue.js 2.x, this can be done by setting a global error handler on the Vue.config.errorHandler property.

// Vue 2.x example
Vue.config.errorHandler = function(err, vm, info) {
  rg4js('send', {
    error: err,
    customData: [{ info: info }]
  });
};

For Vue.js 3.x, the .config property is part of the application instance. You will need to create your application instance first before you can assign the errorHandler property.

// Vue 3.x example
const app = Vue.createApp({});

app.config.errorHandler = function(err, vm, info) {
  rg4js('send', {
    error: err,
    customData: [{ info: info }]
  });
};

app.mount('#app');

Release History

View the changelog here

raygun4js's People

Contributors

anothergithub avatar autopulated avatar benjaminharding avatar bennycode avatar callum-mckay avatar crystalqdm avatar darcythomas avatar deacon-mcintyre avatar dependabot[bot] avatar dwnz avatar dylang avatar filip-dimitrievski avatar fundead avatar hamish-taylor avatar jamiepenney avatar jdstory avatar josephambe avatar krishnakapadia avatar lee-houghton avatar martin308 avatar mduncan26 avatar niraj-rajbhandari avatar olwiba avatar pano-skylakis avatar roryprimrose avatar sleepysaurus avatar sumitramanga avatar ubermouse avatar widdershin avatar yaronshamir 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  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  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  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  avatar  avatar  avatar  avatar  avatar

raygun4js's Issues

Ajax Signature Issue

With the recent update in 1.4.1 to the ajax override - there is an issue in how the url param is used. If you use the newer $.ajax(url,options) parameters the updated code works fine - but if you use the older single options object - it fails. This code here is perfect:

if (typeof url === "object") {
    options = url;
    url = undefined;
}

So we now have the correct 'options' and an undefined url. But later on line 1167 you still reference 'url' without a check:

try {
    return _oldAjax.call(this, url, options);
} catch (e) {
    TraceKit.report(e);
    throw e;
}

Where you could be doing this:

try {
    return (url) ? _oldAjax.call(this, url, options) : _oldAjax.call(this, options);
} catch (e) {
    TraceKit.report(e);
    throw e;
}

This update is defintely need for those user who prefer Zepto over jQuery and are using Standalone.Deferred for the deferred implementation - but possibly others as well.

Also for Zepto / Ender users - adding this on lines 1174 and 1446 would be a huge help:

window.jQuery || window.Zepto || window.ender || window.$

Thanks!

traceKitWrapper bug

I'm seeing errors in the log in this function:

TraceKit.wrap = function traceKitWrapper(func) {
    function wrapped() {
        try {
            return func.apply(this, arguments);
        } catch (e) {
            TraceKit.report(e);
            throw e;
        }
    }
    return wrapped;
};

Error message on the 'return func.apply' line:

JavaScript-object wordt verwacht
(translation: Javascript object expected)

Out of stack space in IE8

Win 7, IE 8 on Hyper-V (Host system: Win 8.1)
VM Assigned Memory: 2GB
Error: Out of stack space; Line 50, column 9

It appears that it's running out of stack space, capturing that error and thus running out of stack space again, since it ran out of it in the first place. IE8 is a strange place.

wp_20140512_006

Stacktrace property is null on js windows store app causing further exception

When throwing an exception in a JavaScript based windows store app (eg, throw new Error('test')) the stacktrace property of the exception is null. This causes a problem in computeStackTraceFromStacktraceProp as it is not coded to cope with an empty stacktrace.

Specifically line 715 of dist/raygun.js v 1.18.3.

EmberJS issue

Hi,

I'm using Ember JS, and i would love to use Raygun for all errors handling... But, now i cannot send any errors, cause every time when i do :

Raygun.send(error);

I'm getting same error in console:

Uncaught SyntaxError: Invalid regular expression: /function superFunction(){.....}/;

I believe that problem with lines:

navigator.userAgent.match(_excludedUserAgents[userAgentIndex] 

and

window.location.hostname && window.location.hostname.match(_excludedHostnames[hostIndex])

Improperly looping through arrays

The _excludedHostnames and _excludedUserAgents arrays are being looped through improperly. If there are any prototype functions attached to your Array object, they will be looped through (and cause an exception in Raygun4JS).

Proper way to handle this is to call hasOwnProperty on the array. I've fixed the issue, see below. Can someone please double-check/merge?

Passing function to withTags breaks sending additional tags in raygun.send

Passing a function to raygun.withTags causes an error if additional tags are passed in raygun.send.

mergeArray is called with the tag function and additional tag array in raygun.send. The tag function isn't evaluated yet, and so it attempts to call concat on a function, which bombs.

This is in raygun.vanilla.js 1.18.4

Undefined is not a function in processJQueryAjaxError

function processJQueryAjaxError(event, jqXHR, ajaxSettings, thrownError) {
    var message = 'AJAX Error: ' +
        (jqXHR.statusText || 'unknown') +' '+
        (ajaxSettings.type || 'unknown') + ' '+
        (truncateURL(ajaxSettings.url) || 'unknown');

    // ignore ajax abort if set in the options
    if (_ignoreAjaxAbort) {
      if (!jqXHR.getAllResponseHeaders()) {
         return;
       }
    }

    Raygun.send(thrownError || event.type, {
      status: jqXHR.status,
      statusText: jqXHR.statusText,
      type: ajaxSettings.type,
      url: ajaxSettings.url,
      ajaxErrorMessage: message,
      contentType: ajaxSettings.contentType,
      data: ajaxSettings.data ? ajaxSettings.data.slice(0, 10240) : undefined });
}

Happening on slice call as data is an HTMLDocument Object

_filteredKeys does not appear to filter AJAX JSONP data

I have to admit that I have only determined this issue by looking at the raygun.js source. It uses _filteredKeys to filter querystring key/value pairs only.

We are using stripe.js to submit credit card details to stripe and need to make sure that failures in that JSONP call do not result in raygun.js submitting the CC details to Raygun.

I'd like to see _filteredKeys being applied to all mechanisms for submitting data to Raygun.

Cheers :)

Error infinite loop?

Hi there,

We were puzzled at why our Raygun account's error processing limit was exceeded within the space of about an hour. It turns out we received over 16000 errors from a single user!

The error seems to come from this line of code:

sendToRaygun(JSON.parse(localStorage[key]));

I don't know how invalid JSON got into the localStorage key, but it doesn't handle the error raised by JSON.parse, so that error then gets stored and raised itself. Is it possible that Raygun4JS has got itself into an infinite loop here?

Possible version tag typo causing Bower confusion

It looks like the latest release was tagged v.1.13.1. Notice the extra full stop after the 'v'.

This seems to be causing Bower to think that 1.13.0 is still the latest available version.

You can still install 1.13.1 but you have to do something like bower install MindscapeHQ/raygun4js#v.1.13.1 to get Bower to find the tag.

Not sure if this was intentional or accidental, but maybe the tag could be renamed or a future version can be tagged in a more Bower friendly manner? Thanks!

Send responseText along with AJAX errors in processJQueryAjaxError

Just noticed that Raygun does not provide the responseText when it encounters an AJAX error. Is there a reason it omits it? You can easily pull it off of the jqXHR argument when there is an AJAX error. It would be very helpful to see this in the client. When we receive server errors but cannot see what the actual response was.

Update to latest version of TraceKit

There are several updates to TraceKit which Raygun does not bundle. For instance, TraceKit was updated not to patch the global window.onerror function unless .register() was called at least once.

During development, I don't call .attach() from Raygun, and thus in the newer versions of TraceKit, it would not be overriding the onerror function.

A reference to the commit is here -- there are also several commits past this one I think you guys should also think about pulling in.

occ/TraceKit@e70e401

Cannot set property 'parseUrl' of undefined

Errors rejected due to account processing limits get saved and sent again

We noticed this one when dealing with the result of #115.

If an error is rejected due to our raygun account's processing usage being maxed out, the API returns HTTP status code 429. Raygun4JS sees this as a network error (not 400 or 403), and thus saves the error to send later.

} else if (_enableOfflineSave && xhr.status !== 403 && xhr.status !== 400) {

I think this behaviour is probably unwanted in most cases. It means that as soon as our next billing period starts, we'll probably be slammed with thousands of errors that were saved to localStorage, and go over our limit again in less than a day - this month we went over our limit in less than 2 hours. If you're going over your processing limit, you're probably more interested in having a more recent snapshot of errors than in older ones.

I'm proposing not saving offline requests that resulted in HTTP 429. Does this sound like a reasonable change to you? If so I'll send a pull request.

Add error filtering

It would be awesome if I could pass Raygun a function which would return a boolean indicating whether an error should be logged to Raygun's servers or not. This function would be passed all the error data which Raygun has in order to make its decision.

Adding onBeforeSend events

Have you considered the ability to subscribe/attach callbacks to the send method so that users can attach custom data prior to sending each error?

This is not the same as withCustomData since it gives you flexibility to manipulate the data considering each error individually.

So for example, if I want to attach some data depending on the type of the error I would subscribe to onBeforeSend and in my callback have a simple conditional.

        Raygun.onBeforeSend(function(data, customData, customTags) {
            customData.isImportant = data.Error.ClassName === 'ImportantException';
        });

Processing _filteredKeys when lacking indexOf actually includes filtered fields rather than excludes them

The current code collects all of the fields that should be submitted when processing _filteredKeys. If Array.prototype.indexOf is not available then the code falls back to an index iteration. This code uses an incorrect equality check such that excluded fields and included and included fields are excluded.

Currently

              for (i = 0; i < _filteredKeys.length; i++) {
                if (_filteredKeys[i] === key) {
                   qs[key] = value;
                }
              }

but should be

              var included = true;
              for (i = 0; i < _filteredKeys.length; i++) {
                if (_filteredKeys[i] === key) {
                   included = false;
                   break;
                }
              }
              if (included) {
                   qs[key] = value;
              }

User tracking - bad cookie name

(v1.13.1 - 2014-11-12)

In ensureUser fn the cookie created is called raygun4js_userid but in resetAnonymousUser fn the cookie being cleared is called raygun4js-userid.

Publish to NPM

We'd like to install raygun4js through npm. You look to have everything you need to publish this (package.json, git tags, npm account) so should just be npm publish

Mark errors as client-side in UI

It would be great if errors listed in the app UI were marked somehow as being client-side. If you use the same app for both server and client errors it would make it easier to go through them.

Ajax abort issue

When we issue a xhr.abort(); call we are getting an 'Uncaught #' error from Raygun line 229. I'm not sure how common aborting xhr request is, so this might be edgecase, but it would be great if Raygun would ignore aborted xhr request. Thanks!

Combine Errors

When the same error occurs in different browsers they are listed separately on the site. So when checking in FireFox, Chrome, IE and Opera, 4 different errors are shown. I appreciate that this is tricky as all the browsers are different but the line numbers for the errors are the same, except for IE, which was one line off. Would be great if they were grouped together.

processJQueryAjaxError should be configurable: not send on 4xx status codes

As it stands, Raygun sends on every single ajaxError - regardless of the status.

In typical JSON API's you'd send back statuses like 422 when an entity fails validation. These aren't "true" errors, just normal workflow between client -> server.

I'm pretty sure anything in the 4xx should not be sent to Raygun. Regardless though, it would be nice to configure the behavior on ajaxError. As it stands processJQueryAjaxError is a "private" function and currently I have to replace Raygun.attach() to prevent it from being called.

anonymous functions missing from stacktrace in Phonegap/Cordova on iOS

Anonymous functions are excluded from the stacktrace in the UIWebView on iOS 7. This affects all Phonegap / Cordova apps running on iOS.

The regexs used by tracekit (see computeStackTraceFromStackProp()) to extract the stack information don't appear to be designed for this version of WebKit. The regex for Gecko ends up being used, but fails to extract anonymous functions.

Gecko format: <function_name>@<file_url>:<line_number>:<column_number>

iOS 7 UIWebView format (named function): <function_name>@<file_url>:<line_number>:<column_number>
iOS 7 UIWebView format (anon function): <file_url>:<line_number>:<column_number>

Basically, Gecko always includes the @ - even for anonymous functions - while Webkit does not. Simply making the @ optional in the regex fixes the issue, but it seems wrong to rely on the Gecko regex in the first place.

Option to exclude user agents from error reports

I like Raygun and it's JavaScript library is great!

But it would be useful if you could exclude certain browsers (user agents) from error reports. In the company I am working for we are using CasperJS to run automated tests on our web application. These tests cause errors which we evaluate within the reports generated by our test automation.

Because we use Raygun on our website, errors triggered by CasperJS will be reported in Raygun. We don't want that. So it would be nice if we could exclude certain user agents.

The user agent from CasperJS is:

Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/534.34 (KHTML, like Gecko) CasperJS/1.1.0-beta3+PhantomJS/1.9.8 Safari/534.34

Using excludedHostnames for us is not an option as we run our tests with CasperJS against a staging environment where we usally want to have error reports from Raygun.

Can you add an option so that errors will not be reported if the user agent matches a string from a given array? I was thinking about something like this:

Raygun.init('apikey', {
  debugMode: false,
  excludedUserAgents: ['CasperJS', 'PhantomJS', 'Googlebot', 'Android']
}).attach();

What do you think? Something like this would help us really much but perhaps there is already a different workaround?

Uncaught TypeError: Converting circular structure to JSON

We use the minified version of raygun since 8 days I see an error caused by raygun.

Uncaught TypeError: Converting circular structure to JSON
     at ? line 7, column undefined (http://www.spreadshirt.de/Public/Tablomat/build/8.20.5/sprd/lib/raygun.js:7)

Within the source in line 7 I cannot see a JSON.stringify, but maybe this due a call.

Provide Raygun.initialized() method

Since Raygun is registered as global whether it has been initialised or not (through init()), there should be a method initialized() that returns true if Raygun has been correctly initialised and can accept send() requests.

Currently we're using a hack to keep track of whether Raygun is initialised or not - we have to disable it for dev environments.

Protect against cyclical references when JSON serializing an object

We have hit an issue when an error report fails to process. The failure in Raygun.js is then reported rather than the original failure. This happens for example when the context data has a cyclical reference.

Converting circular structure to JSON
     at sendToRaygun line 1656, column 35 (https://localhost:44301/Scripts/raygun.js:1656)
     at processUnhandledException line 1645, column 7 (https://localhost:44301/Scripts/raygun.js:1645)
     at notifyHandlers line 135, column 33 (https://localhost:44301/Scripts/raygun.js:135)
     at HTMLBodyElement.traceKitWindowOnError line 188, column 9 (https://localhost:44301/Scripts/raygun.js:188)
     at Object.jQuery.event.trigger line 4330, column 27 (https://localhost:44301/Scripts/jquery-2.1.1.js:4330)
     at HTMLInputElement.<anonymous> line 4875, column 17 (https://localhost:44301/Scripts/jquery-2.1.1.js:4875)
     at Function.jQuery.extend.each line 375, column 23 (https://localhost:44301/Scripts/jquery-2.1.1.js:375)
     at jQuery.fn.jQuery.each line 139, column 17 (https://localhost:44301/Scripts/jquery-2.1.1.js:139)
     at jQuery.fn.extend.trigger line 4874, column 15 (https://localhost:44301/Scripts/jquery-2.1.1.js:4874)

I wanted to fix this with a pull request but it is something that requires too many design decisions. See http://stackoverflow.com/questions/11616630/json-stringify-avoid-typeerror-converting-circular-structure-to-json for an interesting discussion. I particularly like the look of using cycle.js to solve this problem (https://github.com/douglascrockford/JSON-js/blob/master/cycle.js).

In addition to this specific issue, more error handling in Raygun.js could be added as even partial error reporting is better than none.

publish to npm

If this client is different than the Node client, it would be helpful to publish this one to npm as well for those that use npm for all package management (frontend and backend) instead of bower.

This makes it easy to add raygun4js to the code by using

var raygun = require('raygun4js');
raygun.init(process.env.RAYGUN_API_KEY).attach();

in our frontend code, and use browserify to build the bundle.

Support for AMD/require.js

Being able to manage raygun4js with require.js when working with cross browser development or HTML5/javascript based mobile phone applications.

the log function does not handle data

When logging the data sent to Raygun the log function itself omits the data and only logs the message.

log('Sending exception data to Raygun:', data); 
function log(message) {
        if (window.console && window.console.log && _debugMode) {
            window.console.log(message);
        }
    }

Include response data in AJAX failure reporting

Currently an AJAX failure reports information about the request, but not the response from the server. This can lead to a lot of investigation and reproduction work. If raygun.js can also log the server response, this work becomes unnecessary where the server response contains information about the problem.

For example, our web api returns a Bad Request for when DOB is in the future. ATM, this is not captured client side via validation. In this scenario, the content of the response indicates both the field and the failure. When we look at raygun for such a scenario, all we see is the problem without all the context.

Cannot call method 'indexOf' of undefined caused by raygun itself

Hi,

I use the development version of raygun (1.8.1) and minify it during my own build step. Today I saw the following error message in raygun.

Uncaught TypeError: Cannot call method 'indexOf' of undefined
     at ? line 11, column undefined (http://www.spreadshirt.de/Public/Tablomat/build/8.20.0/sprd/lib/raygun.js:11)

The url points to the build version and contains the following content in line 11.

)return"";try{function r(){try{return new e.XMLHttpRequest}catch(t){return new e.ActiveXObject("Microsoft.XMLHTTP")}}var i=r();return i.open("GET",t,!1),i.send(""),i.responseText}catch(s){return""}}function f(e){if(!o(i,e)){var t="";e.indexOf(document

I traced it down to be equal with the unified version at Line 347
https://github.com/MindscapeHQ/raygun4js/blob/master/dist/raygun.js#L347

For some reason url is undefined and the method should check if before calling indexOf on the string. A fix could be

url = url || "";

Onerror callback

Would it be possible to have onSuccess and onError callbacks on lines 258 and 261 of raygun.js?

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.