Skip to content

Commit 41b552c

Browse files
committed
feat: Use timestamp of last span
1 parent 80a3e02 commit 41b552c

File tree

5 files changed

+46
-39
lines changed

5 files changed

+46
-39
lines changed

packages/hub/src/hub.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -405,12 +405,12 @@ export class Hub implements HubInterface {
405405
/**
406406
* @inheritDoc
407407
*/
408-
public startSpan(spanOrSpanContext?: Span | SpanContext): Span {
408+
public startSpan(spanOrSpanContext?: Span | SpanContext, forceNoChild: boolean = false): Span {
409409
const scope = this.getScope();
410410
const client = this.getClient();
411411
let span;
412412

413-
if (!isSpanInstance(spanOrSpanContext)) {
413+
if (!isSpanInstance(spanOrSpanContext) && !forceNoChild) {
414414
if (scope) {
415415
const parentSpan = scope.getSpan();
416416
if (parentSpan) {

packages/hub/src/span.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -261,13 +261,13 @@ export class Span implements SpanInterface, SpanContext {
261261
/**
262262
* Sets the finish timestamp on the current span
263263
*/
264-
public finish(endTimestamp?: number): string | undefined {
264+
public finish(useLastSpanTimestamp: boolean = false): string | undefined {
265265
// This transaction is already finished, so we should not flush it again.
266266
if (this.timestamp !== undefined) {
267267
return undefined;
268268
}
269269

270-
this.timestamp = endTimestamp || timestampWithMs();
270+
this.timestamp = timestampWithMs();
271271

272272
if (this.spanRecorder === undefined) {
273273
return undefined;
@@ -291,6 +291,10 @@ export class Span implements SpanInterface, SpanContext {
291291
}
292292
const finishedSpans = this.spanRecorder ? this.spanRecorder.finishedSpans.filter(s => s !== this) : [];
293293

294+
if (useLastSpanTimestamp && finishedSpans.length > 0) {
295+
this.timestamp = finishedSpans[finishedSpans.length - 1].timestamp;
296+
}
297+
294298
return this._hub.captureEvent({
295299
// TODO: Is this necessary? We already do store contextx in in applyToEvent,
296300
// so maybe we can move `getTraceContext` call there as well?

packages/integrations/src/transactionactivity.ts

+36-33
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { EventProcessor, Hub, Integration, Scope, Span, SpanContext } from '@sentry/types';
2-
import { timestampWithMs } from '@sentry/utils';
32

43
/** JSDoc */
54
interface TransactionActivityOptions {
@@ -11,7 +10,7 @@ interface TransactionActivityOptions {
1110
// onActivity?: (info) => {
1211
// return info.type !== 'xhr' || !info.url.match(/zendesk/);
1312
// },
14-
idleTimeout?: number;
13+
idleTimeout: number;
1514
}
1615

1716
/** JSDoc */
@@ -51,11 +50,12 @@ export class TransactionActivity implements Integration {
5150
/**
5251
* @inheritDoc
5352
*/
54-
public constructor(options?: TransactionActivityOptions) {
55-
TransactionActivity._options = {
53+
public constructor(
54+
public readonly _options: TransactionActivityOptions = {
5655
idleTimeout: 500,
57-
...options,
58-
};
56+
},
57+
) {
58+
TransactionActivity._options = _options;
5959
}
6060

6161
/**
@@ -65,35 +65,16 @@ export class TransactionActivity implements Integration {
6565
TransactionActivity._getCurrentHub = getCurrentHub;
6666
}
6767

68-
/**
69-
* Internal run loop that checks if activy is running
70-
*/
71-
private static _watchActivity(): void {
72-
const count = Object.keys(TransactionActivity._activities).length;
73-
clearTimeout(TransactionActivity._debounce);
74-
if (count > 0) {
75-
setTimeout(() => {
76-
TransactionActivity._watchActivity();
77-
}, 10);
78-
} else {
79-
const timeout = TransactionActivity._options && TransactionActivity._options.idleTimeout;
80-
TransactionActivity._debounce = (setTimeout(() => {
81-
const active = TransactionActivity._activeTransaction;
82-
if (active) {
83-
active.finish(timestampWithMs() - (timeout || 0));
84-
}
85-
}, timeout) as any) as number; // TODO 500
86-
}
87-
}
88-
8968
/**
9069
* Starts a Transaction waiting for activity idle to finish
9170
*/
9271
public static startIdleTransaction(name: string, spanContext?: SpanContext): Span | undefined {
9372
const activeTransaction = TransactionActivity._activeTransaction;
9473

9574
if (activeTransaction) {
96-
// We need to finish any active transaction before starting a new
75+
// If we already have an active transaction it means one of two things
76+
// a) The user did rapid navigation changes and didn't wait until the transaction was finished
77+
// b) A activity wasn't popped correctly and therefore the transaction is stalling
9778
activeTransaction.finish();
9879
}
9980

@@ -107,17 +88,27 @@ export class TransactionActivity implements Integration {
10788
return undefined;
10889
}
10990

110-
const span = hub.startSpan({
111-
...spanContext,
112-
transaction: name,
113-
});
91+
const span = hub.startSpan(
92+
{
93+
...spanContext,
94+
transaction: name,
95+
},
96+
true,
97+
);
11498

11599
TransactionActivity._activeTransaction = span;
116100

117101
hub.configureScope((scope: Scope) => {
118102
scope.setSpan(span);
119103
});
120104

105+
// The reason we do this here is because of cached responses
106+
// If we start and transaction without an activity it would never finish since there is no activity
107+
const id = TransactionActivity.pushActivity('idleTransactionStarted');
108+
setTimeout(() => {
109+
TransactionActivity.popActivity(id);
110+
}, (TransactionActivity._options && TransactionActivity._options.idleTimeout) || 100);
111+
121112
return span;
122113
}
123114

@@ -152,7 +143,6 @@ export class TransactionActivity implements Integration {
152143
};
153144
}
154145

155-
TransactionActivity._watchActivity();
156146
return TransactionActivity._currentIndex++;
157147
}
158148

@@ -168,5 +158,18 @@ export class TransactionActivity implements Integration {
168158
// tslint:disable-next-line: no-dynamic-delete
169159
delete TransactionActivity._activities[id];
170160
}
161+
162+
const count = Object.keys(TransactionActivity._activities).length;
163+
clearTimeout(TransactionActivity._debounce);
164+
165+
if (count === 0) {
166+
const timeout = TransactionActivity._options && TransactionActivity._options.idleTimeout;
167+
TransactionActivity._debounce = (setTimeout(() => {
168+
const active = TransactionActivity._activeTransaction;
169+
if (active) {
170+
active.finish(true);
171+
}
172+
}, timeout) as any) as number; // TODO 500
173+
}
171174
}
172175
}

packages/types/src/hub.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -179,5 +179,5 @@ export interface Hub {
179179
*
180180
* @param span Already constructed span which should be started or properties with which the span should be created
181181
*/
182-
startSpan(span?: Span | SpanContext): Span;
182+
startSpan(span?: Span | SpanContext, forceNoChild?: boolean): Span;
183183
}

packages/types/src/span.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/** Span holding trace_id, span_id */
22
export interface Span {
33
/** Sets the finish timestamp on the current span and sends it if it was a transaction */
4-
finish(endTimestamp?: number): string | undefined;
4+
finish(useLastSpanTimestamp?: boolean): string | undefined;
55
/** Return a traceparent compatible header string */
66
toTraceparent(): string;
77
/** Convert the object to JSON for w. spans array info only */

0 commit comments

Comments
 (0)