Skip to content

Commit

Permalink
Add opentracing integration (#860)
Browse files Browse the repository at this point in the history
* add lightstep integration

* separate validation of tracer + span b/c we dont always have an active span when validating tracer at client instantiation

* add item.custom data to custom field in browserjs implementation

* move tracer config to Client rather than each implementation

* revert spreading of data.custom attrs to root data obj in browserjs

* add item.data.custom to all occurrences for both nodejs and browserjs

* add item.data.custom for react-native too
  • Loading branch information
austenLacy authored Jun 2, 2020
1 parent 11634b6 commit 84bbcd7
Show file tree
Hide file tree
Showing 9 changed files with 398 additions and 109 deletions.
1 change: 0 additions & 1 deletion src/browser/rollbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ function Rollbar(options, client) {
this.options._configuredOptions = options;
var api = new API(this.options, transport, urllib);
this.client = client || new Client(this.options, api, logger, 'browser');

var gWindow = _gWindow();
var gDocument = (typeof document != 'undefined') && document;
this.isChrome = gWindow.chrome && gWindow.chrome.runtime; // check .runtime to avoid Edge browsers
Expand Down
3 changes: 2 additions & 1 deletion src/browser/transforms.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ function addBaseInfo(item, options, callback) {
notifier: {
name: 'rollbar-browser-js',
version: options.version
}
},
custom: item.custom
});
callback(null, item);
}
Expand Down
3 changes: 2 additions & 1 deletion src/react-native/transforms.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ function baseData(item, options, callback) {
language: 'javascript',
framework: item.framework || options.framework,
uuid: item.uuid,
notifier: JSON.parse(JSON.stringify(options.notifier))
notifier: JSON.parse(JSON.stringify(options.notifier)),
custom: item.custom
};

