@sentry/apm
Advanced tools
Comparing version 5.14.2 to 5.15.0
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var hub_1 = require("@sentry/hub"); | ||
var utils_1 = require("@sentry/utils"); | ||
var span_1 = require("./span"); | ||
/** | ||
* Checks whether given value is instance of Span | ||
* @param span value to check | ||
*/ | ||
function isSpanInstance(span) { | ||
return utils_1.isInstanceOf(span, span_1.Span); | ||
} | ||
/** Returns all trace headers that are currently on the top scope. */ | ||
@@ -32,29 +24,33 @@ function traceHeaders() { | ||
* | ||
* @param span Already constructed span which should be started or properties with which the span should be created | ||
* @param spanContext Already constructed span or properties with which the span should be created | ||
*/ | ||
function startSpan(spanOrSpanContext, forceNoChild) { | ||
if (forceNoChild === void 0) { forceNoChild = false; } | ||
function startSpan(spanContext) { | ||
// @ts-ignore | ||
var that = this; | ||
var scope = that.getScope(); | ||
var client = that.getClient(); | ||
var hub = this; | ||
var scope = hub.getScope(); | ||
var client = hub.getClient(); | ||
var span; | ||
if (!isSpanInstance(spanOrSpanContext) && !forceNoChild) { | ||
if (scope) { | ||
var parentSpan = scope.getSpan(); | ||
if (parentSpan) { | ||
span = parentSpan.child(spanOrSpanContext); | ||
} | ||
// This flag determines if we already added the span as a child to the span that currently lives on the scope | ||
// If we do not have this, we will add it later on twice to the span recorder and therefore have too many spans | ||
var addedAsChild = false; | ||
if (scope) { | ||
var parentSpan = scope.getSpan(); | ||
if (parentSpan) { | ||
span = parentSpan.child(spanContext); | ||
addedAsChild = true; | ||
} | ||
} | ||
if (!isSpanInstance(span)) { | ||
span = new span_1.Span(spanOrSpanContext, that); | ||
if (!span) { | ||
span = new span_1.Span(spanContext, hub); | ||
} | ||
if (span.sampled === undefined && span.transaction !== undefined) { | ||
// We only roll the dice on sampling for "root" spans (transactions) because the childs inherit this state | ||
if (span.sampled === undefined && span.isRootSpan()) { | ||
var sampleRate = (client && client.getOptions().tracesSampleRate) || 0; | ||
span.sampled = Math.random() < sampleRate; | ||
} | ||
if (span.sampled) { | ||
// We only want to create a span list if we sampled the transaction | ||
// in case we will discard the span anyway because sampled == false, we safe memory and do not store child spans | ||
if (span.sampled && !addedAsChild) { | ||
var experimentsOptions = (client && client.getOptions()._experiments) || {}; | ||
span.initFinishedSpans(experimentsOptions.maxSpans); | ||
span.initSpanRecorder(experimentsOptions.maxSpans); | ||
} | ||
@@ -61,0 +57,0 @@ return span; |
@@ -1,2 +0,3 @@ | ||
import { EventProcessor, Hub, Integration, Span, SpanContext, SpanStatus } from '@sentry/types'; | ||
import { Hub } from '@sentry/hub'; | ||
import { EventProcessor, Integration, Span, SpanContext, SpanStatus } from '@sentry/types'; | ||
/** | ||
@@ -48,11 +49,2 @@ * Options for Tracing integration | ||
/** | ||
* Sample to determine if the Integration should instrument anything. The decision will be taken once per load | ||
* on initalization. | ||
* 0 = 0% chance of instrumenting | ||
* 1 = 100% change of instrumenting | ||
* | ||
* Default: 1 | ||
*/ | ||
tracesSampleRate: number; | ||
/** | ||
* The maximum duration of a transaction before it will be discarded. This is for some edge cases where a browser | ||
@@ -94,6 +86,2 @@ * completely freezes the JS state and picks it up later (background tabs). | ||
static id: string; | ||
/** | ||
* Is Tracing enabled, this will be determined once per pageload. | ||
*/ | ||
private static _enabled?; | ||
/** JSDoc */ | ||
@@ -160,6 +148,2 @@ static options: TracingOptions; | ||
/** | ||
* Is tracing enabled | ||
*/ | ||
private static _isEnabled; | ||
/** | ||
* Starts a Transaction waiting for activity idle to finish | ||
@@ -169,7 +153,2 @@ */ | ||
/** | ||
* Update transaction | ||
* @deprecated | ||
*/ | ||
static updateTransactionName(name: string): void; | ||
/** | ||
* Finshes the current active transaction | ||
@@ -176,0 +155,0 @@ */ |
@@ -37,3 +37,2 @@ Object.defineProperty(exports, "__esModule", { value: true }); | ||
traceXHR: true, | ||
tracesSampleRate: 1, | ||
tracingOrigins: defaultTracingOrigins, | ||
@@ -56,5 +55,2 @@ }; | ||
} | ||
if (!Tracing._isEnabled()) { | ||
return; | ||
} | ||
// Starting our inital pageload transaction | ||
@@ -65,3 +61,2 @@ if (global.location && global.location.href) { | ||
op: 'pageload', | ||
sampled: true, | ||
}); | ||
@@ -81,11 +76,9 @@ } | ||
} | ||
if (Tracing._isEnabled()) { | ||
var isOutdatedTransaction = event.timestamp && | ||
event.start_timestamp && | ||
(event.timestamp - event.start_timestamp > Tracing.options.maxTransactionDuration || | ||
event.timestamp - event.start_timestamp < 0); | ||
if (Tracing.options.maxTransactionDuration !== 0 && event.type === 'transaction' && isOutdatedTransaction) { | ||
utils_1.logger.log('[Tracing] Discarded transaction since it maxed out maxTransactionDuration'); | ||
return null; | ||
} | ||
var isOutdatedTransaction = event.timestamp && | ||
event.start_timestamp && | ||
(event.timestamp - event.start_timestamp > Tracing.options.maxTransactionDuration || | ||
event.timestamp - event.start_timestamp < 0); | ||
if (Tracing.options.maxTransactionDuration !== 0 && event.type === 'transaction' && isOutdatedTransaction) { | ||
utils_1.logger.log('[Tracing] Discarded transaction since it maxed out maxTransactionDuration'); | ||
return null; | ||
} | ||
@@ -147,2 +140,15 @@ return event; | ||
Tracing._resetActiveTransaction = function () { | ||
// We want to clean up after ourselves | ||
// If there is still the active transaction on the scope we remove it | ||
var _getCurrentHub = Tracing._getCurrentHub; | ||
if (_getCurrentHub) { | ||
var hub = _getCurrentHub(); | ||
var scope = hub.getScope(); | ||
if (scope) { | ||
if (scope.getSpan() === Tracing._activeTransaction) { | ||
scope.setSpan(undefined); | ||
} | ||
} | ||
} | ||
// ------------------------------------------------------------------ | ||
Tracing._activeTransaction = undefined; | ||
@@ -208,24 +214,5 @@ Tracing._activities = {}; | ||
/** | ||
* Is tracing enabled | ||
*/ | ||
Tracing._isEnabled = function () { | ||
if (Tracing._enabled !== undefined) { | ||
return Tracing._enabled; | ||
} | ||
// This happens only in test cases where the integration isn't initalized properly | ||
// tslint:disable-next-line: strict-type-predicates | ||
if (!Tracing.options || typeof Tracing.options.tracesSampleRate !== 'number') { | ||
return false; | ||
} | ||
Tracing._enabled = Math.random() > Tracing.options.tracesSampleRate ? false : true; | ||
return Tracing._enabled; | ||
}; | ||
/** | ||
* Starts a Transaction waiting for activity idle to finish | ||
*/ | ||
Tracing.startIdleTransaction = function (name, spanContext) { | ||
if (!Tracing._isEnabled()) { | ||
// Tracing is not enabled | ||
return undefined; | ||
} | ||
// If we already have an active transaction it means one of two things | ||
@@ -244,9 +231,9 @@ // a) The user did rapid navigation changes and didn't wait until the transaction was finished | ||
} | ||
var span = hub.startSpan(tslib_1.__assign({}, spanContext, { transaction: name }), true); | ||
Tracing._activeTransaction = span; | ||
// We need to do this workaround here and not use configureScope | ||
// Reason being at the time we start the inital transaction we do not have a client bound on the hub yet | ||
// therefore configureScope wouldn't be executed and we would miss setting the transaction | ||
// tslint:disable-next-line: no-unsafe-any | ||
hub.getScope().setSpan(span); | ||
Tracing._activeTransaction = hub.startSpan(tslib_1.__assign({}, spanContext, { transaction: name })); | ||
// We set the transaction on the scope so if there are any other spans started outside of this integration | ||
// we also add them to this transaction. | ||
// Once the idle transaction is finished, we make sure to remove it again. | ||
hub.configureScope(function (scope) { | ||
scope.setSpan(Tracing._activeTransaction); | ||
}); | ||
// The reason we do this here is because of cached responses | ||
@@ -258,21 +245,5 @@ // If we start and transaction without an activity it would never finish since there is no activity | ||
}, (Tracing.options && Tracing.options.idleTimeout) || 100); | ||
return span; | ||
return Tracing._activeTransaction; | ||
}; | ||
/** | ||
* Update transaction | ||
* @deprecated | ||
*/ | ||
Tracing.updateTransactionName = function (name) { | ||
utils_1.logger.log('[Tracing] DEPRECATED, use Sentry.configureScope => scope.setTransaction instead', name); | ||
var _getCurrentHub = Tracing._getCurrentHub; | ||
if (_getCurrentHub) { | ||
var hub = _getCurrentHub(); | ||
if (hub) { | ||
hub.configureScope(function (scope) { | ||
scope.setTransaction(name); | ||
}); | ||
} | ||
} | ||
}; | ||
/** | ||
* Finshes the current active transaction | ||
@@ -304,8 +275,2 @@ */ | ||
// tslint:disable-next-line: completed-docs | ||
function addSpan(span) { | ||
if (transactionSpan.spanRecorder) { | ||
transactionSpan.spanRecorder.finishSpan(span); | ||
} | ||
} | ||
// tslint:disable-next-line: completed-docs | ||
function addPerformanceNavigationTiming(parent, entry, event) { | ||
@@ -318,3 +283,2 @@ var span = parent.child({ | ||
span.timestamp = timeOrigin + Tracing._msToSec(entry[event + "End"]); | ||
addSpan(span); | ||
} | ||
@@ -329,3 +293,2 @@ // tslint:disable-next-line: completed-docs | ||
request.timestamp = timeOrigin + Tracing._msToSec(entry.responseEnd); | ||
addSpan(request); | ||
var response = parent.child({ | ||
@@ -337,3 +300,2 @@ description: 'response', | ||
response.timestamp = timeOrigin + Tracing._msToSec(entry.responseEnd); | ||
addSpan(response); | ||
} | ||
@@ -386,3 +348,2 @@ var entryScriptSrc; | ||
} | ||
addSpan(mark); | ||
break; | ||
@@ -394,3 +355,3 @@ case 'resource': | ||
if (transactionSpan.spanRecorder) { | ||
transactionSpan.spanRecorder.finishedSpans.map(function (finishedSpan) { | ||
transactionSpan.spanRecorder.spans.map(function (finishedSpan) { | ||
if (finishedSpan.description && finishedSpan.description.indexOf(resourceName_1) !== -1) { | ||
@@ -414,3 +375,2 @@ finishedSpan.startTimestamp = timeOrigin + startTime; | ||
} | ||
addSpan(resource); | ||
} | ||
@@ -429,3 +389,2 @@ break; | ||
evaluation.timestamp = tracingInitMarkStartTime; | ||
addSpan(evaluation); | ||
} | ||
@@ -460,7 +419,4 @@ Tracing._performanceCursor = Math.max(performance.getEntries().length - 1, 0); | ||
Tracing.pushActivity = function (name, spanContext, options) { | ||
if (!Tracing._isEnabled()) { | ||
// Tracing is not enabled | ||
return 0; | ||
} | ||
if (!Tracing._activeTransaction) { | ||
var activeTransaction = Tracing._activeTransaction; | ||
if (!activeTransaction) { | ||
utils_1.logger.log("[Tracing] Not pushing activity " + name + " since there is no active transaction"); | ||
@@ -475,3 +431,3 @@ return 0; | ||
if (hub) { | ||
var span = hub.startSpan(spanContext); | ||
var span = activeTransaction.child(spanContext); | ||
Tracing._activities[Tracing._currentIndex] = { | ||
@@ -507,6 +463,4 @@ name: name, | ||
// The !id is on purpose to also fail with 0 | ||
// Since 0 is returned by push activity in case tracing is not enabled | ||
// or there is no active transaction | ||
if (!Tracing._isEnabled() || !id) { | ||
// Tracing is not enabled | ||
// Since 0 is returned by push activity in case there is no active transaction | ||
if (!id) { | ||
return; | ||
@@ -593,3 +547,8 @@ } | ||
if (span && handlerData.xhr.setRequestHeader) { | ||
handlerData.xhr.setRequestHeader('sentry-trace', span.toTraceparent()); | ||
try { | ||
handlerData.xhr.setRequestHeader('sentry-trace', span.toTraceparent()); | ||
} | ||
catch (_) { | ||
// Error: InvalidStateError: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED. | ||
} | ||
} | ||
@@ -647,3 +606,2 @@ } | ||
op: 'navigation', | ||
sampled: true, | ||
}); | ||
@@ -650,0 +608,0 @@ } |
@@ -9,5 +9,4 @@ import { Hub } from '@sentry/hub'; | ||
private readonly _maxlen; | ||
private _openSpanCount; | ||
finishedSpans: Span[]; | ||
constructor(maxlen: number); | ||
spans: Span[]; | ||
constructor(maxlen?: number); | ||
/** | ||
@@ -19,8 +18,3 @@ * This is just so that we don't run out of memory while recording a lot | ||
*/ | ||
startSpan(span: Span): void; | ||
/** | ||
* Appends a span to finished spans table | ||
* @param span Span to be added | ||
*/ | ||
finishSpan(span: Span): void; | ||
add(span: Span): void; | ||
} | ||
@@ -48,2 +42,6 @@ /** | ||
/** | ||
* Internal keeper of the status | ||
*/ | ||
private _status?; | ||
/** | ||
* @inheritDoc | ||
@@ -88,2 +86,8 @@ */ | ||
spanRecorder?: SpanRecorder; | ||
/** | ||
* You should never call the custructor manually, always use `hub.startSpan()`. | ||
* @internal | ||
* @hideconstructor | ||
* @hidden | ||
*/ | ||
constructor(spanContext?: SpanContext, hub?: Hub); | ||
@@ -94,13 +98,16 @@ /** | ||
*/ | ||
initFinishedSpans(maxlen?: number): void; | ||
initSpanRecorder(maxlen?: number): void; | ||
/** | ||
* Creates a new `Span` while setting the current `Span.id` as `parentSpanId`. | ||
* Also the `sampled` decision will be inherited. | ||
* @inheritDoc | ||
*/ | ||
child(spanContext?: Pick<SpanContext, Exclude<keyof SpanContext, 'spanId'>>): Span; | ||
child(spanContext?: Pick<SpanContext, Exclude<keyof SpanContext, 'spanId' | 'sampled' | 'traceId' | 'parentSpanId'>>): Span; | ||
/** | ||
* @inheritDoc | ||
*/ | ||
isRootSpan(): boolean; | ||
/** | ||
* Continues a trace from a string (usually the header). | ||
* @param traceparent Traceparent string | ||
*/ | ||
static fromTraceparent(traceparent: string, spanContext?: Pick<SpanContext, Exclude<keyof SpanContext, 'spanId' | 'sampled' | 'traceid'>>): Span | undefined; | ||
static fromTraceparent(traceparent: string, spanContext?: Pick<SpanContext, Exclude<keyof SpanContext, 'spanId' | 'sampled' | 'traceId' | 'parentSpanId'>>): Span | undefined; | ||
/** | ||
@@ -141,9 +148,38 @@ * @inheritDoc | ||
*/ | ||
getTraceContext(): object; | ||
getTraceContext(): { | ||
data?: { | ||
[key: string]: any; | ||
}; | ||
description?: string; | ||
op?: string; | ||
parent_span_id?: string; | ||
span_id: string; | ||
status?: string; | ||
tags?: { | ||
[key: string]: string; | ||
}; | ||
trace_id: string; | ||
}; | ||
/** | ||
* @inheritDoc | ||
*/ | ||
toJSON(): object; | ||
toJSON(): { | ||
data?: { | ||
[key: string]: any; | ||
}; | ||
description?: string; | ||
op?: string; | ||
parent_span_id?: string; | ||
sampled?: boolean; | ||
span_id: string; | ||
start_timestamp: number; | ||
tags?: { | ||
[key: string]: string; | ||
}; | ||
timestamp?: number; | ||
trace_id: string; | ||
transaction?: string; | ||
}; | ||
} | ||
export {}; | ||
//# sourceMappingURL=span.d.ts.map |
@@ -18,4 +18,4 @@ // tslint:disable:max-classes-per-file | ||
function SpanRecorder(maxlen) { | ||
this._openSpanCount = 0; | ||
this.finishedSpans = []; | ||
if (maxlen === void 0) { maxlen = 1000; } | ||
this.spans = []; | ||
this._maxlen = maxlen; | ||
@@ -29,15 +29,10 @@ } | ||
*/ | ||
SpanRecorder.prototype.startSpan = function (span) { | ||
this._openSpanCount += 1; | ||
if (this._openSpanCount > this._maxlen) { | ||
SpanRecorder.prototype.add = function (span) { | ||
if (this.spans.length > this._maxlen) { | ||
span.spanRecorder = undefined; | ||
} | ||
else { | ||
this.spans.push(span); | ||
} | ||
}; | ||
/** | ||
* Appends a span to finished spans table | ||
* @param span Span to be added | ||
*/ | ||
SpanRecorder.prototype.finishSpan = function (span) { | ||
this.finishedSpans.push(span); | ||
}; | ||
return SpanRecorder; | ||
@@ -49,2 +44,8 @@ }()); | ||
var Span = /** @class */ (function () { | ||
/** | ||
* You should never call the custructor manually, always use `hub.startSpan()`. | ||
* @internal | ||
* @hideconstructor | ||
* @hidden | ||
*/ | ||
function Span(spanContext, hub) { | ||
@@ -109,2 +110,5 @@ /** | ||
} | ||
if (spanContext.status) { | ||
this._status = spanContext.status; | ||
} | ||
} | ||
@@ -115,3 +119,3 @@ /** | ||
*/ | ||
Span.prototype.initFinishedSpans = function (maxlen) { | ||
Span.prototype.initSpanRecorder = function (maxlen) { | ||
if (maxlen === void 0) { maxlen = 1000; } | ||
@@ -121,7 +125,6 @@ if (!this.spanRecorder) { | ||
} | ||
this.spanRecorder.startSpan(this); | ||
this.spanRecorder.add(this); | ||
}; | ||
/** | ||
* Creates a new `Span` while setting the current `Span.id` as `parentSpanId`. | ||
* Also the `sampled` decision will be inherited. | ||
* @inheritDoc | ||
*/ | ||
@@ -131,5 +134,14 @@ Span.prototype.child = function (spanContext) { | ||
span.spanRecorder = this.spanRecorder; | ||
if (span.spanRecorder) { | ||
span.spanRecorder.add(span); | ||
} | ||
return span; | ||
}; | ||
/** | ||
* @inheritDoc | ||
*/ | ||
Span.prototype.isRootSpan = function () { | ||
return this._parentSpanId === undefined; | ||
}; | ||
/** | ||
* Continues a trace from a string (usually the header). | ||
@@ -172,3 +184,3 @@ * @param traceparent Traceparent string | ||
Span.prototype.setStatus = function (value) { | ||
this.setTag('status', value); | ||
this._status = value; | ||
return this; | ||
@@ -191,3 +203,3 @@ }; | ||
Span.prototype.isSuccess = function () { | ||
return this.tags.status === types_1.SpanStatus.Ok; | ||
return this._status === types_1.SpanStatus.Ok; | ||
}; | ||
@@ -209,20 +221,17 @@ /** | ||
this.timestamp = utils_1.timestampWithMs(); | ||
if (this.spanRecorder === undefined) { | ||
// We will not send any child spans | ||
if (!this.isRootSpan()) { | ||
return undefined; | ||
} | ||
this.spanRecorder.finishSpan(this); | ||
if (this.transaction === undefined) { | ||
// If this has no transaction set we assume there's a parent | ||
// transaction for this span that would be flushed out eventually. | ||
// This happens if a span was initiated outside of `hub.startSpan` | ||
// Also if the span was sampled (sampled = false) in `hub.startSpan` already | ||
if (this.spanRecorder === undefined) { | ||
return undefined; | ||
} | ||
if (this.sampled === undefined) { | ||
// At this point a `sampled === undefined` should have already been | ||
// resolved to a concrete decision. If `sampled` is `undefined`, it's | ||
// likely that somebody used `Sentry.startSpan(...)` on a | ||
// non-transaction span and later decided to make it a transaction. | ||
utils_1.logger.warn('Discarding transaction Span without sampling decision'); | ||
if (this.sampled !== true) { | ||
// At this point if `sampled !== true` we want to discard the transaction. | ||
utils_1.logger.warn('Discarding transaction Span because it was span.sampled !== true'); | ||
return undefined; | ||
} | ||
var finishedSpans = this.spanRecorder ? this.spanRecorder.finishedSpans.filter(function (s) { return s !== _this; }) : []; | ||
var finishedSpans = this.spanRecorder ? this.spanRecorder.spans.filter(function (s) { return s !== _this && s.timestamp; }) : []; | ||
if (trimEnd && finishedSpans.length > 0) { | ||
@@ -268,3 +277,3 @@ this.timestamp = finishedSpans.reduce(function (prev, current) { | ||
span_id: this._spanId, | ||
status: this.tags.status, | ||
status: this._status, | ||
tags: Object.keys(this.tags).length > 0 ? this.tags : undefined, | ||
@@ -271,0 +280,0 @@ trace_id: this._traceId, |
import { getMainCarrier } from '@sentry/hub'; | ||
import { isInstanceOf } from '@sentry/utils'; | ||
import { Span } from './span'; | ||
/** | ||
* Checks whether given value is instance of Span | ||
* @param span value to check | ||
*/ | ||
function isSpanInstance(span) { | ||
return isInstanceOf(span, Span); | ||
} | ||
/** Returns all trace headers that are currently on the top scope. */ | ||
@@ -31,29 +23,33 @@ function traceHeaders() { | ||
* | ||
* @param span Already constructed span which should be started or properties with which the span should be created | ||
* @param spanContext Already constructed span or properties with which the span should be created | ||
*/ | ||
function startSpan(spanOrSpanContext, forceNoChild) { | ||
if (forceNoChild === void 0) { forceNoChild = false; } | ||
function startSpan(spanContext) { | ||
// @ts-ignore | ||
var that = this; | ||
var scope = that.getScope(); | ||
var client = that.getClient(); | ||
var hub = this; | ||
var scope = hub.getScope(); | ||
var client = hub.getClient(); | ||
var span; | ||
if (!isSpanInstance(spanOrSpanContext) && !forceNoChild) { | ||
if (scope) { | ||
var parentSpan = scope.getSpan(); | ||
if (parentSpan) { | ||
span = parentSpan.child(spanOrSpanContext); | ||
} | ||
// This flag determines if we already added the span as a child to the span that currently lives on the scope | ||
// If we do not have this, we will add it later on twice to the span recorder and therefore have too many spans | ||
var addedAsChild = false; | ||
if (scope) { | ||
var parentSpan = scope.getSpan(); | ||
if (parentSpan) { | ||
span = parentSpan.child(spanContext); | ||
addedAsChild = true; | ||
} | ||
} | ||
if (!isSpanInstance(span)) { | ||
span = new Span(spanOrSpanContext, that); | ||
if (!span) { | ||
span = new Span(spanContext, hub); | ||
} | ||
if (span.sampled === undefined && span.transaction !== undefined) { | ||
// We only roll the dice on sampling for "root" spans (transactions) because the childs inherit this state | ||
if (span.sampled === undefined && span.isRootSpan()) { | ||
var sampleRate = (client && client.getOptions().tracesSampleRate) || 0; | ||
span.sampled = Math.random() < sampleRate; | ||
} | ||
if (span.sampled) { | ||
// We only want to create a span list if we sampled the transaction | ||
// in case we will discard the span anyway because sampled == false, we safe memory and do not store child spans | ||
if (span.sampled && !addedAsChild) { | ||
var experimentsOptions = (client && client.getOptions()._experiments) || {}; | ||
span.initFinishedSpans(experimentsOptions.maxSpans); | ||
span.initSpanRecorder(experimentsOptions.maxSpans); | ||
} | ||
@@ -60,0 +56,0 @@ return span; |
@@ -1,2 +0,3 @@ | ||
import { EventProcessor, Hub, Integration, Span, SpanContext, SpanStatus } from '@sentry/types'; | ||
import { Hub } from '@sentry/hub'; | ||
import { EventProcessor, Integration, Span, SpanContext, SpanStatus } from '@sentry/types'; | ||
/** | ||
@@ -48,11 +49,2 @@ * Options for Tracing integration | ||
/** | ||
* Sample to determine if the Integration should instrument anything. The decision will be taken once per load | ||
* on initalization. | ||
* 0 = 0% chance of instrumenting | ||
* 1 = 100% change of instrumenting | ||
* | ||
* Default: 1 | ||
*/ | ||
tracesSampleRate: number; | ||
/** | ||
* The maximum duration of a transaction before it will be discarded. This is for some edge cases where a browser | ||
@@ -94,6 +86,2 @@ * completely freezes the JS state and picks it up later (background tabs). | ||
static id: string; | ||
/** | ||
* Is Tracing enabled, this will be determined once per pageload. | ||
*/ | ||
private static _enabled?; | ||
/** JSDoc */ | ||
@@ -160,6 +148,2 @@ static options: TracingOptions; | ||
/** | ||
* Is tracing enabled | ||
*/ | ||
private static _isEnabled; | ||
/** | ||
* Starts a Transaction waiting for activity idle to finish | ||
@@ -169,7 +153,2 @@ */ | ||
/** | ||
* Update transaction | ||
* @deprecated | ||
*/ | ||
static updateTransactionName(name: string): void; | ||
/** | ||
* Finshes the current active transaction | ||
@@ -176,0 +155,0 @@ */ |
@@ -36,3 +36,2 @@ import * as tslib_1 from "tslib"; | ||
traceXHR: true, | ||
tracesSampleRate: 1, | ||
tracingOrigins: defaultTracingOrigins, | ||
@@ -55,5 +54,2 @@ }; | ||
} | ||
if (!Tracing._isEnabled()) { | ||
return; | ||
} | ||
// Starting our inital pageload transaction | ||
@@ -64,3 +60,2 @@ if (global.location && global.location.href) { | ||
op: 'pageload', | ||
sampled: true, | ||
}); | ||
@@ -80,11 +75,9 @@ } | ||
} | ||
if (Tracing._isEnabled()) { | ||
var isOutdatedTransaction = event.timestamp && | ||
event.start_timestamp && | ||
(event.timestamp - event.start_timestamp > Tracing.options.maxTransactionDuration || | ||
event.timestamp - event.start_timestamp < 0); | ||
if (Tracing.options.maxTransactionDuration !== 0 && event.type === 'transaction' && isOutdatedTransaction) { | ||
logger.log('[Tracing] Discarded transaction since it maxed out maxTransactionDuration'); | ||
return null; | ||
} | ||
var isOutdatedTransaction = event.timestamp && | ||
event.start_timestamp && | ||
(event.timestamp - event.start_timestamp > Tracing.options.maxTransactionDuration || | ||
event.timestamp - event.start_timestamp < 0); | ||
if (Tracing.options.maxTransactionDuration !== 0 && event.type === 'transaction' && isOutdatedTransaction) { | ||
logger.log('[Tracing] Discarded transaction since it maxed out maxTransactionDuration'); | ||
return null; | ||
} | ||
@@ -146,2 +139,15 @@ return event; | ||
Tracing._resetActiveTransaction = function () { | ||
// We want to clean up after ourselves | ||
// If there is still the active transaction on the scope we remove it | ||
var _getCurrentHub = Tracing._getCurrentHub; | ||
if (_getCurrentHub) { | ||
var hub = _getCurrentHub(); | ||
var scope = hub.getScope(); | ||
if (scope) { | ||
if (scope.getSpan() === Tracing._activeTransaction) { | ||
scope.setSpan(undefined); | ||
} | ||
} | ||
} | ||
// ------------------------------------------------------------------ | ||
Tracing._activeTransaction = undefined; | ||
@@ -207,24 +213,5 @@ Tracing._activities = {}; | ||
/** | ||
* Is tracing enabled | ||
*/ | ||
Tracing._isEnabled = function () { | ||
if (Tracing._enabled !== undefined) { | ||
return Tracing._enabled; | ||
} | ||
// This happens only in test cases where the integration isn't initalized properly | ||
// tslint:disable-next-line: strict-type-predicates | ||
if (!Tracing.options || typeof Tracing.options.tracesSampleRate !== 'number') { | ||
return false; | ||
} | ||
Tracing._enabled = Math.random() > Tracing.options.tracesSampleRate ? false : true; | ||
return Tracing._enabled; | ||
}; | ||
/** | ||
* Starts a Transaction waiting for activity idle to finish | ||
*/ | ||
Tracing.startIdleTransaction = function (name, spanContext) { | ||
if (!Tracing._isEnabled()) { | ||
// Tracing is not enabled | ||
return undefined; | ||
} | ||
// If we already have an active transaction it means one of two things | ||
@@ -243,9 +230,9 @@ // a) The user did rapid navigation changes and didn't wait until the transaction was finished | ||
} | ||
var span = hub.startSpan(tslib_1.__assign({}, spanContext, { transaction: name }), true); | ||
Tracing._activeTransaction = span; | ||
// We need to do this workaround here and not use configureScope | ||
// Reason being at the time we start the inital transaction we do not have a client bound on the hub yet | ||
// therefore configureScope wouldn't be executed and we would miss setting the transaction | ||
// tslint:disable-next-line: no-unsafe-any | ||
hub.getScope().setSpan(span); | ||
Tracing._activeTransaction = hub.startSpan(tslib_1.__assign({}, spanContext, { transaction: name })); | ||
// We set the transaction on the scope so if there are any other spans started outside of this integration | ||
// we also add them to this transaction. | ||
// Once the idle transaction is finished, we make sure to remove it again. | ||
hub.configureScope(function (scope) { | ||
scope.setSpan(Tracing._activeTransaction); | ||
}); | ||
// The reason we do this here is because of cached responses | ||
@@ -257,21 +244,5 @@ // If we start and transaction without an activity it would never finish since there is no activity | ||
}, (Tracing.options && Tracing.options.idleTimeout) || 100); | ||
return span; | ||
return Tracing._activeTransaction; | ||
}; | ||
/** | ||
* Update transaction | ||
* @deprecated | ||
*/ | ||
Tracing.updateTransactionName = function (name) { | ||
logger.log('[Tracing] DEPRECATED, use Sentry.configureScope => scope.setTransaction instead', name); | ||
var _getCurrentHub = Tracing._getCurrentHub; | ||
if (_getCurrentHub) { | ||
var hub = _getCurrentHub(); | ||
if (hub) { | ||
hub.configureScope(function (scope) { | ||
scope.setTransaction(name); | ||
}); | ||
} | ||
} | ||
}; | ||
/** | ||
* Finshes the current active transaction | ||
@@ -303,8 +274,2 @@ */ | ||
// tslint:disable-next-line: completed-docs | ||
function addSpan(span) { | ||
if (transactionSpan.spanRecorder) { | ||
transactionSpan.spanRecorder.finishSpan(span); | ||
} | ||
} | ||
// tslint:disable-next-line: completed-docs | ||
function addPerformanceNavigationTiming(parent, entry, event) { | ||
@@ -317,3 +282,2 @@ var span = parent.child({ | ||
span.timestamp = timeOrigin + Tracing._msToSec(entry[event + "End"]); | ||
addSpan(span); | ||
} | ||
@@ -328,3 +292,2 @@ // tslint:disable-next-line: completed-docs | ||
request.timestamp = timeOrigin + Tracing._msToSec(entry.responseEnd); | ||
addSpan(request); | ||
var response = parent.child({ | ||
@@ -336,3 +299,2 @@ description: 'response', | ||
response.timestamp = timeOrigin + Tracing._msToSec(entry.responseEnd); | ||
addSpan(response); | ||
} | ||
@@ -385,3 +347,2 @@ var entryScriptSrc; | ||
} | ||
addSpan(mark); | ||
break; | ||
@@ -393,3 +354,3 @@ case 'resource': | ||
if (transactionSpan.spanRecorder) { | ||
transactionSpan.spanRecorder.finishedSpans.map(function (finishedSpan) { | ||
transactionSpan.spanRecorder.spans.map(function (finishedSpan) { | ||
if (finishedSpan.description && finishedSpan.description.indexOf(resourceName_1) !== -1) { | ||
@@ -413,3 +374,2 @@ finishedSpan.startTimestamp = timeOrigin + startTime; | ||
} | ||
addSpan(resource); | ||
} | ||
@@ -428,3 +388,2 @@ break; | ||
evaluation.timestamp = tracingInitMarkStartTime; | ||
addSpan(evaluation); | ||
} | ||
@@ -459,7 +418,4 @@ Tracing._performanceCursor = Math.max(performance.getEntries().length - 1, 0); | ||
Tracing.pushActivity = function (name, spanContext, options) { | ||
if (!Tracing._isEnabled()) { | ||
// Tracing is not enabled | ||
return 0; | ||
} | ||
if (!Tracing._activeTransaction) { | ||
var activeTransaction = Tracing._activeTransaction; | ||
if (!activeTransaction) { | ||
logger.log("[Tracing] Not pushing activity " + name + " since there is no active transaction"); | ||
@@ -474,3 +430,3 @@ return 0; | ||
if (hub) { | ||
var span = hub.startSpan(spanContext); | ||
var span = activeTransaction.child(spanContext); | ||
Tracing._activities[Tracing._currentIndex] = { | ||
@@ -506,6 +462,4 @@ name: name, | ||
// The !id is on purpose to also fail with 0 | ||
// Since 0 is returned by push activity in case tracing is not enabled | ||
// or there is no active transaction | ||
if (!Tracing._isEnabled() || !id) { | ||
// Tracing is not enabled | ||
// Since 0 is returned by push activity in case there is no active transaction | ||
if (!id) { | ||
return; | ||
@@ -592,3 +546,8 @@ } | ||
if (span && handlerData.xhr.setRequestHeader) { | ||
handlerData.xhr.setRequestHeader('sentry-trace', span.toTraceparent()); | ||
try { | ||
handlerData.xhr.setRequestHeader('sentry-trace', span.toTraceparent()); | ||
} | ||
catch (_) { | ||
// Error: InvalidStateError: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED. | ||
} | ||
} | ||
@@ -646,3 +605,2 @@ } | ||
op: 'navigation', | ||
sampled: true, | ||
}); | ||
@@ -649,0 +607,0 @@ } |
@@ -9,5 +9,4 @@ import { Hub } from '@sentry/hub'; | ||
private readonly _maxlen; | ||
private _openSpanCount; | ||
finishedSpans: Span[]; | ||
constructor(maxlen: number); | ||
spans: Span[]; | ||
constructor(maxlen?: number); | ||
/** | ||
@@ -19,8 +18,3 @@ * This is just so that we don't run out of memory while recording a lot | ||
*/ | ||
startSpan(span: Span): void; | ||
/** | ||
* Appends a span to finished spans table | ||
* @param span Span to be added | ||
*/ | ||
finishSpan(span: Span): void; | ||
add(span: Span): void; | ||
} | ||
@@ -48,2 +42,6 @@ /** | ||
/** | ||
* Internal keeper of the status | ||
*/ | ||
private _status?; | ||
/** | ||
* @inheritDoc | ||
@@ -88,2 +86,8 @@ */ | ||
spanRecorder?: SpanRecorder; | ||
/** | ||
* You should never call the custructor manually, always use `hub.startSpan()`. | ||
* @internal | ||
* @hideconstructor | ||
* @hidden | ||
*/ | ||
constructor(spanContext?: SpanContext, hub?: Hub); | ||
@@ -94,13 +98,16 @@ /** | ||
*/ | ||
initFinishedSpans(maxlen?: number): void; | ||
initSpanRecorder(maxlen?: number): void; | ||
/** | ||
* Creates a new `Span` while setting the current `Span.id` as `parentSpanId`. | ||
* Also the `sampled` decision will be inherited. | ||
* @inheritDoc | ||
*/ | ||
child(spanContext?: Pick<SpanContext, Exclude<keyof SpanContext, 'spanId'>>): Span; | ||
child(spanContext?: Pick<SpanContext, Exclude<keyof SpanContext, 'spanId' | 'sampled' | 'traceId' | 'parentSpanId'>>): Span; | ||
/** | ||
* @inheritDoc | ||
*/ | ||
isRootSpan(): boolean; | ||
/** | ||
* Continues a trace from a string (usually the header). | ||
* @param traceparent Traceparent string | ||
*/ | ||
static fromTraceparent(traceparent: string, spanContext?: Pick<SpanContext, Exclude<keyof SpanContext, 'spanId' | 'sampled' | 'traceid'>>): Span | undefined; | ||
static fromTraceparent(traceparent: string, spanContext?: Pick<SpanContext, Exclude<keyof SpanContext, 'spanId' | 'sampled' | 'traceId' | 'parentSpanId'>>): Span | undefined; | ||
/** | ||
@@ -141,9 +148,38 @@ * @inheritDoc | ||
*/ | ||
getTraceContext(): object; | ||
getTraceContext(): { | ||
data?: { | ||
[key: string]: any; | ||
}; | ||
description?: string; | ||
op?: string; | ||
parent_span_id?: string; | ||
span_id: string; | ||
status?: string; | ||
tags?: { | ||
[key: string]: string; | ||
}; | ||
trace_id: string; | ||
}; | ||
/** | ||
* @inheritDoc | ||
*/ | ||
toJSON(): object; | ||
toJSON(): { | ||
data?: { | ||
[key: string]: any; | ||
}; | ||
description?: string; | ||
op?: string; | ||
parent_span_id?: string; | ||
sampled?: boolean; | ||
span_id: string; | ||
start_timestamp: number; | ||
tags?: { | ||
[key: string]: string; | ||
}; | ||
timestamp?: number; | ||
trace_id: string; | ||
transaction?: string; | ||
}; | ||
} | ||
export {}; | ||
//# sourceMappingURL=span.d.ts.map |
@@ -17,4 +17,4 @@ // tslint:disable:max-classes-per-file | ||
function SpanRecorder(maxlen) { | ||
this._openSpanCount = 0; | ||
this.finishedSpans = []; | ||
if (maxlen === void 0) { maxlen = 1000; } | ||
this.spans = []; | ||
this._maxlen = maxlen; | ||
@@ -28,15 +28,10 @@ } | ||
*/ | ||
SpanRecorder.prototype.startSpan = function (span) { | ||
this._openSpanCount += 1; | ||
if (this._openSpanCount > this._maxlen) { | ||
SpanRecorder.prototype.add = function (span) { | ||
if (this.spans.length > this._maxlen) { | ||
span.spanRecorder = undefined; | ||
} | ||
else { | ||
this.spans.push(span); | ||
} | ||
}; | ||
/** | ||
* Appends a span to finished spans table | ||
* @param span Span to be added | ||
*/ | ||
SpanRecorder.prototype.finishSpan = function (span) { | ||
this.finishedSpans.push(span); | ||
}; | ||
return SpanRecorder; | ||
@@ -48,2 +43,8 @@ }()); | ||
var Span = /** @class */ (function () { | ||
/** | ||
* You should never call the custructor manually, always use `hub.startSpan()`. | ||
* @internal | ||
* @hideconstructor | ||
* @hidden | ||
*/ | ||
function Span(spanContext, hub) { | ||
@@ -108,2 +109,5 @@ /** | ||
} | ||
if (spanContext.status) { | ||
this._status = spanContext.status; | ||
} | ||
} | ||
@@ -114,3 +118,3 @@ /** | ||
*/ | ||
Span.prototype.initFinishedSpans = function (maxlen) { | ||
Span.prototype.initSpanRecorder = function (maxlen) { | ||
if (maxlen === void 0) { maxlen = 1000; } | ||
@@ -120,7 +124,6 @@ if (!this.spanRecorder) { | ||
} | ||
this.spanRecorder.startSpan(this); | ||
this.spanRecorder.add(this); | ||
}; | ||
/** | ||
* Creates a new `Span` while setting the current `Span.id` as `parentSpanId`. | ||
* Also the `sampled` decision will be inherited. | ||
* @inheritDoc | ||
*/ | ||
@@ -130,5 +133,14 @@ Span.prototype.child = function (spanContext) { | ||
span.spanRecorder = this.spanRecorder; | ||
if (span.spanRecorder) { | ||
span.spanRecorder.add(span); | ||
} | ||
return span; | ||
}; | ||
/** | ||
* @inheritDoc | ||
*/ | ||
Span.prototype.isRootSpan = function () { | ||
return this._parentSpanId === undefined; | ||
}; | ||
/** | ||
* Continues a trace from a string (usually the header). | ||
@@ -171,3 +183,3 @@ * @param traceparent Traceparent string | ||
Span.prototype.setStatus = function (value) { | ||
this.setTag('status', value); | ||
this._status = value; | ||
return this; | ||
@@ -190,3 +202,3 @@ }; | ||
Span.prototype.isSuccess = function () { | ||
return this.tags.status === SpanStatus.Ok; | ||
return this._status === SpanStatus.Ok; | ||
}; | ||
@@ -208,20 +220,17 @@ /** | ||
this.timestamp = timestampWithMs(); | ||
if (this.spanRecorder === undefined) { | ||
// We will not send any child spans | ||
if (!this.isRootSpan()) { | ||
return undefined; | ||
} | ||
this.spanRecorder.finishSpan(this); | ||
if (this.transaction === undefined) { | ||
// If this has no transaction set we assume there's a parent | ||
// transaction for this span that would be flushed out eventually. | ||
// This happens if a span was initiated outside of `hub.startSpan` | ||
// Also if the span was sampled (sampled = false) in `hub.startSpan` already | ||
if (this.spanRecorder === undefined) { | ||
return undefined; | ||
} | ||
if (this.sampled === undefined) { | ||
// At this point a `sampled === undefined` should have already been | ||
// resolved to a concrete decision. If `sampled` is `undefined`, it's | ||
// likely that somebody used `Sentry.startSpan(...)` on a | ||
// non-transaction span and later decided to make it a transaction. | ||
logger.warn('Discarding transaction Span without sampling decision'); | ||
if (this.sampled !== true) { | ||
// At this point if `sampled !== true` we want to discard the transaction. | ||
logger.warn('Discarding transaction Span because it was span.sampled !== true'); | ||
return undefined; | ||
} | ||
var finishedSpans = this.spanRecorder ? this.spanRecorder.finishedSpans.filter(function (s) { return s !== _this; }) : []; | ||
var finishedSpans = this.spanRecorder ? this.spanRecorder.spans.filter(function (s) { return s !== _this && s.timestamp; }) : []; | ||
if (trimEnd && finishedSpans.length > 0) { | ||
@@ -267,3 +276,3 @@ this.timestamp = finishedSpans.reduce(function (prev, current) { | ||
span_id: this._spanId, | ||
status: this.tags.status, | ||
status: this._status, | ||
tags: Object.keys(this.tags).length > 0 ? this.tags : undefined, | ||
@@ -270,0 +279,0 @@ trace_id: this._traceId, |
{ | ||
"name": "@sentry/apm", | ||
"version": "5.14.2", | ||
"version": "5.15.0", | ||
"description": "Extensions for APM", | ||
@@ -19,7 +19,7 @@ "repository": "git://github.com/getsentry/sentry-javascript.git", | ||
"dependencies": { | ||
"@sentry/browser": "5.14.2", | ||
"@sentry/hub": "5.14.2", | ||
"@sentry/minimal": "5.14.2", | ||
"@sentry/types": "5.14.2", | ||
"@sentry/utils": "5.14.2", | ||
"@sentry/browser": "5.15.0", | ||
"@sentry/hub": "5.15.0", | ||
"@sentry/minimal": "5.15.0", | ||
"@sentry/types": "5.15.0", | ||
"@sentry/utils": "5.15.0", | ||
"tslib": "^1.9.3" | ||
@@ -26,0 +26,0 @@ }, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
282947
3108
+ Added@sentry/browser@5.15.0(transitive)
+ Added@sentry/core@5.15.0(transitive)
+ Added@sentry/hub@5.15.0(transitive)
+ Added@sentry/minimal@5.15.0(transitive)
+ Added@sentry/types@5.15.0(transitive)
+ Added@sentry/utils@5.15.0(transitive)
- Removed@sentry/browser@5.14.2(transitive)
- Removed@sentry/core@5.14.2(transitive)
- Removed@sentry/hub@5.14.2(transitive)
- Removed@sentry/minimal@5.14.2(transitive)
- Removed@sentry/types@5.14.2(transitive)
- Removed@sentry/utils@5.14.2(transitive)
Updated@sentry/browser@5.15.0
Updated@sentry/hub@5.15.0
Updated@sentry/minimal@5.15.0
Updated@sentry/types@5.15.0
Updated@sentry/utils@5.15.0