Introduction
Sentry is an open source error tracking tool, that helps developers monitor and fix crashes in real time. It's really fast to set up, and supports many platforms and programming languages.
On the Web UI of sentry, you can see all errors that your code captured, a stack trace, context and breadcrumbs (if you implement it).
Setting up your Sentry project
After you've registered onSentry and logged in, press New Project in the top-right corner.
In this tutorial, we're covering the generic Node.js usage of Sentry, so make sure to choose Node.js instead of Express.
After giving your project a name and clicking on the shiny Create button, a documention page should pop up.
Below the "Configuring the Client" headline, there should be a codeblock containing your Sentry DSN.Save that code somewhere, becausewe'll need it later, so we can communicate with Sentry via our client module, Raven.
Setting up Raven
After creating your project on the Sentry website, it's time to spin up your editor and start coding.
First, you'll need to add the Raven module to your project.
npm install raven --save
Open the code you've saved earlier from the Sentry website, and paste it along the other require statements in your file. To make the codeready for public Git providers, don't forget toremove the hardcoded Sentry DSN, and move it to an external gitignored config file, or toenvironment variables.
Capturing errors
Let's present the different methods of capturing errors with a sample code.
functiondoSomething(data){if(data){// Check if our data is defined or notreturndata;// Return data}else{thrownewError("Missing required data parameter.");// Throw error}}doSomething();// Call doSomething without defining data -> error thrown
Our functiondoSomething
will check if it's parameterdata
is defined: if it is, it just returns it, but if it isn't,it throws an error. Just after definingdoSomething
, our code calls it,without supplying the data parameter, therefore throwing an error.
There are two main methods for capturing issues with the Raven client:
- Wrapping code into a context, or
- Manually capturing errors.
Method 1 - Wrapping code into a context
There are two methods of wrapping code into a context:Raven.context
, andRaven.wrap
. There aren't many differences, except thatRaven.wrap
returns a function, whileRaven.context
doesn't, meaning that you'd want to useRaven.wrap
for code like callbacks, andRaven.context
for just generic code wrapping.
varRaven=require('raven');Raven.config('https://13c3c4f3c6094d749436722b3031f787:6fe68b76c7e34d2cb69831355d6e3beb@sentry.io/301629').install();functiondoSomething(data){if(data){// Check if our data is defined or notreturndata;// Return data}else{thrownewError("Missing required data parameter.");// Throw error}}Raven.context(function(){// Wrap the following code with Raven.contextdoSomething();// Call doSomething without defining data -> error thrown});setTimeout(Raven.wrap(function(){doSomething();// Call doSomething without defining data -> error thrown},1000);// Run doSomething delayed with setTimeout and Raven.wrap
There's a major advantage for using this method instead of manually capturing errors: code inside a context (a.k.a. code insideRaven.wrap
orRaven.context
) hasaccess to methods that enable associating data with the context, which can be useful for debugging.
varRaven=require('raven');Raven.config('https://13c3c4f3c6094d749436722b3031f787:6fe68b76c7e34d2cb69831355d6e3beb@sentry.io/301629').install();functiondoSomething(data){if(data){// Check if our data is defined or notreturndata;// Return data}else{thrownewError("Missing required data parameter.");// Throw error}}Raven.context(function(){// Wrap the following code with Raven.contextRaven.setContext({// Set context data with the specified objecttags:{component:'main'}});Raven.mergeContext({// Extend context data with the specified objecttags:{method:'doSomething'}});console.log(Raven.getContext());doSomething();// Call doSomething without defining data -> error thrown});
Keep in mind thatsetContext
,mergeContext
andgetContext
only work in codeinside a context.
You can store anything inside your context data, for example, you could associate errors with user data, like this:
Raven.setContext({user:{email:'matt@example.com',id:123}});
Method 2 - Manually capturing errors
With Raven'scaputreException
, you can capturenon-thrown exceptions, or you can capture thrown exceptions using atry-catch block.
varRaven=require('raven');Raven.config('https://13c3c4f3c6094d749436722b3031f787:6fe68b76c7e34d2cb69831355d6e3beb@sentry.io/301629').install();functiondoSomething(data){if(data){// Check if our data is defined or notreturndata;// Return data}else{thrownewError("Missing required data parameter.");// Throw error}}try{doSomething();// Call doSomething without defining data -> error thrown}catch(e){Raven.captureException(e,function(sendErr){// Capture exceptionif(sendErr){// Check if send failedconsole.error("Failed to send exception to Sentry.");}else{console.log("Exception sent to Sentry.");}});}
You can usecaptureMessage
tosend non-exception error messages to Sentry.
varRaven=require('raven');Raven.config('https://13c3c4f3c6094d749436722b3031f787:6fe68b76c7e34d2cb69831355d6e3beb@sentry.io/301629').install();functiondoSomething(data){if(data){// Check if our data is defined or notreturn;// Return nothing}else{return"Missing required data parameter.";// Return error}}varerr=doSomething();// Call doSomething without defining data -> error returnedif(err){Raven.captureMessage(err,function(err){// Sent!});}
Although youdo not have access tosetContext
and other context-only functions, you cansupply additional data tocaptureException
andcaptureMessage
that should be captured.
Raven.captureException(err,{user:{id:123},// User-related inforeq:req,// Request object from HTTP web server (handled by Raven Express)tags:{component:'main',method:'doSomething'},// Tagsextra:{catType:cat.type},// Any other data you'd specify with setContextlevel:'error'// Event level});
For more additional information you can provide, visitthe Raven Node docs.
Breadcrumbs, breadcrumbs everywhere!
For additional info on databefore the exception happened, Breadcrumbs are the solution. Breadcrumbs are atrail of events that occurred in your applicationleading up to a captured error. They can be as simple asa log message, or they can containrich metadata about the state of your appliction, like network requests, database queries, or even earlier occurring errors.
Raven for Node supports a feature calledautoBreadcrumbs
, whichautomatically records useful breadcrumbs, like HTTP(S) requests, log statements (withconsole.log
,.warn
, etc.), and PostgreSQL queries via thepg
module.
To enable it, add this setting toRaven.config
, and you're good to go!
Raven.config('https://13c3c4f3c6094d749436722b3031f787:6fe68b76c7e34d2cb69831355d6e3beb@sentry.io/301629',{autoBreadcrumbs:true// Enable autoBreadcrumbs}).install();
This may be just enough for you, but if it isn't, fear not! There's an easy way of capturing breadcrumbs manually.
varRaven=require('raven');Raven.config('https://13c3c4f3c6094d749436722b3031f787:6fe68b76c7e34d2cb69831355d6e3beb@sentry.io/301629').install();functiondoSomething(data){if(data){// Check if our data is defined or notreturndata;// Return data}else{thrownewError("Missing required data parameter.");// Throw error}}varourJson="{}";// Blank JSON object, not containing needed data.Raven.context(function(){// Wrap the following code with Raven.contextvarparsedJson=JSON.parse(ourJson);// Parse JSONRaven.captureBreadcrumb({// Capture breadcrumbmessage:'Parsed JSON',category:'log',data:{raw:ourJson,parsedJson:parsedJson}});doSomething(parsedJson.data);// Call doSomething with non-existing data -> error thrown});
If we view the error on the Web UI, we can see our breadcrumb containing our raw JSON and our parsed JSON, this way we can see if the JSON doesn't have the needed data (which is the case here), or if we parsed the JSON wrong.
This can be really useful for debugging info that is coming from an outside source, so you can see if your code is wrong, or if the users' input is wrong.
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse