Socket
Socket
Sign inDemoInstall

@elastic/apm-rum-core

Package Overview
Dependencies
Maintainers
57
Versions
51
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@elastic/apm-rum-core - npm Package Compare versions

Comparing version 4.1.1 to 4.2.0

dist/lib/env.js

21

CHANGELOG.md

@@ -6,2 +6,23 @@ # Change Log

# [4.2.0](https://github.com/elastic/apm-agent-rum-js/compare/@elastic/apm-rum-core@4.1.1...@elastic/apm-rum-core@4.2.0) (2019-07-08)
### Bug Fixes
* **rum-core:** remove sensitive info from span context ([#274](https://github.com/elastic/apm-agent-rum-js/issues/274)) ([b073f7f](https://github.com/elastic/apm-agent-rum-js/commit/b073f7f))
### Features
* **rum-core:** add user timing spans to the page-load transaction ([#276](https://github.com/elastic/apm-agent-rum-js/issues/276)) ([11a62f1](https://github.com/elastic/apm-agent-rum-js/commit/11a62f1))
### Performance Improvements
* **rum-core:** check span validition before creating arbitrary spans ([#277](https://github.com/elastic/apm-agent-rum-js/issues/277)) ([dcba903](https://github.com/elastic/apm-agent-rum-js/commit/dcba903))
## [4.1.1](https://github.com/elastic/apm-agent-rum-js/compare/@elastic/apm-rum-core@4.1.0...@elastic/apm-rum-core@4.1.1) (2019-06-20)

@@ -8,0 +29,0 @@

27

dist/lib/common/apm-server.js

@@ -16,2 +16,4 @@ "use strict";

var _env = require("../env");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

@@ -23,8 +25,2 @@

this._loggingService = loggingService;
this.logMessages = {
invalidConfig: {
message: 'RUM agent configuration is invalid!',
level: 'warn'
}
};
this.errorQueue = undefined;

@@ -195,12 +191,2 @@ this.transactionQueue = undefined;

warnOnce(logObject) {
if (logObject.level === 'warn') {
logObject.level = 'debug';
this._loggingService.warn(logObject.message);
} else {
this._loggingService.debug(logObject.message);
}
}
ndjsonErrors(errors) {

@@ -234,7 +220,2 @@ return errors.map(function (error) {

_send(data = [], type = 'transaction') {
if (!this._configService.isValid()) {
this.warnOnce(this.logMessages.invalidConfig);
return;
}
if (data.length === 0) {

@@ -269,3 +250,5 @@ return;

} else {
this._loggingService.debug('Dropped payload due to unknown data type ');
if (_env.__DEV__) {
this._loggingService.debug('Dropped payload due to unknown data type');
}

@@ -272,0 +255,0 @@ return;

@@ -125,4 +125,3 @@ "use strict";

getEndpointUrl() {
var url = this.get('serverUrl') + this.get('serverUrlPrefix');
return url;
return this.config.serverUrl + this.config.serverUrlPrefix;
}

@@ -191,2 +190,6 @@

setConfig(properties = {}) {
if (properties.serverUrl) {
properties.serverUrl = properties.serverUrl.replace(/\/+$/, '');
}
this.config = (0, _utils.merge)({}, this.defaults, this.config, properties);

@@ -201,14 +204,23 @@

isValid() {
validate(properties = {}) {
const requiredKeys = ['serviceName', 'serverUrl'];
const errors = {
missing: [],
invalid: []
};
Object.keys(properties).forEach(key => {
if (requiredKeys.indexOf(key) !== -1 && !properties[key]) {
errors.missing.push(key);
}
});
for (let i = 0; i < requiredKeys.length; i++) {
const key = requiredKeys[i];
if (this.config[key] == null || this.config[key] === '') {
return false;
}
if (properties.serviceName && !/^[a-zA-Z0-9 _-]+$/.test(properties.serviceName)) {
errors.invalid.push({
key: 'serviceName',
value: properties.serviceName,
allowed: 'a-z, A-Z, 0-9, _, -, <space>'
});
}
return true;
return errors;
}

@@ -215,0 +227,0 @@

"use strict";
exports.__esModule = true;
exports.KEYWORD_LIMIT = exports.TYPE_CUSTOM = exports.NAME_UNKNOWN = exports.PAGE_LOAD = exports.SPAN_THRESHOLD = exports.REUSABILITY_THRESHOLD = exports.HISTORY_PUSHSTATE = exports.RESOURCE_INITIATOR_TYPES = exports.REMOVE_EVENT_LISTENER_STR = exports.ADD_EVENT_LISTENER_STR = exports.XMLHTTPREQUEST_SOURCE = exports.FETCH_SOURCE = exports.CLEAR = exports.INVOKE = exports.SCHEDULE = void 0;
exports.KEYWORD_LIMIT = exports.USER_TIMING_THRESHOLD = exports.TYPE_CUSTOM = exports.NAME_UNKNOWN = exports.PAGE_LOAD = exports.MAX_SPAN_DURATION = exports.REUSABILITY_THRESHOLD = exports.RESOURCE_INITIATOR_TYPES = exports.REMOVE_EVENT_LISTENER_STR = exports.ADD_EVENT_LISTENER_STR = exports.HISTORY_PUSHSTATE = exports.XMLHTTPREQUEST_SOURCE = exports.FETCH_SOURCE = exports.CLEAR = exports.INVOKE = exports.SCHEDULE = void 0;
const SCHEDULE = 'schedule';

@@ -25,4 +25,4 @@ exports.SCHEDULE = SCHEDULE;

exports.REUSABILITY_THRESHOLD = REUSABILITY_THRESHOLD;
const SPAN_THRESHOLD = 5 * 60 * 1000;
exports.SPAN_THRESHOLD = SPAN_THRESHOLD;
const MAX_SPAN_DURATION = 5 * 60 * 1000;
exports.MAX_SPAN_DURATION = MAX_SPAN_DURATION;
const PAGE_LOAD = 'page-load';

@@ -34,3 +34,5 @@ exports.PAGE_LOAD = PAGE_LOAD;

exports.TYPE_CUSTOM = TYPE_CUSTOM;
const USER_TIMING_THRESHOLD = 60;
exports.USER_TIMING_THRESHOLD = USER_TIMING_THRESHOLD;
const KEYWORD_LIMIT = 1024;
exports.KEYWORD_LIMIT = KEYWORD_LIMIT;

@@ -5,3 +5,3 @@ "use strict";

exports.default = void 0;
const RULES = [['#', 'hash'], ['?', 'query'], ['/', 'path'], [NaN, 'host', 1]];
const RULES = [['#', 'hash'], ['?', 'query'], ['/', 'path'], ['@', 'auth', 1], [NaN, 'host', undefined, 1]];
const PROTOCOL_REGEX = /^([a-z][a-z0-9.+-]*:)?(\/\/)?([\S\s]*)/i;

@@ -31,4 +31,13 @@

if (~index) {
this[key] = address.slice(index);
address = address.slice(0, index);
const instLength = instruction[2];
if (instLength) {
let newIndex = address.lastIndexOf(parse);
index = Math.max(index, newIndex);
this[key] = address.slice(0, index);
address = address.slice(index + instLength);
} else {
this[key] = address.slice(index);
address = address.slice(0, index);
}
}

@@ -39,10 +48,31 @@ } else {

this[key] = this[key] || (relative && instruction[2] ? location[key] || '' : '');
if (instruction[2]) this[key] = this[key].toLowerCase();
this[key] = this[key] || (relative && instruction[3] ? location[key] || '' : '');
if (instruction[3]) this[key] = this[key].toLowerCase();
}
this.relative = relative;
this.protocol = protocol || location.protocol || '';
this.origin = this.protocol && this.host && this.protocol !== 'file:' ? this.protocol + '//' + this.host : 'null';
this.href = this.toString();
}
toString() {
let result = this.protocol;
result += '//';
if (this.auth) {
const REDACTED = '[REDACTED]';
const userpass = this.auth.split(':');
const username = userpass[0] ? REDACTED : '';
const password = userpass[1] ? ':' + REDACTED : '';
result += username + password + '@';
}
result += this.host;
result += this.path;
result += this.query;
result += this.hash;
return result;
}
getLocation() {

@@ -49,0 +79,0 @@ var globalVar = {};

@@ -33,4 +33,2 @@ "use strict";

var _url = _interopRequireDefault(require("../common/url"));
var _rngBrowser = _interopRequireDefault(require("uuid/lib/rng-browser"));

@@ -95,5 +93,3 @@

if (typeof target === 'string') {
const src = new _url.default(source);
const tar = new _url.default(target);
isSame = src.origin === tar.origin;
isSame = source === target;
} else if (Array.isArray(target)) {

@@ -100,0 +96,0 @@ target.forEach(function (t) {

@@ -75,18 +75,16 @@ "use strict";

logErrorEvent(errorEvent, sendImmediately) {
if (this._configService.isActive()) {
if (typeof errorEvent === 'undefined') {
return;
}
if (typeof errorEvent === 'undefined') {
return;
}
const errorObject = this.createErrorDataModel(errorEvent);
var errorObject = this.createErrorDataModel(errorEvent);
if (typeof errorObject.exception.message === 'undefined') {
return;
}
if (typeof errorObject.exception.message === 'undefined') {
return;
}
if (sendImmediately) {
return this._apmServer.sendErrors([errorObject]);
} else {
return this._apmServer.addError(errorObject);
}
if (sendImmediately) {
return this._apmServer.sendErrors([errorObject]);
} else {
return this._apmServer.addError(errorObject);
}

@@ -93,0 +91,0 @@ }

@@ -14,2 +14,4 @@ "use strict";

var _env = require("../env");
var _span2 = _interopRequireDefault(require("./span"));

@@ -38,3 +40,5 @@

if (options.references.length > 1) {
this.loggingService.debug('Elastic APM OpenTracing: Unsupported number of references, only the first childOf reference will be recorded.');
if (_env.__DEV__) {
this.loggingService.debug('Elastic APM OpenTracing: Unsupported number of references, only the first childOf reference will be recorded.');
}
}

@@ -86,3 +90,6 @@

case _constants.FORMAT_BINARY:
this.loggingService.debug('Elastic APM OpenTracing: binary carrier format is not supported.');
if (_env.__DEV__) {
this.loggingService.debug('Elastic APM OpenTracing: binary carrier format is not supported.');
}
break;

@@ -102,3 +109,6 @@ }

case _constants.FORMAT_BINARY:
this.loggingService.debug('Elastic APM OpenTracing: binary carrier format is not supported.');
if (_env.__DEV__) {
this.loggingService.debug('Elastic APM OpenTracing: binary carrier format is not supported.');
}
break;

@@ -105,0 +115,0 @@ }

@@ -7,2 +7,3 @@ "use strict";

exports.createResourceTimingSpans = createResourceTimingSpans;
exports.createUserTimingSpans = createUserTimingSpans;

@@ -19,12 +20,7 @@ var _span = _interopRequireDefault(require("./span"));

function isValidSpan(transaction, span) {
const duration = span.duration();
return duration < _constants.SPAN_THRESHOLD && duration > 0 && span._start <= transaction._end && span._end <= transaction._end;
function shouldCreateSpan(start, end, baseTime, transactionEnd) {
return typeof start === 'number' && typeof end === 'number' && start >= baseTime && end > start && end - baseTime <= transactionEnd && end - start < _constants.MAX_SPAN_DURATION && start - baseTime < _constants.MAX_SPAN_DURATION && end - baseTime < _constants.MAX_SPAN_DURATION;
}
function isValidPerformanceTiming(start, end, baseTime = 0) {
return typeof start === 'number' && typeof end === 'number' && start >= baseTime && end > start && end - start < _constants.SPAN_THRESHOLD && start - baseTime < _constants.SPAN_THRESHOLD && end - baseTime < _constants.SPAN_THRESHOLD;
}
function createNavigationTimingSpans(timings, baseTime) {
function createNavigationTimingSpans(timings, baseTime, transactionEnd) {
const spans = [];

@@ -36,3 +32,3 @@

if (!isValidPerformanceTiming(start, end, baseTime)) {
if (!shouldCreateSpan(start, end, baseTime, transactionEnd)) {
continue;

@@ -71,3 +67,3 @@ }

span._start = start;
span.ended = true;
span.end();
span._end = end;

@@ -77,3 +73,3 @@ return span;

function createResourceTimingSpans(entries, filterUrls) {
function createResourceTimingSpans(entries, filterUrls, transactionEnd) {
const spans = [];

@@ -91,7 +87,9 @@

continue;
} else if (!isValidPerformanceTiming(startTime, responseEnd)) {
continue;
}
if (_constants.RESOURCE_INITIATOR_TYPES.indexOf(initiatorType) !== -1) {
if (!shouldCreateSpan(startTime, responseEnd, 0, transactionEnd)) {
continue;
}
spans.push(createResourceTimingSpan(name, initiatorType, startTime, responseEnd));

@@ -114,3 +112,3 @@ } else {

if (!foundAjaxReq) {
if (!foundAjaxReq && shouldCreateSpan(startTime, responseEnd, 0, transactionEnd)) {
spans.push(createResourceTimingSpan(name, initiatorType, startTime, responseEnd));

@@ -124,2 +122,28 @@ }

function createUserTimingSpans(entries, transactionEnd) {
const userTimingSpans = [];
for (let i = 0; i < entries.length; i++) {
const {
name,
startTime,
duration
} = entries[i];
const end = startTime + duration;
if (duration <= _constants.USER_TIMING_THRESHOLD || !shouldCreateSpan(startTime, end, 0, transactionEnd)) {
continue;
}
const kind = 'app';
const span = new _span.default(name, kind);
span._start = startTime;
span.end();
span._end = end;
userTimingSpans.push(span);
}
return userTimingSpans;
}
function captureHardNavigation(transaction) {

@@ -139,17 +163,16 @@ const perf = window.performance;

transaction._start = 0;
createNavigationTimingSpans(timings, timings.fetchStart).forEach(function (span) {
if (isValidSpan(transaction, span)) {
span.traceId = transaction.traceId;
span.sampled = transaction.sampled;
const transactionEnd = transaction._end;
createNavigationTimingSpans(timings, timings.fetchStart, transactionEnd).forEach(span => {
span.traceId = transaction.traceId;
span.sampled = transaction.sampled;
if (transaction.options.pageLoadSpanId && span.pageResponse) {
span.id = transaction.options.pageLoadSpanId;
}
if (span.pageResponse && transaction.options.pageLoadSpanId) {
span.id = transaction.options.pageLoadSpanId;
}
transaction.spans.push(span);
}
transaction.spans.push(span);
});
if (typeof perf.getEntriesByType === 'function') {
const entries = perf.getEntriesByType('resource');
const resourceEntries = perf.getEntriesByType('resource');
const ajaxUrls = [];

@@ -167,9 +190,7 @@

createResourceTimingSpans(entries, ajaxUrls).forEach(function (span) {
if (isValidSpan(transaction, span)) {
transaction.spans.push(span);
}
});
createResourceTimingSpans(resourceEntries, ajaxUrls, transactionEnd).forEach(span => transaction.spans.push(span));
const userEntries = perf.getEntriesByType('measure');
createUserTimingSpans(userEntries, transactionEnd).forEach(span => transaction.spans.push(span));
}
}
}

@@ -8,2 +8,4 @@ "use strict";

var _url = _interopRequireDefault(require("../common/url"));
var _patching = require("../common/patching");

@@ -17,2 +19,6 @@

var _env = require("../env");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
class PerformanceMonitoring {

@@ -46,26 +52,30 @@ constructor(apmServer, configService, loggingService, transactionService) {

if (event === _constants.SCHEDULE && task.data) {
var spanName = task.data.method + ' ' + (0, _utils.stripQueryStringFromUrl)(task.data.url);
var span = transactionService.startSpan(spanName, 'external.http');
var taskId = transactionService.addTask();
const requestUrl = new _url.default(task.data.url);
const spanName = task.data.method + ' ' + (requestUrl.relative ? requestUrl.path : (0, _utils.stripQueryStringFromUrl)(requestUrl.href));
const span = transactionService.startSpan(spanName, 'external.http');
const taskId = transactionService.addTask();
if (span) {
var isDtEnabled = configService.get('distributedTracing');
var origins = configService.get('distributedTracingOrigins');
var isSameOrigin = (0, _utils.checkSameOrigin)(task.data.url, window.location.href) || (0, _utils.checkSameOrigin)(task.data.url, origins);
var target = task.data.target;
if (!span) {
return;
}
if (isDtEnabled && isSameOrigin && target) {
pm.injectDtHeader(span, target);
}
const isDtEnabled = configService.get('distributedTracing');
const dtOrigins = configService.get('distributedTracingOrigins');
const currentUrl = new _url.default(window.location.href);
const isSameOrigin = (0, _utils.checkSameOrigin)(requestUrl.origin, currentUrl.origin) || (0, _utils.checkSameOrigin)(requestUrl.origin, dtOrigins);
const target = task.data.target;
span.addContext({
http: {
method: task.data.method,
url: task.data.url
}
});
span.sync = task.data.sync;
task.data.span = span;
task.id = taskId;
if (isDtEnabled && isSameOrigin && target) {
pm.injectDtHeader(span, target);
}
span.addContext({
http: {
method: task.data.method,
url: requestUrl.href
}
});
span.sync = task.data.sync;
task.data.span = span;
task.id = taskId;
}

@@ -96,3 +106,3 @@

if (event === _constants.INVOKE && task.source === _constants.HISTORY_PUSHSTATE) {
if (task.source === _constants.HISTORY_PUSHSTATE && event === _constants.INVOKE) {
transactionService.startTransaction(task.data.title, 'route-change', {

@@ -165,3 +175,5 @@ canReuse: true

if (!wasBrowserResponsive) {
performanceMonitoring._logginService.debug('Transaction was discarded! browser was not responsive enough during the transaction.', ' duration:', duration, ' browserResponsivenessCounter:', tr.browserResponsivenessCounter, 'interval:', browserResponsivenessInterval);
if (_env.__DEV__) {
performanceMonitoring._logginService.debug('Transaction was discarded! browser was not responsive enough during the transaction.', ' duration:', duration, ' browserResponsivenessCounter:', tr.browserResponsivenessCounter, 'interval:', browserResponsivenessInterval);
}

@@ -217,3 +229,3 @@ return false;

transaction.spans = transaction.spans.filter(function (span) {
return span.duration() > 0 && span._start >= transaction._start && span._end > transaction._start && span._start < transaction._end && span._end <= transaction._end;
return span.duration() > 0 && span._start >= transaction._start && span._end <= transaction._end;
});

@@ -275,3 +287,5 @@ this.setTransactionContext(transaction);

this._logginService.debug('Sending Transactions to apm server.', transactions.length);
if (_env.__DEV__) {
this._logginService.debug('Sending Transactions to apm server.', transactions.length);
}

@@ -278,0 +292,0 @@ const promise = this._apmServer.sendTransactions(payload);

@@ -11,3 +11,11 @@ "use strict";

class SpanBase {
constructor(name = _constants.NAME_UNKNOWN, type = _constants.TYPE_CUSTOM, options = {}) {
constructor(name, type, options = {}) {
if (!name) {
name = _constants.NAME_UNKNOWN;
}
if (!type) {
type = _constants.TYPE_CUSTOM;
}
this.options = options;

@@ -14,0 +22,0 @@ this.name = name;

@@ -16,2 +16,4 @@ "use strict";

var _env = require("../env");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

@@ -21,3 +23,3 @@

constructor(logger, config) {
if (typeof config === 'undefined') {
if (_env.__DEV__ && typeof config === 'undefined') {
logger.debug('TransactionService: config is not provided');

@@ -75,3 +77,5 @@ }

if (typeof interval === 'undefined') {
this._logger.debug('browserResponsivenessInterval is undefined!');
if (_env.__DEV__) {
this._logger.debug('browserResponsivenessInterval is undefined!');
}

@@ -115,11 +119,2 @@ return;

const perfOptions = this.createPerfOptions(options);
if (!type) {
type = _constants.TYPE_CUSTOM;
}
if (!name) {
name = _constants.NAME_UNKNOWN;
}
var tr = this.getCurrentTransaction();

@@ -130,7 +125,11 @@

} else if (tr.canReuse()) {
this._logger.debug('Redefining the current transaction', tr, name, type, perfOptions);
if (_env.__DEV__) {
this._logger.debug('Redefining the current transaction', tr, name, type, perfOptions);
}
tr.redefine(name, type, perfOptions);
} else {
this._logger.debug('Ending old transaction', tr);
if (_env.__DEV__) {
this._logger.debug('Ending old transaction', tr);
}

@@ -157,7 +156,11 @@ tr.end();

this._logger.debug('TransactionService.startTransaction', tr);
if (_env.__DEV__) {
this._logger.debug('TransactionService.startTransaction', tr);
}
tr.onEnd = () => {
return Promise.resolve().then(() => {
this._logger.debug('TransactionService transaction finished', tr);
if (_env.__DEV__) {
this._logger.debug('TransactionService transaction finished', tr);
}

@@ -183,3 +186,7 @@ if (this.shouldIgnoreTransaction(tr.name)) {

}
}, err => this._logger.debug(err));
}, err => {
if (_env.__DEV__) {
this._logger.debug('TransactionService transaction onEnd', err);
}
});
};

@@ -212,3 +219,5 @@

if (trans) {
this._logger.debug('TransactionService.startSpan', name, type);
if (_env.__DEV__) {
this._logger.debug('TransactionService.startSpan', name, type);
}

@@ -223,3 +232,5 @@ var span = trans.startSpan(name, type, options);

this._logger.debug('TransactionService.add', transaction);
if (_env.__DEV__) {
this._logger.debug('TransactionService.add', transaction);
}
}

@@ -237,3 +248,5 @@

this._logger.debug('TransactionService.addTask', taskId);
if (_env.__DEV__) {
this._logger.debug('TransactionService.addTask', taskId);
}
}

@@ -250,3 +263,5 @@

this._logger.debug('TransactionService.removeTask', taskId);
if (_env.__DEV__) {
this._logger.debug('TransactionService.removeTask', taskId);
}
}

@@ -261,3 +276,5 @@ }

this._logger.debug('TransactionService.detectFinish');
if (_env.__DEV__) {
this._logger.debug('TransactionService.detectFinish');
}
}

@@ -264,0 +281,0 @@ }

{
"name": "@elastic/apm-rum-core",
"version": "4.1.1",
"version": "4.2.0",
"description": "Elastic apm core",

@@ -39,3 +39,3 @@ "license": "MIT",

},
"gitHead": "b57be6f7052233fc421f8699ad185d8e367ca57a"
"gitHead": "683e9370a8b9bff20f8863f93e20a9a421bfc2f0"
}

@@ -31,2 +31,3 @@ /**

import { truncateModel, METADATA_MODEL } from './truncate'
import { __DEV__ } from '../env'

@@ -37,8 +38,2 @@ class ApmServer {

this._loggingService = loggingService
this.logMessages = {
invalidConfig: {
message: 'RUM agent configuration is invalid!',
level: 'warn'
}
}

@@ -199,11 +194,2 @@ this.errorQueue = undefined

warnOnce(logObject) {
if (logObject.level === 'warn') {
logObject.level = 'debug'
this._loggingService.warn(logObject.message)
} else {
this._loggingService.debug(logObject.message)
}
}
ndjsonErrors(errors) {

@@ -233,6 +219,2 @@ return errors.map(function(error) {

_send(data = [], type = 'transaction') {
if (!this._configService.isValid()) {
this.warnOnce(this.logMessages.invalidConfig)
return
}
if (data.length === 0) {

@@ -257,3 +239,5 @@ return

} else {
this._loggingService.debug('Dropped payload due to unknown data type ')
if (__DEV__) {
this._loggingService.debug('Dropped payload due to unknown data type')
}
return

@@ -260,0 +244,0 @@ }

@@ -157,4 +157,3 @@ /**

getEndpointUrl() {
var url = this.get('serverUrl') + this.get('serverUrlPrefix')
return url
return this.config.serverUrl + this.config.serverUrlPrefix
}

@@ -213,2 +212,12 @@

setConfig(properties = {}) {
/**
* Normalize config
*
* Remove all trailing slash for serverUrl since serverUrlPrefix
* includes a forward slash for the path
*/
if (properties.serverUrl) {
properties.serverUrl = properties.serverUrl.replace(/\/+$/, '')
}
this.config = merge({}, this.defaults, this.config, properties)

@@ -222,13 +231,35 @@ this._changeSubscription.applyAll(this, [this.config])

isValid() {
/**
* Validate the config aganist the required parameters and
* generates error messages with missing and invalid keys
*/
validate(properties = {}) {
const requiredKeys = ['serviceName', 'serverUrl']
for (let i = 0; i < requiredKeys.length; i++) {
const key = requiredKeys[i]
if (this.config[key] == null || this.config[key] === '') {
return false
const errors = {
missing: [],
invalid: []
}
/**
* Check when required keys are missing
*/
Object.keys(properties).forEach(key => {
if (requiredKeys.indexOf(key) !== -1 && !properties[key]) {
errors.missing.push(key)
}
})
/**
* Invalid values on the config
*/
if (
properties.serviceName &&
!/^[a-zA-Z0-9 _-]+$/.test(properties.serviceName)
) {
errors.invalid.push({
key: 'serviceName',
value: properties.serviceName,
allowed: 'a-z, A-Z, 0-9, _, -, <space>'
})
}
return true
return errors
}

@@ -235,0 +266,0 @@ }

@@ -72,3 +72,3 @@ /**

*/
const SPAN_THRESHOLD = 5 * 60 * 1000
const MAX_SPAN_DURATION = 5 * 60 * 1000

@@ -83,2 +83,7 @@ /**

/**
* Check only for long tasks that are more than 60ms
*/
const USER_TIMING_THRESHOLD = 60
/**
* Others

@@ -94,12 +99,13 @@ */

XMLHTTPREQUEST_SOURCE,
HISTORY_PUSHSTATE,
ADD_EVENT_LISTENER_STR,
REMOVE_EVENT_LISTENER_STR,
RESOURCE_INITIATOR_TYPES,
HISTORY_PUSHSTATE,
REUSABILITY_THRESHOLD,
SPAN_THRESHOLD,
MAX_SPAN_DURATION,
PAGE_LOAD,
NAME_UNKNOWN,
TYPE_CUSTOM,
USER_TIMING_THRESHOLD,
KEYWORD_LIMIT
}

@@ -48,2 +48,10 @@ /**

/**
* Order of the RULES are very important
*
* RULE[0] -> for checking the index of the character on the URL
* RULE[1] -> key to store the associated value present after the RULE[0]
* RULE[2] -> Extract from the front till the last index
* RULE[3] -> Left over values of the URL
*/
const RULES = [

@@ -53,3 +61,4 @@ ['#', 'hash'],

['/', 'path'],
[NaN, 'host', 1] //
['@', 'auth', 1],
[NaN, 'host', undefined, 1] //
]

@@ -76,4 +85,20 @@ const PROTOCOL_REGEX = /^([a-z][a-z0-9.+-]*:)?(\/\/)?([\S\s]*)/i

if (~index) {
this[key] = address.slice(index)
address = address.slice(0, index)
const instLength = instruction[2]
if (instLength) {
/**
* we need to figure out the explicit index where the auth portion
* in the host ends before parsing the rest of the URL as host.
*
* ex: http://a@b@c.com/d
* auth -> a@b
* host -> c.com
*/
let newIndex = address.lastIndexOf(parse)
index = Math.max(index, newIndex)
this[key] = address.slice(0, index)
address = address.slice(index + instLength)
} else {
this[key] = address.slice(index)
address = address.slice(0, index)
}
}

@@ -88,3 +113,3 @@ } else {

this[key] =
this[key] || (relative && instruction[2] ? location[key] || '' : '')
this[key] || (relative && instruction[3] ? location[key] || '' : '')
/**

@@ -94,5 +119,7 @@ * host should be lowercased so they can be used to

*/
if (instruction[2]) this[key] = this[key].toLowerCase()
if (instruction[3]) this[key] = this[key].toLowerCase()
}
this.relative = relative
this.protocol = protocol || location.protocol || ''

@@ -104,4 +131,23 @@

: 'null'
this.href = this.toString()
}
toString() {
let result = this.protocol
result += '//'
if (this.auth) {
const REDACTED = '[REDACTED]'
const userpass = this.auth.split(':')
const username = userpass[0] ? REDACTED : ''
const password = userpass[1] ? ':' + REDACTED : ''
result += username + password + '@'
}
result += this.host
result += this.path
result += this.query
result += this.hash
return result
}
getLocation() {

@@ -108,0 +154,0 @@ var globalVar = {}

@@ -26,3 +26,2 @@ /**

import Url from '../common/url'
import rng from 'uuid/lib/rng-browser'

@@ -108,5 +107,3 @@

if (typeof target === 'string') {
const src = new Url(source)
const tar = new Url(target)
isSame = src.origin === tar.origin
isSame = source === target
} else if (Array.isArray(target)) {

@@ -113,0 +110,0 @@ target.forEach(function(t) {

@@ -97,16 +97,14 @@ /**

logErrorEvent(errorEvent, sendImmediately) {
if (this._configService.isActive()) {
if (typeof errorEvent === 'undefined') {
return
}
const errorObject = this.createErrorDataModel(errorEvent)
if (typeof errorObject.exception.message === 'undefined') {
return
}
if (sendImmediately) {
return this._apmServer.sendErrors([errorObject])
} else {
return this._apmServer.addError(errorObject)
}
if (typeof errorEvent === 'undefined') {
return
}
var errorObject = this.createErrorDataModel(errorEvent)
if (typeof errorObject.exception.message === 'undefined') {
return
}
if (sendImmediately) {
return this._apmServer.sendErrors([errorObject])
} else {
return this._apmServer.addError(errorObject)
}
}

@@ -113,0 +111,0 @@

@@ -35,2 +35,3 @@ /**

import { getTimeOrigin, find } from '../common/utils'
import { __DEV__ } from '../env'
import Span from './span'

@@ -60,6 +61,8 @@

if (options.references.length > 1) {
this.loggingService.debug(
// eslint-disable-next-line
'Elastic APM OpenTracing: Unsupported number of references, only the first childOf reference will be recorded.'
)
if (__DEV__) {
this.loggingService.debug(
// eslint-disable-next-line
'Elastic APM OpenTracing: Unsupported number of references, only the first childOf reference will be recorded.'
)
}
}

@@ -110,5 +113,7 @@

case FORMAT_BINARY:
this.loggingService.debug(
'Elastic APM OpenTracing: binary carrier format is not supported.'
)
if (__DEV__) {
this.loggingService.debug(
'Elastic APM OpenTracing: binary carrier format is not supported.'
)
}
break

@@ -126,5 +131,7 @@ }

case FORMAT_BINARY:
this.loggingService.debug(
'Elastic APM OpenTracing: binary carrier format is not supported.'
)
if (__DEV__) {
this.loggingService.debug(
'Elastic APM OpenTracing: binary carrier format is not supported.'
)
}
break

@@ -131,0 +138,0 @@ }

@@ -27,3 +27,7 @@ /**

import Span from './span'
import { RESOURCE_INITIATOR_TYPES, SPAN_THRESHOLD } from '../common/constants'
import {
RESOURCE_INITIATOR_TYPES,
MAX_SPAN_DURATION,
USER_TIMING_THRESHOLD
} from '../common/constants'
import { stripQueryStringFromUrl } from '../common/utils'

@@ -55,14 +59,13 @@

function isValidSpan(transaction, span) {
const duration = span.duration()
/**
* start, end, baseTime - unsigned long long(PerformanceTiming)
* representing the moment, in milliseconds since the UNIX epoch
*
* transactionEnd - DOMHighResTimeStamp, measured in milliseconds.
*
* We have to convert the long values in milliseconds before doing the comparision
* eg: end - baseTime <= transactionEnd
*/
function shouldCreateSpan(start, end, baseTime, transactionEnd) {
return (
duration < SPAN_THRESHOLD &&
duration > 0 &&
span._start <= transaction._end &&
span._end <= transaction._end
)
}
function isValidPerformanceTiming(start, end, baseTime = 0) {
return (
typeof start === 'number' &&

@@ -72,9 +75,10 @@ typeof end === 'number' &&

end > start &&
end - start < SPAN_THRESHOLD &&
start - baseTime < SPAN_THRESHOLD &&
end - baseTime < SPAN_THRESHOLD
end - baseTime <= transactionEnd &&
end - start < MAX_SPAN_DURATION &&
start - baseTime < MAX_SPAN_DURATION &&
end - baseTime < MAX_SPAN_DURATION
)
}
function createNavigationTimingSpans(timings, baseTime) {
function createNavigationTimingSpans(timings, baseTime, transactionEnd) {
const spans = []

@@ -85,3 +89,3 @@ for (let i = 0; i < eventPairs.length; i++) {

if (!isValidPerformanceTiming(start, end, baseTime)) {
if (!shouldCreateSpan(start, end, baseTime, transactionEnd)) {
continue

@@ -110,3 +114,3 @@ }

span._start = start
span.ended = true
span.end()
span._end = end

@@ -116,3 +120,3 @@ return span

function createResourceTimingSpans(entries, filterUrls) {
function createResourceTimingSpans(entries, filterUrls, transactionEnd) {
const spans = []

@@ -130,6 +134,3 @@ for (let i = 0; i < entries.length; i++) {

continue
} else if (!isValidPerformanceTiming(startTime, responseEnd)) {
continue
}
/**

@@ -139,2 +140,5 @@ * Create spans for all known resource initiator types

if (RESOURCE_INITIATOR_TYPES.indexOf(initiatorType) !== -1) {
if (!shouldCreateSpan(startTime, responseEnd, 0, transactionEnd)) {
continue
}
spans.push(

@@ -169,3 +173,6 @@ createResourceTimingSpan(name, initiatorType, startTime, responseEnd)

*/
if (!foundAjaxReq) {
if (
!foundAjaxReq &&
shouldCreateSpan(startTime, responseEnd, 0, transactionEnd)
) {
spans.push(

@@ -180,2 +187,25 @@ createResourceTimingSpan(name, initiatorType, startTime, responseEnd)

function createUserTimingSpans(entries, transactionEnd) {
const userTimingSpans = []
for (let i = 0; i < entries.length; i++) {
const { name, startTime, duration } = entries[i]
const end = startTime + duration
if (
duration <= USER_TIMING_THRESHOLD ||
!shouldCreateSpan(startTime, end, 0, transactionEnd)
) {
continue
}
const kind = 'app'
const span = new Span(name, kind)
span._start = startTime
span.end()
span._end = end
userTimingSpans.push(span)
}
return userTimingSpans
}
function captureHardNavigation(transaction) {

@@ -195,17 +225,25 @@ const perf = window.performance

createNavigationTimingSpans(timings, timings.fetchStart).forEach(function(
span
) {
if (isValidSpan(transaction, span)) {
span.traceId = transaction.traceId
span.sampled = transaction.sampled
if (transaction.options.pageLoadSpanId && span.pageResponse) {
span.id = transaction.options.pageLoadSpanId
}
transaction.spans.push(span)
/**
* Threshold that decides if the span must be
* captured as part of the page load transaction
*
* Denotes the time when the onload event fires
*/
const transactionEnd = transaction._end
createNavigationTimingSpans(
timings,
timings.fetchStart,
transactionEnd
).forEach(span => {
span.traceId = transaction.traceId
span.sampled = transaction.sampled
if (span.pageResponse && transaction.options.pageLoadSpanId) {
span.id = transaction.options.pageLoadSpanId
}
transaction.spans.push(span)
})
if (typeof perf.getEntriesByType === 'function') {
const entries = perf.getEntriesByType('resource')
const resourceEntries = perf.getEntriesByType('resource')

@@ -221,7 +259,12 @@ const ajaxUrls = []

}
createResourceTimingSpans(entries, ajaxUrls).forEach(function(span) {
if (isValidSpan(transaction, span)) {
transaction.spans.push(span)
}
})
createResourceTimingSpans(
resourceEntries,
ajaxUrls,
transactionEnd
).forEach(span => transaction.spans.push(span))
const userEntries = perf.getEntriesByType('measure')
createUserTimingSpans(userEntries, transactionEnd).forEach(span =>
transaction.spans.push(span)
)
}

@@ -234,3 +277,4 @@ }

createNavigationTimingSpans,
createResourceTimingSpans
createResourceTimingSpans,
createUserTimingSpans
}

@@ -30,7 +30,8 @@ /**

merge,
stripQueryStringFromUrl,
parseDtHeaderValue,
getEarliestSpan,
stripQueryStringFromUrl,
getLatestNonXHRSpan
} from '../common/utils'
import Url from '../common/url'
import { patchSubscription } from '../common/patching'

@@ -50,2 +51,3 @@ import { globalState } from '../common/patching/patch-utils'

} from '../common/truncate'
import { __DEV__ } from '../env'

@@ -86,27 +88,34 @@ class PerformanceMonitoring {

if (event === SCHEDULE && task.data) {
var spanName =
task.data.method + ' ' + stripQueryStringFromUrl(task.data.url)
var span = transactionService.startSpan(spanName, 'external.http')
var taskId = transactionService.addTask()
const requestUrl = new Url(task.data.url)
const spanName =
task.data.method +
' ' +
(requestUrl.relative
? requestUrl.path
: stripQueryStringFromUrl(requestUrl.href))
const span = transactionService.startSpan(spanName, 'external.http')
const taskId = transactionService.addTask()
if (span) {
var isDtEnabled = configService.get('distributedTracing')
var origins = configService.get('distributedTracingOrigins')
var isSameOrigin =
checkSameOrigin(task.data.url, window.location.href) ||
checkSameOrigin(task.data.url, origins)
var target = task.data.target
if (isDtEnabled && isSameOrigin && target) {
pm.injectDtHeader(span, target)
if (!span) {
return
}
const isDtEnabled = configService.get('distributedTracing')
const dtOrigins = configService.get('distributedTracingOrigins')
const currentUrl = new Url(window.location.href)
const isSameOrigin =
checkSameOrigin(requestUrl.origin, currentUrl.origin) ||
checkSameOrigin(requestUrl.origin, dtOrigins)
const target = task.data.target
if (isDtEnabled && isSameOrigin && target) {
pm.injectDtHeader(span, target)
}
span.addContext({
http: {
method: task.data.method,
url: requestUrl.href
}
span.addContext({
http: {
method: task.data.method,
url: task.data.url
}
})
span.sync = task.data.sync
task.data.span = span
task.id = taskId
}
})
span.sync = task.data.sync
task.data.span = span
task.id = taskId
}

@@ -131,3 +140,3 @@ if (event === INVOKE && task.data && task.data.span) {

if (event === INVOKE && task.source === HISTORY_PUSHSTATE) {
if (task.source === HISTORY_PUSHSTATE && event === INVOKE) {
transactionService.startTransaction(task.data.title, 'route-change', {

@@ -219,11 +228,13 @@ canReuse: true

if (!wasBrowserResponsive) {
performanceMonitoring._logginService.debug(
'Transaction was discarded! browser was not responsive enough during the transaction.',
' duration:',
duration,
' browserResponsivenessCounter:',
tr.browserResponsivenessCounter,
'interval:',
browserResponsivenessInterval
)
if (__DEV__) {
performanceMonitoring._logginService.debug(
'Transaction was discarded! browser was not responsive enough during the transaction.',
' duration:',
duration,
' browserResponsivenessCounter:',
tr.browserResponsivenessCounter,
'interval:',
browserResponsivenessInterval
)
}
return false

@@ -290,4 +301,2 @@ }

span._start >= transaction._start &&
span._end > transaction._start &&
span._start < transaction._end &&
span._end <= transaction._end

@@ -355,6 +364,8 @@ )

this._logginService.debug(
'Sending Transactions to apm server.',
transactions.length
)
if (__DEV__) {
this._logginService.debug(
'Sending Transactions to apm server.',
transactions.length
)
}

@@ -361,0 +372,0 @@ // todo: check if transactions are already being sent

@@ -32,3 +32,12 @@ /**

constructor(name = NAME_UNKNOWN, type = TYPE_CUSTOM, options = {}) {
constructor(name, type, options = {}) {
/**
* Check for undefined and empty string
*/
if (!name) {
name = NAME_UNKNOWN
}
if (!type) {
type = TYPE_CUSTOM
}
this.options = options

@@ -35,0 +44,0 @@ this.name = name

@@ -28,9 +28,10 @@ /**

import { extend, getPageLoadMarks } from '../common/utils'
import { PAGE_LOAD, NAME_UNKNOWN, TYPE_CUSTOM } from '../common/constants'
import { PAGE_LOAD, NAME_UNKNOWN } from '../common/constants'
import Subscription from '../common/subscription'
import { captureHardNavigation } from './capture-hard-navigation'
import { __DEV__ } from '../env'
class TransactionService {
constructor(logger, config) {
if (typeof config === 'undefined') {
if (__DEV__ && typeof config === 'undefined') {
logger.debug('TransactionService: config is not provided')

@@ -81,3 +82,5 @@ }

if (typeof interval === 'undefined') {
this._logger.debug('browserResponsivenessInterval is undefined!')
if (__DEV__) {
this._logger.debug('browserResponsivenessInterval is undefined!')
}
return

@@ -127,10 +130,2 @@ }

if (!type) {
type = TYPE_CUSTOM
}
if (!name) {
name = NAME_UNKNOWN
}
var tr = this.getCurrentTransaction()

@@ -146,13 +141,16 @@

*/
this._logger.debug(
'Redefining the current transaction',
tr,
name,
type,
perfOptions
)
if (__DEV__) {
this._logger.debug(
'Redefining the current transaction',
tr,
name,
type,
perfOptions
)
}
tr.redefine(name, type, perfOptions)
} else {
this._logger.debug('Ending old transaction', tr)
if (__DEV__) {
this._logger.debug('Ending old transaction', tr)
}
tr.end()

@@ -172,4 +170,4 @@ tr = this.createTransaction(name, type, perfOptions)

/**
* Retriving the name before transaction ends should reflect
* the correctg page load transaction name
* The name must be set as soon as the transaction is started
* Ex: Helps to decide sampling based on name
*/

@@ -180,9 +178,12 @@ if (tr.name === NAME_UNKNOWN && perfOptions.pageLoadTransactionName) {

}
if (__DEV__) {
this._logger.debug('TransactionService.startTransaction', tr)
}
this._logger.debug('TransactionService.startTransaction', tr)
tr.onEnd = () => {
return Promise.resolve().then(
() => {
this._logger.debug('TransactionService transaction finished', tr)
if (__DEV__) {
this._logger.debug('TransactionService transaction finished', tr)
}
if (this.shouldIgnoreTransaction(tr.name)) {

@@ -193,4 +194,4 @@ return

/**
* Setting the name via configService.setConfig after transaction
* has started should also reflect the correct name.
* Setting the pageLoadTransactionName via configService.setConfig after
* transaction has started should also reflect the correct name.
*/

@@ -211,3 +212,7 @@ const pageLoadTransactionName = this._config.get(

},
err => this._logger.debug(err)
err => {
if (__DEV__) {
this._logger.debug('TransactionService transaction onEnd', err)
}
}
)

@@ -238,3 +243,5 @@ }

if (trans) {
this._logger.debug('TransactionService.startSpan', name, type)
if (__DEV__) {
this._logger.debug('TransactionService.startSpan', name, type)
}
var span = trans.startSpan(name, type, options)

@@ -247,3 +254,5 @@ return span

this._subscription.applyAll(this, [transaction])
this._logger.debug('TransactionService.add', transaction)
if (__DEV__) {
this._logger.debug('TransactionService.add', transaction)
}
}

@@ -259,3 +268,5 @@

var taskId = tr.addTask(taskId)
this._logger.debug('TransactionService.addTask', taskId)
if (__DEV__) {
this._logger.debug('TransactionService.addTask', taskId)
}
}

@@ -269,3 +280,5 @@ return taskId

tr.removeTask(taskId)
this._logger.debug('TransactionService.removeTask', taskId)
if (__DEV__) {
this._logger.debug('TransactionService.removeTask', taskId)
}
}

@@ -278,3 +291,5 @@ }

tr.detectFinish()
this._logger.debug('TransactionService.detectFinish')
if (__DEV__) {
this._logger.debug('TransactionService.detectFinish')
}
}

@@ -281,0 +296,0 @@ }

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc