Skip to content
This repository was archived by the owner on Oct 23, 2023. It is now read-only.

Commit 2e9c8e5

Browse files
committed
Merge branch 'master' of github.com:getsentry/raven-node into proxy_support
2 parents ed0172a + ff785f0 commit 2e9c8e5

19 files changed

+896
-43
lines changed

.travis.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
branches:
2+
only:
3+
- master
14
sudo: false
25
language: node_js
36
node_js:
@@ -6,4 +9,7 @@ node_js:
69
- "6"
710
- "7"
811
- "8"
12+
cache:
13+
directories:
14+
- node_modules
915
script: npm run test-full

History.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
# 2.2.1 - 10/02/2017
2+
3+
- Remove unintentional memwatch-next dependency
4+
5+
# 2.2.0 - 10/02/2017
6+
- Fixed all Node v8 tests to ensure everything is working correctly [See #366]
7+
- Raven now uses Prettier to format it's code [See #364]
8+
- Prevent Raven from queueing too many requests in case server is down [See #132]
9+
- Enable keep-alive on socket connection and limit number of sockets [See #284]
10+
- Pull Error's name from constructor, not Error itself to always get correct error type [See #372]
11+
- Updated Errors serialization to store all additional properties and allow for attaching other object instances directly to it [See #376]
12+
- Preserve some non-enumerable properties from request [See #379]
13+
- Fall back to NODE_ENV for Sentry Environment [See #384]
14+
115
# 2.1.2 - 8/16/2017
216
- Remove errant large file that accidentally got published in 2.1.1. [See #361]
317

docs/config.rst

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,20 @@ To get started, you need to configure Raven to use your Sentry DSN:
66
.. sourcecode:: javascript
77

88
var Raven = require('raven');
9-
Raven.config('___PUBLIC_DSN___').install()
9+
Raven.config('___PUBLIC_DSN___').install();
1010

1111
At this point, Raven is ready to capture any uncaught exceptions.
1212

13+
Note that the ``install`` method can optionally take a callback function that is invoked if a fatal, non-recoverable error occurs.
14+
You can use this callback to perform any cleanup that should occur before the Node process exits.
15+
16+
.. sourcecode:: javascript
17+
18+
Raven.config('___PUBLIC_DSN___').install(function (err, initialErr, eventId) {
19+
console.error(err);
20+
process.exit(1);
21+
});
22+
1323
Optional settings
1424
-----------------
1525

@@ -18,8 +28,8 @@ Optional settings
1828
.. sourcecode:: javascript
1929

2030
Raven.config('___PUBLIC_DSN___', {
21-
release: '1.3.0'
22-
}).install()
31+
release: '1.3.0'
32+
}).install();
2333

2434
Those configuration options are documented below:
2535

@@ -33,19 +43,44 @@ Those configuration options are documented below:
3343
logger: 'default'
3444
}
3545
46+
.. describe:: name
47+
48+
Set the server name for the client to use. Default: ``require('os').hostname()``
49+
Optionally, use ``SENTRY_NAME`` environment variable.
50+
51+
.. code-block:: javascript
52+
53+
{
54+
name: 'primary'
55+
}
56+
3657
.. describe:: release
3758

3859
Track the version of your application in Sentry.
60+
Optionally, use ``SENTRY_RELEASE`` environment variable.
3961

4062
.. code-block:: javascript
4163
4264
{
4365
release: '721e41770371db95eee98ca2707686226b993eda'
4466
}
4567
68+
This is usually a Git SHA hash, which can be obtained using various npm packages, e.g.
69+
70+
.. code-block:: javascript
71+
72+
var git = require('git-rev-sync');
73+
74+
{
75+
// this will return 40 characters long hash
76+
// eg. '75bf4eea9aa1a7fd6505d0d0aa43105feafa92ef'
77+
release: git.long()
78+
}
79+
4680
.. describe:: environment
4781

4882
Track the environment name inside Sentry.
83+
Optionally, use ``SENTRY_ENVIRONMENT`` environment variable.
4984

5085
.. code-block:: javascript
5186
@@ -195,6 +230,14 @@ Those configuration options are documented below:
195230
Please see the raven-node source code to see `how transports are implemented
196231
<https://github.com/getsentry/raven-node/blob/master/lib/transports.js>`__.
197232

233+
.. describe:: maxReqQueueCount
234+
235+
Controls how many requests can be maximally queued before bailing out and emitting an error. Defaults to `100`.
236+
237+
.. describe:: stacktrace
238+
239+
Attach stack trace to `captureMessage` calls by generatic "synthetic" error object and extracting all frames.
240+
198241
Environment Variables
199242
---------------------
200243

@@ -204,13 +247,12 @@ Environment Variables
204247

205248
.. describe:: SENTRY_NAME
206249

207-
Optionally set the name for the client to use. `What is name?
208-
<http://raven.readthedocs.org/en/latest/config/index.html#name>`__
250+
Optionally set the server name for the client to use.
209251

210252
.. describe:: SENTRY_RELEASE
211253

212254
Optionally set the application release version for the client to use, this is usually a Git SHA hash.
213255

214256
.. describe:: SENTRY_ENVIRONMENT
215257

216-
Optionally set the environment name, e.g. "staging", "production".
258+
Optionally set the environment name, e.g. "staging", "production". Sentry will default to the value of `NODE_ENV`, if present.

docs/integrations/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ Integrations
77
connect
88
express
99
koa
10+
loopback
11+
sails

docs/integrations/loopback.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Loopback
2+
========
3+
4+
.. code-block:: javascript
5+
6+
// server/middleware/sentry.js
7+
8+
var Raven = require('raven');
9+
Raven.config('__DSN__').install();
10+
11+
module.exports = function () {
12+
return Raven.errorHandler();
13+
}
14+
15+
.. code-block:: javascript
16+
17+
// server/middleware.json
18+
19+
"final": {
20+
"./middleware/sentry": {}
21+
}

docs/integrations/sails.rst

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
Sails
2+
=====
3+
4+
.. code-block:: javascript
5+
6+
// config/http.js
7+
8+
var Raven = require('raven');
9+
Raven.config('__DSN__').install();
10+
11+
module.exports.http = {
12+
middleware: {
13+
// Raven's handlers has to be added as a keys to http.middleware config object
14+
requestHandler: Raven.requestHandler(),
15+
errorHandler: Raven.errorHandler(),
16+
17+
// And they have to be added in a correct order to middlewares list
18+
order: [
19+
// The request handler must be the very first one
20+
'requestHandler',
21+
// ...more middlewares
22+
'router',
23+
// The error handler must be after router, but before any other error middleware
24+
'errorHandler',
25+
/// ...remaining middlewares
26+
]
27+
}
28+
}
29+
30+

docs/usage.rst

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,11 @@ All optional attributes are passed as part of the options to ``captureException`
136136
137137
If you're inside a context and your context data includes a ``user`` key, that data will be merged into this.
138138

139-
.. describe:: req
139+
.. describe:: request
140140

141-
The ``req`` object associated with this event, from a Node http server, Express, Koa, or similar.
142-
Will be parsed for request details and user context from ``req.user`` if present.
141+
Alias: ``req``. The ``request`` object associated with this event, from a Node http server, Express, Koa, or similar.
142+
Will be parsed for request details and user context from ``request.user`` if present. It will only pull out the data
143+
that's handled by the server: ``headers``, ``method``, ``host``, ``protocol``, ``url``, ``query``, ``cookies``, ``body``, ``ip`` and ``user``.
143144

144145
.. code-block:: javascript
145146
@@ -299,7 +300,7 @@ It can do anything necessary, including asynchronous operations, to make a best
299300
not throw, and it absolutely must not allow the process to keep running indefinitely. This means it should probably make an explicit ``process.exit()`` call.
300301

301302
After catching a fatal exception, Raven will make a best-effort attempt to send it to Sentry before it calls the fatal exception handler.
302-
If sending fails, a ``sendErr`` error object will be passed, and otherwise the ``eventId`` will be provided. In either case, the error object
303+
If sending fails, a ``sendErr`` error object will be passed, and otherwise the ``eventId`` will be provided. In either case, the error object
303304
resulting in the shutdown is passed as the first parameter.
304305

305306
.. code-block:: javascript

lib/client.js

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
var stringify = require('json-stringify-safe');
3+
var stringify = require('../vendor/json-stringify-safe');
44
var parsers = require('./parsers');
55
var zlib = require('zlib');
66
var utils = require('./utils');
@@ -54,7 +54,8 @@ extend(Raven.prototype, {
5454
this.transport = options.transport || transports[this.dsn.protocol];
5555
this.sendTimeout = options.sendTimeout || 1;
5656
this.release = options.release || process.env.SENTRY_RELEASE || '';
57-
this.environment = options.environment || process.env.SENTRY_ENVIRONMENT || '';
57+
this.environment =
58+
options.environment || process.env.SENTRY_ENVIRONMENT || process.env.NODE_ENV || '';
5859

5960
// autoBreadcrumbs: true enables all, autoBreadcrumbs: false disables all
6061
// autoBreadcrumbs: { http: true } enables a single type
@@ -67,7 +68,9 @@ extend(Raven.prototype, {
6768
this.dataCallback = options.dataCallback;
6869
this.shouldSendCallback = options.shouldSendCallback;
6970
this.sampleRate = typeof options.sampleRate === 'undefined' ? 1 : options.sampleRate;
71+
this.maxReqQueueCount = options.maxReqQueueCount || 100;
7072
this.parseUser = options.parseUser;
73+
this.stacktrace = options.stacktrace || false;
7174

7275
if (!this.dsn) {
7376
utils.consoleAlert('no DSN provided, error reporting disabled');
@@ -227,15 +230,18 @@ extend(Raven.prototype, {
227230
but also want to provide convenience for passing a req object and having us parse it out
228231
so we only parse a `req` property if the `request` property is absent/empty (and hence we won't clobber)
229232
parseUser returns a partial kwargs object with a `request` property and possibly a `user` property
230-
*/
231-
kwargs.request = extend(
232-
{},
233+
*/
234+
kwargs.request = this._createRequestObject(
233235
this._globalContext.request,
234236
domainContext.request,
235237
kwargs.request
236238
);
237239
if (Object.keys(kwargs.request).length === 0) {
238-
var req = extend({}, this._globalContext.req, domainContext.req, kwargs.req);
240+
var req = this._createRequestObject(
241+
this._globalContext.req,
242+
domainContext.req,
243+
kwargs.req
244+
);
239245
if (Object.keys(req).length > 0) {
240246
var parseUser = Object.keys(kwargs.user).length === 0 ? this.parseUser : false;
241247
extend(kwargs, parsers.parseRequest(req, parseUser));
@@ -313,8 +319,31 @@ extend(Raven.prototype, {
313319
} else {
314320
kwargs = kwargs || {};
315321
}
322+
316323
var eventId = this.generateEventId();
317-
this.process(eventId, parsers.parseText(message, kwargs), cb);
324+
325+
if (this.stacktrace) {
326+
var ex;
327+
// Generate a "synthetic" stack trace
328+
try {
329+
throw new Error(message);
330+
} catch (ex1) {
331+
ex = ex1;
332+
}
333+
334+
utils.parseStack(
335+
ex,
336+
function(frames) {
337+
// We trim last frame, as it's our `throw new Error(message)` call itself, which is redundant
338+
kwargs.stacktrace = {
339+
frames: frames.slice(0, -1)
340+
};
341+
this.process(eventId, parsers.parseText(message, kwargs), cb);
342+
}.bind(this)
343+
);
344+
} else {
345+
this.process(eventId, parsers.parseText(message, kwargs), cb);
346+
}
318347

319348
return eventId;
320349
},
@@ -512,6 +541,47 @@ extend(Raven.prototype, {
512541
currCtx.breadcrumbs.shift();
513542
}
514543
this.setContext(currCtx);
544+
},
545+
546+
_createRequestObject: function() {
547+
/**
548+
* When using proxy, some of the attributes of req/request objects are non-enumerable.
549+
* To make sure, that they are still available to us after we consolidate our sources
550+
* (eg. globalContext.request + domainContext.request + kwargs.request),
551+
* we manually pull them out from original objects.
552+
*
553+
* Same scenario happens when some frameworks (eg. Koa) decide to use request within
554+
* request. eg `this.request.req`, which adds aliases to the main `request` object.
555+
* By manually reassigning them here, we don't need to add additional checks
556+
* like `req.method || (req.req && req.req.method)`
557+
*
558+
* We don't use Object.assign/extend as it's only merging over objects own properties,
559+
* and we don't want to go through all of the properties as well, as we simply don't
560+
* need all of them.
561+
**/
562+
var sources = Array.from(arguments).filter(function(source) {
563+
return Object.prototype.toString.call(source) === '[object Object]';
564+
});
565+
sources = [{}].concat(sources);
566+
var request = extend.apply(null, sources);
567+
var nonEnumberables = [
568+
'headers',
569+
'host',
570+
'ip',
571+
'method',
572+
'protocol',
573+
'query',
574+
'secure',
575+
'url'
576+
];
577+
578+
nonEnumberables.forEach(function(key) {
579+
sources.forEach(function(source) {
580+
if (source[key]) request[key] = source[key];
581+
});
582+
});
583+
584+
return request;
515585
}
516586
});
517587

lib/parsers.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
var cookie = require('cookie');
44
var urlParser = require('url');
5-
var stringify = require('json-stringify-safe');
5+
var stringify = require('../vendor/json-stringify-safe');
66

77
var utils = require('./utils');
88

@@ -15,7 +15,8 @@ module.exports.parseText = function parseText(message, kwargs) {
1515

1616
module.exports.parseError = function parseError(err, kwargs, cb) {
1717
utils.parseStack(err, function(frames) {
18-
var name = err.name + '';
18+
var name =
19+
({}.hasOwnProperty.call(err, 'name') ? err.name : err.constructor.name) + '';
1920
if (typeof kwargs.message === 'undefined') {
2021
kwargs.message = name + ': ' + (err.message || '<no message>');
2122
}

0 commit comments

Comments
 (0)