if (options.codeVersion) {
Expand Down
142 changes: 123 additions & 19 deletions src/rollbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,18 @@ function Rollbar(options, api, logger, platform) {
Rollbar.rateLimiter.setPlatformOptions(platform, this.options);
this.api = api;
this.queue = new Queue(Rollbar.rateLimiter, api, logger, this.options);

// This must happen before the Notifier is created
var tracer = this.options.tracer || null;
if (validateTracer(tracer)) {
this.tracer = tracer;
// set to a string for api response serialization
this.options.tracer = 'opentracing-tracer-enabled';
this.options._configuredOptions.tracer = 'opentracing-tracer-enabled';
} else {
this.tracer = null;
}

this.notifier = new Notifier(this.queue, this.options);
this.telemeter = new Telemeter(this.options);
setStackTraceLimit(options);
Expand All @@ -32,81 +44,99 @@ var defaultOptions = {

Rollbar.rateLimiter = new RateLimiter(defaultOptions);

Rollbar.prototype.global = function(options) {
Rollbar.prototype.global = function (options) {
Rollbar.rateLimiter.configureGlobal(options);
return this;
};

Rollbar.prototype.configure = function(options, payloadData) {
Rollbar.prototype.configure = function (options, payloadData) {
var oldOptions = this.options;
var payload = {};
if (payloadData) {
payload = {payload: payloadData};
payload = { payload: payloadData };
}

this.options = _.merge(oldOptions, options, payload);

// This must happen before the Notifier is configured
var tracer = this.options.tracer || null;
if (validateTracer(tracer)) {
this.tracer = tracer;
// set to a string for api response serialization
this.options.tracer = 'opentracing-tracer-enabled';
this.options._configuredOptions.tracer = 'opentracing-tracer-enabled';
} else {
this.tracer = null;
}

this.notifier && this.notifier.configure(this.options);
this.telemeter && this.telemeter.configure(this.options);
setStackTraceLimit(options);
this.global(this.options);

if (validateTracer(options.tracer)) {
this.tracer = options.tracer
}

return this;
};

Rollbar.prototype.log = function(item) {
Rollbar.prototype.log = function (item) {
var level = this._defaultLogLevel();
return this._log(level, item);
};

Rollbar.prototype.debug = function(item) {
Rollbar.prototype.debug = function (item) {
this._log('debug', item);
};

Rollbar.prototype.info = function(item) {
Rollbar.prototype.info = function (item) {
this._log('info', item);
};

Rollbar.prototype.warn = function(item) {
Rollbar.prototype.warn = function (item) {
this._log('warning', item);
};

Rollbar.prototype.warning = function(item) {
Rollbar.prototype.warning = function (item) {
this._log('warning', item);
};

Rollbar.prototype.error = function(item) {
Rollbar.prototype.error = function (item) {
this._log('error', item);
};

Rollbar.prototype.critical = function(item) {
Rollbar.prototype.critical = function (item) {
this._log('critical', item);
};

Rollbar.prototype.wait = function(callback) {
Rollbar.prototype.wait = function (callback) {
this.queue.wait(callback);
};

Rollbar.prototype.captureEvent = function(type, metadata, level) {
Rollbar.prototype.captureEvent = function (type, metadata, level) {
return this.telemeter.captureEvent(type, metadata, level);
};

Rollbar.prototype.captureDomContentLoaded = function(ts) {
Rollbar.prototype.captureDomContentLoaded = function (ts) {
return this.telemeter.captureDomContentLoaded(ts);
};

Rollbar.prototype.captureLoad = function(ts) {
Rollbar.prototype.captureLoad = function (ts) {
return this.telemeter.captureLoad(ts);
};

Rollbar.prototype.buildJsonPayload = function(item) {
Rollbar.prototype.buildJsonPayload = function (item) {
return this.api.buildJsonPayload(item);
};

Rollbar.prototype.sendJsonPayload = function(jsonPayload) {
Rollbar.prototype.sendJsonPayload = function (jsonPayload) {
this.api.postJsonPayload(jsonPayload);
};

/* Internal */

Rollbar.prototype._log = function(defaultLevel, item) {
Rollbar.prototype._log = function (defaultLevel, item) {
var callback;
if (item.callback) {
callback = item.callback;
Expand All @@ -121,6 +151,7 @@ Rollbar.prototype._log = function(defaultLevel, item) {
return;
}
try {
this._addTracingInfo(item);
item.level = item.level || defaultLevel;
this.telemeter._captureRollbarItem(item);
item.telemetryEvents = this.telemeter.copyEvents();
Expand All @@ -130,11 +161,11 @@ Rollbar.prototype._log = function(defaultLevel, item) {
}
};

Rollbar.prototype._defaultLogLevel = function() {
Rollbar.prototype._defaultLogLevel = function () {
return this.options.logLevel || 'debug';
};

Rollbar.prototype._sameAsLastError = function(item) {
Rollbar.prototype._sameAsLastError = function (item) {
if (!item._isUncaught) {
return false;
}
Expand All @@ -147,6 +178,34 @@ Rollbar.prototype._sameAsLastError = function(item) {
return false;
};

Rollbar.prototype._addTracingInfo = function (item) {
// Tracer validation occurs in the constructor
// or in the Rollbar.prototype.configure methods
if (this.tracer) {
// add rollbar occurrence uuid to span
var span = this.tracer.scope().active();

if (validateSpan(span)) {
span.setTag('rollbar_uuid', item.uuid);
span.setTag('has_rollbar_error', true);

// add span ID & trace ID to occurrence
var opentracingSpanId = span.context().toSpanId();
var opentracingTraceId = span.context().toTraceId();

if (item.custom) {
item.custom.opentracing_span_id = opentracingSpanId;
item.custom.opentracing_trace_id = opentracingTraceId;
} else {
item.custom = {
opentracing_span_id: opentracingSpanId,
opentracing_trace_id: opentracingTraceId
};
}
}
}
}

function generateItemHash(item) {
var message = item.message || '';
var stack = (item.err || {}).stack || String(item.err);
Expand All @@ -162,4 +221,49 @@ function setStackTraceLimit(options) {
}
}

/**
* Validate the Tracer object provided to the Client
* is valid for our Opentracing use case.
* @param {opentracer.Tracer} tracer
*/
function validateTracer(tracer) {
if (!tracer) {
return false;
}

if (!tracer.scope || typeof tracer.scope !== 'function') {
return false;
}

const scope = tracer.scope();

if (!scope || !scope.active || typeof scope.active !== 'function') {
return false;
}

return true;
}

/**
* Validate the Span object provided
* @param {opentracer.Span} span
*/
function validateSpan(span) {
if (!span || !span.context || typeof span.context !== 'function') {
return false;
}

const spanContext = span.context();

if (!spanContext
|| !spanContext.toSpanId
|| !spanContext.toTraceId
|| typeof spanContext.toSpanId !== 'function'
|| typeof spanContext.toTraceId !== 'function') {
return false
}

return true;
}

module.exports = Rollbar;
Loading

0 comments on commit 84bbcd7

Please sign in to comment.