Skip to content

Make the transport mechanism (for making requests to Sentry) pluggable. #335

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/config/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,22 @@ maxMessageLength

By default, raven truncates messages to a max length of 100 characters. You can customize the max length with this parameter.

transportMechanism
------------------

A function that accepts the data, and the endpoint details that allow you to
customise when and how errors are sent over the network.

.. code-block:: javascript

{
transportMechanism: function(data, server, authQueryString) {
var endpoint = server + authQueryString + '&sentry_data=' + encodeURIComponent(JSON.stringify(data));
yourFetchMethod(endpoint);
}
}



Putting it all together
~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
13 changes: 10 additions & 3 deletions src/raven.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ var _Raven = window.Raven,
collectWindowErrors: true,
tags: {},
maxMessageLength: 100,
transportMechanism: makeRequest,
extra: {}
},
authQueryString,
Expand Down Expand Up @@ -67,6 +68,8 @@ var Raven = {
lastSlash = uri.path.lastIndexOf('/'),
path = uri.path.substr(1, lastSlash);

globalOptions.transportMechanism = makeRequest;

// merge in options
if (options) {
each(options, function(key, value){
Expand Down Expand Up @@ -351,6 +354,10 @@ var Raven = {
*/
isSetup: function() {
return isSetup();
},

setTransportMethod: function(transport) {
globalOptions.transportMechanism = transport;
}
};

Expand Down Expand Up @@ -712,13 +719,13 @@ function send(data) {
// Set lastEventId after we know the error should actually be sent
lastEventId = data.event_id || (data.event_id = uuid4());

makeRequest(data);
globalOptions.transportMechanism(data, globalServer, authQueryString);
}


function makeRequest(data) {
function makeRequest(data, server, authQueryString) {
var img = newImage(),
src = globalServer + authQueryString + '&sentry_data=' + encodeURIComponent(JSON.stringify(data));
src = server + authQueryString + '&sentry_data=' + encodeURIComponent(JSON.stringify(data));

img.crossOrigin = 'anonymous';
img.onload = function success() {
Expand Down
76 changes: 46 additions & 30 deletions test/raven.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -819,19 +819,20 @@ describe('globals', function() {

it('should build a good data payload', function() {
this.sinon.stub(window, 'isSetup').returns(true);
this.sinon.stub(window, 'makeRequest');
this.sinon.stub(window, 'getHttpData').returns({
url: 'http://localhost/?a=b',
headers: {'User-Agent': 'lolbrowser'}
});
var transportMechanism = this.sinon.stub();

globalProject = '2';
globalOptions = {
logger: 'javascript'
logger: 'javascript',
transportMechanism: transportMechanism
};

send({foo: 'bar'});
assert.deepEqual(window.makeRequest.lastCall.args[0], {
assert.deepEqual(transportMechanism.lastCall.args[0], {
project: '2',
logger: 'javascript',
platform: 'javascript',
Expand All @@ -849,21 +850,22 @@ describe('globals', function() {

it('should build a good data payload with a User', function() {
this.sinon.stub(window, 'isSetup').returns(true);
this.sinon.stub(window, 'makeRequest');
this.sinon.stub(window, 'getHttpData').returns({
url: 'http://localhost/?a=b',
headers: {'User-Agent': 'lolbrowser'}
});

var transportMechanism = this.sinon.stub();
globalProject = '2';
globalOptions = {
logger: 'javascript'
logger: 'javascript',
transportMechanism: transportMechanism
};

globalUser = {name: 'Matt'};

send({foo: 'bar'});
assert.deepEqual(window.makeRequest.lastCall.args, [{
assert.deepEqual(transportMechanism.lastCall.args[0], {
project: '2',
logger: 'javascript',
platform: 'javascript',
Expand All @@ -879,7 +881,7 @@ describe('globals', function() {
},
foo: 'bar',
extra: {'session:duration': 100}
}]);
});
});

it('should merge in global tags', function() {
Expand All @@ -890,15 +892,18 @@ describe('globals', function() {
headers: {'User-Agent': 'lolbrowser'}
});

var transportMechanism = this.sinon.stub();

globalProject = '2';
globalOptions = {
logger: 'javascript',
tags: {tag1: 'value1'}
tags: {tag1: 'value1'},
transportMechanism: transportMechanism
};


send({tags: {tag2: 'value2'}});
assert.deepEqual(window.makeRequest.lastCall.args, [{
assert.deepEqual(transportMechanism.lastCall.args[0], {
project: '2',
logger: 'javascript',
platform: 'javascript',
Expand All @@ -911,30 +916,33 @@ describe('globals', function() {
event_id: 'abc123',
tags: {tag1: 'value1', tag2: 'value2'},
extra: {'session:duration': 100}
}]);
});
assert.deepEqual(globalOptions, {
logger: 'javascript',
tags: {tag1: 'value1'}
tags: {tag1: 'value1'},
transportMechanism: transportMechanism
});
});

it('should merge in global extra', function() {
this.sinon.stub(window, 'isSetup').returns(true);
this.sinon.stub(window, 'makeRequest');
this.sinon.stub(window, 'getHttpData').returns({
url: 'http://localhost/?a=b',
headers: {'User-Agent': 'lolbrowser'}
});

var transportMechanism = this.sinon.stub();

globalProject = '2';
globalOptions = {
logger: 'javascript',
extra: {key1: 'value1'}
extra: {key1: 'value1'},
transportMechanism: transportMechanism
};


send({extra: {key2: 'value2'}});
assert.deepEqual(window.makeRequest.lastCall.args, [{
assert.deepEqual(transportMechanism.lastCall.args[0], {
project: '2',
logger: 'javascript',
platform: 'javascript',
Expand All @@ -946,50 +954,55 @@ describe('globals', function() {
},
event_id: 'abc123',
extra: {key1: 'value1', key2: 'value2', 'session:duration': 100}
}]);
});
assert.deepEqual(globalOptions, {
logger: 'javascript',
extra: {key1: 'value1'}
extra: {key1: 'value1'},
transportMechanism: transportMechanism
});
});

it('should let dataCallback override everything', function() {
this.sinon.stub(window, 'isSetup').returns(true);
this.sinon.stub(window, 'makeRequest');
var transportMechanism = this.sinon.stub();


globalOptions = {
projectId: 2,
logger: 'javascript',
dataCallback: function() {
return {lol: 'ibrokeit'};
}
},
transportMechanism: transportMechanism
};

globalUser = {name: 'Matt'};

send({foo: 'bar'});
assert.deepEqual(window.makeRequest.lastCall.args, [{
assert.deepEqual(transportMechanism.lastCall.args[0], {
lol: 'ibrokeit',
event_id: 'abc123',
}]);
});
});

it('should strip empty tags', function() {
this.sinon.stub(window, 'isSetup').returns(true);
this.sinon.stub(window, 'makeRequest');
this.sinon.stub(window, 'getHttpData').returns({
url: 'http://localhost/?a=b',
headers: {'User-Agent': 'lolbrowser'}
});

var transportMechanism = this.sinon.stub();

globalOptions = {
projectId: 2,
logger: 'javascript',
tags: {}
tags: {},
transportMechanism: transportMechanism
};

send({foo: 'bar', tags: {}, extra: {}});
assert.deepEqual(window.makeRequest.lastCall.args[0], {
assert.deepEqual(transportMechanism.lastCall.args[0], {
project: '2',
logger: 'javascript',
platform: 'javascript',
Expand All @@ -1007,20 +1020,22 @@ describe('globals', function() {

it('should attach release if available', function() {
this.sinon.stub(window, 'isSetup').returns(true);
this.sinon.stub(window, 'makeRequest');
this.sinon.stub(window, 'getHttpData').returns({
url: 'http://localhost/?a=b',
headers: {'User-Agent': 'lolbrowser'}
});

var makeRequestStub = this.sinon.stub();

globalOptions = {
projectId: 2,
logger: 'javascript',
release: 'abc123',
transportMechanism: makeRequestStub
};

send({foo: 'bar'});
assert.deepEqual(window.makeRequest.lastCall.args[0], {
assert.deepEqual(makeRequestStub.lastCall.args[0], {
project: '2',
release: 'abc123',
logger: 'javascript',
Expand All @@ -1040,12 +1055,12 @@ describe('globals', function() {

describe('makeRequest', function() {
it('should load an Image', function() {
authQueryString = '?lol';
globalServer = 'http://localhost/';
var authQueryString = '?lol';
var globalServer = 'http://localhost/';
var imageCache = [];
this.sinon.stub(window, 'newImage', function(){ var img = {}; imageCache.push(img); return img; });

makeRequest({foo: 'bar'});
makeRequest({foo: 'bar'}, globalServer, authQueryString);
assert.equal(imageCache.length, 1);
assert.equal(imageCache[0].src, 'http://localhost/?lol&sentry_data=%7B%22foo%22%3A%22bar%22%7D');
});
Expand Down Expand Up @@ -1074,7 +1089,8 @@ describe('globals', function() {
});

it('should work as advertised #integration', function() {
this.sinon.stub(window, 'makeRequest');
globalOptions.transportMechanism = this.sinon.stub();

var stackInfo = {
name: 'Error',
message: 'crap',
Expand Down Expand Up @@ -1107,7 +1123,7 @@ describe('globals', function() {
};

handleStackInfo(stackInfo, {foo: 'bar'});
assert.isTrue(window.makeRequest.calledOnce);
assert.isTrue(globalOptions.transportMechanism.calledOnce);
/* This is commented out because chai is broken.

assert.deepEqual(window.makeRequest.lastCall.args, [{
Expand Down