Skip to content

Commit 46d2526

Browse files
committed
ref: CodeReview
1 parent f088aad commit 46d2526

File tree

10 files changed

+164
-119
lines changed

10 files changed

+164
-119
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
- [core] fix: sent_at for envelope headers to use same clock #2597
1717
- [apm] fix: Improve bundle size by moving span status to @sentry/apm #2589
1818
- [apm] feat: No longer discard transactions instead mark them deadline exceeded #2588
19-
- [apm] feat: Introduce `Sentry.startTransaction` and `startChild` #2600
19+
- [apm] feat: Introduce `Sentry.startTransaction` and `Transaction.startChild` #2600
2020

2121
## 5.15.5
2222

packages/apm/src/hubextensions.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,27 +25,25 @@ function traceHeaders(): { [key: string]: string } {
2525
* the created Span with the SpanContext will have a reference to it and become it's child.
2626
* Otherwise it'll crete a new `Span`.
2727
*
28-
* @param spanContext Properties with which the span should be created
28+
* @param context Properties with which the span should be created
2929
*/
30-
function startSpan(spanOrTransactionContext: SpanContext | TransactionContext): Transaction | Span {
30+
function startSpan(context: SpanContext | TransactionContext): Transaction | Span {
3131
// @ts-ignore
3232
const hub = this as Hub;
3333
const scope = hub.getScope();
3434
const client = hub.getClient();
3535

36-
let newSpanContext = spanOrTransactionContext;
36+
let newSpanContext = context;
3737

38-
// We create an empty Span in case there is no scope on the hub
39-
let parentSpan = new Span();
4038
if (scope) {
4139
// If there is a Span on the Scope we use the span_id / trace_id
4240
// To define the parent <-> child relationship
43-
parentSpan = scope.getSpan() as Span;
41+
const parentSpan = scope.getSpan();
4442
if (parentSpan) {
4543
const { trace_id } = parentSpan.getTraceContext();
4644
newSpanContext = {
4745
traceId: trace_id,
48-
...spanOrTransactionContext,
46+
...context,
4947
};
5048
}
5149
}
@@ -57,7 +55,7 @@ function startSpan(spanOrTransactionContext: SpanContext | TransactionContext):
5755
// We only roll the dice on sampling for root spans of transactions because all child spans inherit this state
5856
if (transaction.sampled === undefined) {
5957
const sampleRate = (client && client.getOptions().tracesSampleRate) || 0;
60-
transaction.sampled = Math.random() < sampleRate;
58+
transaction.sampled = Math.random() <= sampleRate;
6159
}
6260

6361
// We only want to create a span list if we sampled the transaction

packages/apm/src/integrations/express.ts

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
import { Integration } from '@sentry/types';
1+
import { Integration, Transaction } from '@sentry/types';
22
import { logger } from '@sentry/utils';
33
// tslint:disable-next-line:no-implicit-dependencies
44
import { Application, ErrorRequestHandler, NextFunction, Request, RequestHandler, Response } from 'express';
55

6+
interface SentryTracingResponse {
7+
__sentry_transaction?: Transaction;
8+
}
9+
610
/**
711
* Express integration
812
*
@@ -61,61 +65,65 @@ function wrap(fn: Function): RequestHandler | ErrorRequestHandler {
6165

6266
switch (arrity) {
6367
case 2: {
64-
return function(this: NodeJS.Global, _req: Request, res: Response): any {
65-
// tslint:disable: no-unsafe-any
66-
const transaction = (res as any).getTransaction && (res as any).getTransaction();
68+
return function(this: NodeJS.Global, _req: Request, res: Response & SentryTracingResponse): any {
69+
const transaction = res.__sentry_transaction;
6770
if (transaction) {
6871
const span = transaction.startChild({
6972
description: fn.name,
7073
op: 'middleware',
7174
});
7275
res.once('finish', () => {
73-
span.finish();
76+
if (span) {
77+
span.finish();
78+
}
7479
});
7580
}
76-
// tslint:enable: no-unsafe-any
7781
return fn.apply(this, arguments);
7882
};
7983
}
8084
case 3: {
81-
return function(this: NodeJS.Global, req: Request, res: Response, next: NextFunction): any {
82-
// tslint:disable: no-unsafe-any
83-
const transaction = (res as any).getTransaction && (res as any).getTransaction();
84-
if (transaction) {
85-
const span = transaction.startChild({
85+
return function(
86+
this: NodeJS.Global,
87+
req: Request,
88+
res: Response & SentryTracingResponse,
89+
next: NextFunction,
90+
): any {
91+
const transaction = res.__sentry_transaction;
92+
const span =
93+
transaction &&
94+
transaction.startChild({
8695
description: fn.name,
8796
op: 'middleware',
8897
});
89-
fn.call(this, req, res, function(this: NodeJS.Global): any {
98+
fn.call(this, req, res, function(this: NodeJS.Global): any {
99+
if (span) {
90100
span.finish();
91-
return next.apply(this, arguments);
92-
});
93-
} else {
94-
fn.call(this, req, res, function(this: NodeJS.Global): any {
95-
return next.apply(this, arguments);
96-
});
97-
}
98-
// tslint:enable: no-unsafe-any
101+
}
102+
return next.apply(this, arguments);
103+
});
99104
};
100105
}
101106
case 4: {
102-
return function(this: NodeJS.Global, err: any, req: Request, res: Response, next: NextFunction): any {
103-
// tslint:disable: no-unsafe-any
104-
const transaction = (res as any).getTransaction && (res as any).getTransaction();
105-
if (transaction) {
106-
const span = transaction.startChild({
107+
return function(
108+
this: NodeJS.Global,
109+
err: any,
110+
req: Request,
111+
res: Response & SentryTracingResponse,
112+
next: NextFunction,
113+
): any {
114+
const transaction = res.__sentry_transaction;
115+
const span =
116+
transaction &&
117+
transaction.startChild({
107118
description: fn.name,
108119
op: 'middleware',
109120
});
110-
fn.call(this, err, req, res, function(this: NodeJS.Global): any {
121+
fn.call(this, err, req, res, function(this: NodeJS.Global): any {
122+
if (span) {
111123
span.finish();
112-
return next.apply(this, arguments);
113-
});
114-
} else {
115-
fn.call(this, err, req, res, function(this: NodeJS.Global): any {
116-
return next.apply(this, arguments);
117-
});
118-
}
124+
}
125+
return next.apply(this, arguments);
126+
});
119127
};
120128
}
121129
default: {

packages/apm/src/integrations/tracing.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Hub } from '@sentry/hub';
2-
import { Event, EventProcessor, Integration, Severity, Span, SpanContext } from '@sentry/types';
2+
import { Event, EventProcessor, Integration, Severity, Span, SpanContext, TransactionContext } from '@sentry/types';
33
import {
44
addInstrumentationHandler,
55
getGlobalObject,
@@ -71,7 +71,7 @@ interface TracingOptions {
7171
maxTransactionDuration: number;
7272

7373
/**
74-
* Flag Transactions where tabs moved to background with "cancelled".Browser background tab timing is
74+
* Flag Transactions where tabs moved to background with "cancelled". Browser background tab timing is
7575
* not suited towards doing precise measurements of operations. Background transaction can mess up your
7676
* statistics in non deterministic ways that's why we by default recommend leaving this opition enabled.
7777
*
@@ -205,7 +205,8 @@ export class Tracing implements Integration {
205205
// Starting pageload transaction
206206
if (global.location && global.location.href) {
207207
// Use `${global.location.href}` as transaction name
208-
Tracing.startIdleTransaction(global.location.href, {
208+
Tracing.startIdleTransaction({
209+
name: global.location.href,
209210
op: 'pageload',
210211
});
211212
}
@@ -412,13 +413,13 @@ export class Tracing implements Integration {
412413
/**
413414
* Starts a Transaction waiting for activity idle to finish
414415
*/
415-
public static startIdleTransaction(name: string, spanContext?: SpanContext): Span | undefined {
416+
public static startIdleTransaction(transactionContext: TransactionContext): Transaction | undefined {
416417
// If we already have an active transaction it means one of two things
417418
// a) The user did rapid navigation changes and didn't wait until the transaction was finished
418419
// b) A activity wasn't popped correctly and therefore the transaction is stalling
419420
Tracing.finishIdleTransaction();
420421

421-
Tracing._log('[Tracing] startIdleTransaction, name:', name);
422+
Tracing._log('[Tracing] startIdleTransaction, name:', transactionContext.name);
422423

423424
const _getCurrentHub = Tracing._getCurrentHub;
424425
if (!_getCurrentHub) {
@@ -431,8 +432,8 @@ export class Tracing implements Integration {
431432
}
432433

433434
Tracing._activeTransaction = hub.startSpan({
434-
...spanContext,
435-
name,
435+
trimEnd: true,
436+
...transactionContext,
436437
}) as Transaction;
437438

438439
// The reason we do this here is because of cached responses
@@ -453,7 +454,7 @@ export class Tracing implements Integration {
453454
if (active) {
454455
Tracing._addPerformanceEntries(active);
455456
Tracing._log('[Tracing] finishIdleTransaction', active.name);
456-
active.finish(undefined, /*trimEnd*/ true);
457+
active.finish();
457458
Tracing._resetActiveTransaction();
458459
}
459460
}
@@ -860,7 +861,8 @@ function fetchCallback(handlerData: { [key: string]: any }): void {
860861
*/
861862
function historyCallback(_: { [key: string]: any }): void {
862863
if (Tracing.options.startTransactionOnLocationChange && global && global.location) {
863-
Tracing.startIdleTransaction(global.location.href, {
864+
Tracing.startIdleTransaction({
865+
name: global.location.href,
864866
op: 'navigation',
865867
});
866868
}

packages/apm/src/transaction.ts

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export class SpanRecorder {
2626
* start_timestamp).
2727
*/
2828
public add(span: SpanClass): void {
29-
if (this.spans.length > this._maxlen) {
29+
if (this.spans.length >= this._maxlen) {
3030
span.spanRecorder = undefined;
3131
} else {
3232
this.spans.push(span);
@@ -43,6 +43,8 @@ export class Transaction extends SpanClass {
4343

4444
public name?: string;
4545

46+
private readonly _trimEnd?: boolean;
47+
4648
/**
4749
* This constructor should never be called manually. Those instrumenting tracing should use `Stentry.startTransaction()`, and internal methods should use `hub.startSpan()`.
4850
* @internal
@@ -59,6 +61,8 @@ export class Transaction extends SpanClass {
5961
if (transactionContext.name) {
6062
this.name = transactionContext.name;
6163
}
64+
65+
this._trimEnd = transactionContext.trimEnd;
6266
}
6367

6468
/**
@@ -80,16 +84,9 @@ export class Transaction extends SpanClass {
8084
}
8185

8286
/**
83-
* Sets the finish timestamp on the current span.
84-
*
85-
* @inheritdoc
86-
*
87-
* @param trimEnd If true, sets the end timestamp of the transaction to the highest timestamp of child spans, trimming
88-
* the duration of the transaction. This is useful to discard extra time in the transaction that is not
89-
* accounted for in child spans, like what happens in the idle transaction Tracing integration, where we finish the
90-
* transaction after a given "idle time" and we don't want this "idle time" to be part of the transaction.
87+
* @inheritDoc
9188
*/
92-
public finish(endTimestamp?: number, trimEnd: boolean = false): string | undefined {
89+
public finish(endTimestamp?: number): string | undefined {
9390
// This transaction is already finished, so we should not flush it again.
9491
if (this.endTimestamp !== undefined) {
9592
return undefined;
@@ -105,7 +102,7 @@ export class Transaction extends SpanClass {
105102

106103
const finishedSpans = this.spanRecorder ? this.spanRecorder.spans.filter(s => s !== this && s.endTimestamp) : [];
107104

108-
if (trimEnd && finishedSpans.length > 0) {
105+
if (this._trimEnd && finishedSpans.length > 0) {
109106
this.endTimestamp = finishedSpans.reduce((prev: SpanClass, current: SpanClass) => {
110107
if (prev.endTimestamp && current.endTimestamp) {
111108
return prev.endTimestamp > current.endTimestamp ? prev : current;

packages/hub/src/hub.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,8 +368,8 @@ export class Hub implements HubInterface {
368368
/**
369369
* @inheritDoc
370370
*/
371-
public startSpan(spanOrTransactionContext: SpanContext | TransactionContext): Transaction | Span {
372-
return this._callExtensionMethod('startSpan', spanOrTransactionContext);
371+
public startSpan(context: SpanContext | TransactionContext): Transaction | Span {
372+
return this._callExtensionMethod('startSpan', context);
373373
}
374374

375375
/**

packages/node/src/handlers.ts

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -53,21 +53,17 @@ export function tracingHandler(): (
5353
traceId,
5454
});
5555

56-
if (transaction) {
57-
// We put the transaction on the scope so users can attach children to it
58-
getCurrentHub().configureScope(scope => {
59-
scope.setSpan(transaction);
60-
});
61-
// We also set a function getTransaction on the response so people can grab the transaction there to add
62-
// spans to it
63-
(res as any).getTransaction = () => transaction;
64-
}
56+
// We put the transaction on the scope so users can attach children to it
57+
getCurrentHub().configureScope(scope => {
58+
scope.setSpan(transaction);
59+
});
60+
// We also set __sentry_transaction on the response so people can grab the transaction there to add
61+
// spans to it later.
62+
(res as any).__sentry_transaction = transaction;
6563

6664
res.once('finish', () => {
67-
if (transaction) {
68-
transaction.setHttpStatus(res.statusCode);
69-
transaction.finish();
70-
}
65+
transaction.setHttpStatus(res.statusCode);
66+
transaction.finish();
7167
});
7268

7369
next();
@@ -303,7 +299,6 @@ export function parseRequest(
303299
}
304300

305301
if (options.transaction && !event.transaction) {
306-
// TODO: Use the real transaction here
307302
const transaction = extractTransaction(req, options.transaction);
308303
if (transaction) {
309304
event.transaction = transaction;

packages/types/src/hub.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ export interface Hub {
177177
* This functions starts either a Span or a Transaction (depending on the argument passed).
178178
* If there is a Span on the Scope we use the `trace_id` for all other created Transactions / Spans as a reference.
179179
*
180-
* @param spanOrTransactionContext Properties with which the Transaction/Span should be created
180+
* @param context Properties with which the Transaction/Span should be created
181181
*/
182-
startSpan(spanOrTransactionContext: SpanContext | TransactionContext): Transaction | Span;
182+
startSpan(context: SpanContext | TransactionContext): Transaction | Span;
183183
}

0 commit comments

Comments
 (0)