Installation
The official Raygun provider for Node.js allows you to easily access crash reporting and error monitoring for your node.js network application.
This provider is flexible and supports many configuration scenarios - you can have it running and sending errors quickly, by manually placing send() calls when you detect an error. If you are using the Express.js web application framework, you can add the included middleware at the end of your middleware definitions. Or, you can use node.js domains.
What can I send from my node.js application?
The provider can send Error objects, with error details (time, message etc) a stack trace, request data, environment data, custom user data and more. If you wish to manually send other information, the transport object has a Send function which will pass data to Raygun with the required fields.
Step 1 - Install the Raygun provider
Install the raygun
library with NPM:
npm install raygun
Or with Yarn:
yarn add raygun
Step 2 - Create a RaygunClient
Create an instance of RaygunClient using your app API key. Your app API key is displayed when you create a new application in your Raygun account, or can be viewed in the application settings.
const raygun = require('raygun');
const raygunClient = new raygun.Client().init({
apiKey: 'paste_your_api_key_here',
batch: true,
reportUncaughtExceptions: true
});
When the reportUncaughtExceptions
option is enabled, uncaught exceptions will automatically be captured and sent to Raygun.
Step 3 - Release
Deploy Raygun into your production environment for best results, or raise a test exception. Once we detect your first error event, the Raygun app will automatically update.
Manually sending exceptions
The above instructions will setup Raygun to automatically detect and send all unhandled exceptions. Sometimes you may want to send exceptions manually, such as handled exceptions from within a try/catch block.
Send
You can report errors manually by calling raygunClient.send(error)
. For example:
try {
// some code that may throw an error
} catch (error) {
raygunClient.send(error);
}
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);
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 - This is a response code with an empty body.
If request performed OK, you'll recieve a 202 response code. Otherwise, we'll throw
- 401 response code for incorrect API keys
- 403 response code if you're over your plan limits,
- Or 500+ response codes for anything in the range of internal errors
We use the Node.js http/https
library to make the POST to Raygun. You can view more documentation about this callback in the NodeJS external documentation site
You can await
the call to obtain the result, or use then/catch
.
Using await
Use await
to obtain the IncomingMessage
. Ensure 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
});
Express.js
If you are using Express.js to develop a web application, you can use the provided middleware as an error handler, at the bottom of your middleware definitions:
const raygunClient = new raygun.Client().init({apiKey: '{{paste_your_api_key_here}}'});
// ...
app.use(express.static(path.join(__dirname, 'public')));
app.use(raygunClient.expressHandler);
Express.js 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.
Send Parameters
The send()
method accepts a series of optional named parameters, defined as followed:
client.send(error, { customData, request, tags, timestamp, userInfo });
All these parameters are optional and are explained in detail in the following sections.
Sending custom data
You can pass custom data in on the Send() function, as the customData
parameter. For instance:
client.send(new Error(), { customData: { 'mykey': 'beta' } });
Sending custom data with Express.js
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: "yourkey"});
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: 'paste_your_api_key_here',
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 three different ways to do that:
- Provide the
userInfo
parameter in thesend()
method. - 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 of type string
except isAnonymous
, which is of type boolean
.
They are also all optional. Any other properties will be discarded.
Example:
userInfo = {
identifier: "123",
email: "user@example.com",
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:
setUser("123");
userInfo
parameter in send()
You can provide the userInfo
optional parameter in the send()
method call:
client.send(new Error(), { userInfo });
The provided user information will take priority over the user(request)
and setUser(user)
methods.
raygunClient.user(req)
Implement 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.
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 so:
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');
BreadcrumbMessage
:
Using 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: 'paste_your_api_key_here',
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.
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: 'paste_your_api_key_here',
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: 'paste_your_api_key_here',
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 providersave(transportItem, callback)
- Called when marked as offlineretrieve(callback)
- Returns an array of cached item filenames/idssend(callback)
- Sends the backlog of errors to Raygun
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. NOTE: We only recommend doing this if you are having issues with errors not being grouped properly.
When initializing Raygun, pass through a groupingKey
function.
const raygunClient = new raygun.Client().init({
apiKey: 'paste_your_api_key_here',
groupingKey: function(message, exception, customData, request, tags) {
return "BUILD_CUSTOM_KEY_HERE";
}
});
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: 'paste_your_api_key_here',
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: 'paste_your_api_key_here',
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 -L
-X GET
-u my@email.com: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 -L
-X DELETE
-u my@email.com: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 -L
-X DELETE
-u my@email.com: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).
AWS Lambda
If you are using AWS Lambda functions, you can use the @raygun.io/aws-lambda package.
This package provides two main advantages compared to using Raygun directly:
- Captures any uncaught error in the AWS Lambda function and reports it to Raygun automatically.
- Scopes Breadcrumbs to the current function session.
To add Raygun to an existing AWS Lambda function, wrap the existing handler implementation with the awsHandler
function.
Before:
exports.handler = async function (event, context) {
// your code
}
After:
// 1. Configure your Raygun client outside the AWS Lambda function
const client = new Raygun.client().init( ... );
// 2. Wrap the existing function with awsHandler and pass the client as the first parameter
exports.handler = awsHandler({ client }, async function (event, context) {
// your code
});
If you need additional details, the package documentation @raygun.io/aws-lambda may be useful.
The provider is open source and available at the Raygun4node repository.