Hi there π
As of November 2020, Sentry supports adding specific information to the context on each captured error, so this package has been archived & deprecated.
Self-managed scope management for @sentry/node π¦Ύ
Vedette: A mounted sentry positioned beyond an army's outposts to observe the movements of the enemy.
const Sentry = require('@sentry/node');
const Vedette = require('vedette');
Sentry.init();
const ved = new Vedette();
ved.setTag('hostname', 'localhost');
ved.setTags({ method: 'POST', endpoint: '/api' });
ved.setUser({ id: '11211', ip_address: '127.0.0.1' });
ved.setExtra('requestID', 'f05991fd-8719-4dd5-8e2e-a70c0ef0efbe');
ved.setExtras({ code: 'DROIDS_NOT_FOUND' });
ved.captureException(new Error('These are not the droids you are looking for, move along'));
ved.captureMessage('These are not the droids you are looking for, move along');
Vedette.captureException(new Error('These are not the droids you are looking for, move along'), {
user: { ip_address: '127.0.0.1' },
level: 'fatal',
});
Vedette.captureMessage('These are not the droids you are looking for, move along', {
user: { id: '11211' },
level: 'warning',
});
$ npm install --save git+https://github.com/someimportantcompany/vedette#1.1.3
Currently, @sentry/node doesn't appear to you to pass a scope as an argument, instead continuing to use the deprecated domains module. They have their (good) reasons, however they still could allow scopes to be portable for those that don't want to use domains in their code.
This library attempts to solve this by wrapping around the default scope functions & calling withScope
before captureException
/captureMessage
to include all your locally-set properties. It also offers a couple of static methods to send errors/messages in one invocation.
const ved = new Vedette();
ved.addBreadcrumb({
level: 'info',
message: 'These are not the droids you are looking for, move along',
});
Passes breadcrumbs to Sentry.addBreadcrumb
.
ved.clearBreadcrumbs();
Clears all the breadcrumbs stored so far.
ved.setTag('key', 'value');
Set one tag.
ved.setTags({
key1: 'value1',
key2: 'value2',
});
Set multiple tags.
ved.setUser({
id: '11211',
ip_address: '127.0.0.1',
});
Set the user properties.
ved.setExtra('key', 'value');
Set one extra property.
ved.setExtras({
key1: 'value1',
key2: 'value2',
});
ved.setLevel('warning');
Set a level for all particular errors & messages. Less useful in this form, more useful with Vedette.captureException
& Vedette.captureMessage
.
Levels directly from @sentry/types
:
debug
log
info
warning
error
fatal
critical
ved.populateSentryScope(scope);
Transfer the breadcrumbs, tags, user & extra data to the Sentry scope.
ved.captureException(new Error('These are not the droids you are looking for, move along'));
ved.captureException(new Error('These are not the droids you are looking for, move along'), {
// Optional tags
tags: { tag1: 'value1' },
// Optional user
user: { id: '11211' },
// Optional extras
extra: { extra2: 'value2' },
// Optional level
level: 'fatal',
});
Capture an exception, transferring the breadcrumbs, tags, user & extra data to the Sentry scope before sending.
ved.captureMessage('These are not the droids you are looking for, move along');
ved.captureMessage('These are not the droids you are looking for, move along', {
// Optional tags
tags: { tag1: 'value1' },
// Optional user
user: { id: '11211' },
// Optional extras
extra: { extra2: 'value2' },
// Optional level
level: 'fatal',
});
Capture a message, transferring the breadcrumbs, tags, user & extra data to the Sentry scope before sending.
For convenience, there are some static methods to complete common scenarios.
Vedette.captureException(new Error('These are not the droids you are looking for, move along'));
Vedette.captureException(new Error('These are not the droids you are looking for, move along'), {
// Optional tags
tags: { tag1: 'value1' },
// Optional user
user: { id: '11211' },
// Optional extras
extra: { extra2: 'value2' },
// Optional level
level: 'fatal',
});
Capture an exception, optionally throwing some tags, user & extra data into the mix in one function call.
Vedette.captureMessage('These are not the droids you are looking for, move along');
Vedette.captureMessage('These are not the droids you are looking for, move along', {
// Optional tags
tags: { tag1: 'value1' },
// Optional user
user: { id: '11211' },
// Optional extras
extra: { extra2: 'value2' },
// Optional level
level: 'warning',
});
Capture a message, optionally throwing some tags, user & extra data into the mix in one function call.
const assert = require('http-assert');
const bodyParser = require('body-parser');
const express = require('express');
const Sequelize = require('sequelize');
const Sentry = require('@sentry/node');
const Vedette = require('vedette');
Sentry.init({
environment: process.env.NODE_ENV || 'development',
});
const app = express();
const sequel = new Sequelize('project', 'root', 'password', {
host: '127.0.0.1',
dialect: 'mysql',
});
const users = sequel.import('./UserModel');
app.use(bodyParser.json({ limit: '1mb' }));
app.use((req, res, next) => {
req.ved = new Vedette();
next();
});
app.get('/droids', function (req, res, next) {
throw new Error('These are not the droids you are looking for, move along');
});
app.use((err, req, res, next) => {
req.ved = req.ved || new Vedette();
req.ved.setTags({
method: req.method,
path: req.route.path,
});
req.ved.captureException(err);
res.status(err.status || 500).json(`${err}`);
})
app.listen(8080, () => console.log('π Server ready at http://localhost:3000/'));
const Sentry = require('@sentry/node');
const Vedette = require('vedette');
const { ApolloServer, gql } = require('apollo-server');
Sentry.init({
environment: process.env.NODE_ENV || 'development',
});
const typeDefs = gql`
type Book {
title: String
author: String
}
type Query {
books: [ Book ]
}
`;
const resolvers = {
Query: {
books(parent, args, ctx) {
ctx.ved.addBreadcrumb({ message: 'Hit the books query' });
throw new Error('These are not the droids you are looking for, move along');
return [
{
title: 'Harry Potter and the Chamber of Secrets',
author: 'J.K. Rowling',
},
{
title: 'Jurassic Park',
author: 'Michael Crichton',
},
];
},
},
};
const server = new ApolloServer({
typeDefs,
resolvers,
context() {
return {
ved: new Vedette(),
};
},
formatResponse(result, info) {
const { context: ctx } = info;
if (result.errors) {
result.errors = result.errors.forEach(err => {
if (err.originalError) {
(ctx.ved || Vedette).captureException(err.originalError);
} else {
(ctx.ved || Vedette).captureException(err);
}
});
}
return result;
},
});
server.listen().then(({ url }) => console.log(`π Server ready at ${url}`));
const Sentry = require('@sentry/node');
const Vedette = require('vedette');
Sentry.init({
environment: process.env.NODE_ENV || 'development',
});
module.exports.handler1 = function handler1(event, context, callback) {
const ved = new Vedette();
try {
throw new Error('These are not the droids you are looking for, move along');
callback();
} catch (err) {
// Capture the exception
ved.captureException(err);
// Push the exception to Sentry before Lambda finishes
await Sentry.flush(2000);
// Trigger the callback
callback(err);
}
};
module.exports.handler2 = function handler2(event, context, callback) {
try {
throw new Error('These are not the droids you are looking for, move along');
callback();
} catch (err) {
// Capture the exception
ved.captureException(err);
// Push the exception to Sentry before Lambda finishes
await Sentry.flush(2000);
// Trigger the callback
callback(err);
}
};
import Vue from 'vue';
import * as Sentry from '@sentry/browser';
import { Vue as VueIntegration } from '@sentry/integrations';
import Vedette from 'vedette';
Sentry.init({
dsn: process.env.SENTRY_DSN,
integrations: [ new VueIntegration({ Vue, attachProps: true }) ],
});
const app = new Vue({
computed: {
ved: () => new Vedette(),
},
mounted() {
this.ved.setTag('origin', window.location.origin);
this.ved.setUser({ id: '11211' });
},
methods: {
sendException() {
const err = new Error('These are not the droids you are looking for, move along');
this.ved.captureException(err);
},
},
});
app.$mount('#app');