Skip to content

Commit bc5ee8f

Browse files
HazATkamilogorek
andauthored
feat: Add autoPop parameter and add debug logs (getsentry#2459)
* feat: Add autopop parameter, Add debug loggings * fix: Breadcrumbs type * fix: Breadcrumb types for transaction/events * ref: Add typedoc * ref: PushActivity options * ref: Switch to DeadlineExceeded status * ref: Allow 0 as autopop * fix: Number check * github plz Co-authored-by: Kamil Ogórek <kamil.ogorek@gmail.com>
1 parent 6e1f442 commit bc5ee8f

File tree

4 files changed

+80
-6
lines changed

4 files changed

+80
-6
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
- [node] ref: Drop Node v6, add Node v12 to test matrix, move all scripts to Node v12 (#2455)
77
- [apm] fix: Use monotonic clock to compute durations (#2441)
88
- [utils] ref: Prevent instantiating unnecessary Date objects in `timestampWithMs` (#2442)
9+
- [apm] feat: Add `options.autoPopAfter` parameter to `pushActivity` to prevent never-ending spans (#2459)
10+
- [browser] fix: Mark transactions as event.transaction in breadcrumbs correctly
911

1012
## 5.12.5
1113

packages/apm/src/integrations/tracing.ts

+38-3
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,9 @@ export class Tracing implements Integration {
162162

163163
if (this._emitOptionsWarning) {
164164
logger.warn(
165-
'Sentry: You need to define `tracingOrigins` in the options. Set an array of urls or patterns to trace.',
165+
'[Tracing] You need to define `tracingOrigins` in the options. Set an array of urls or patterns to trace.',
166166
);
167-
logger.warn(`Sentry: We added a reasonable default for you: ${defaultTracingOrigins}`);
167+
logger.warn(`[Tracing] We added a reasonable default for you: ${defaultTracingOrigins}`);
168168
}
169169

170170
if (!Tracing._isEnabled()) {
@@ -255,6 +255,8 @@ export class Tracing implements Integration {
255255
// b) A activity wasn't popped correctly and therefore the transaction is stalling
256256
Tracing.finishIdleTransaction();
257257

258+
logger.log('[Tracing] startIdleTransaction, name:', name);
259+
258260
const _getCurrentHub = Tracing._getCurrentHub;
259261
if (!_getCurrentHub) {
260262
return undefined;
@@ -296,6 +298,7 @@ export class Tracing implements Integration {
296298
* @deprecated
297299
*/
298300
public static updateTransactionName(name: string): void {
301+
logger.log('[Tracing] DEPRECATED, use Sentry.configureScope => scope.setTransaction instead', name);
299302
const _getCurrentHub = Tracing._getCurrentHub;
300303
if (_getCurrentHub) {
301304
const hub = _getCurrentHub();
@@ -313,6 +316,7 @@ export class Tracing implements Integration {
313316
public static finishIdleTransaction(): void {
314317
const active = Tracing._activeTransaction as SpanClass;
315318
if (active) {
319+
logger.log('[Tracing] finishIdleTransaction', active.transaction);
316320
// true = use timestamp of last span
317321
active.finish(true);
318322
}
@@ -324,14 +328,25 @@ export class Tracing implements Integration {
324328
public static setTransactionStatus(status: SpanStatus): void {
325329
const active = Tracing._activeTransaction;
326330
if (active) {
331+
logger.log('[Tracing] setTransactionStatus', status);
327332
active.setStatus(status);
328333
}
329334
}
330335

331336
/**
332337
* Starts tracking for a specifc activity
338+
*
339+
* @param name Name of the activity, can be any string (Only used internally to identify the activity)
340+
* @param spanContext If provided a Span with the SpanContext will be created.
341+
* @param options _autoPopAfter_ | Time in ms, if provided the activity will be popped automatically after this timeout. This can be helpful in cases where you cannot gurantee your application knows the state and calls `popActivity` for sure.
333342
*/
334-
public static pushActivity(name: string, spanContext?: SpanContext): number {
343+
public static pushActivity(
344+
name: string,
345+
spanContext?: SpanContext,
346+
options?: {
347+
autoPopAfter?: number;
348+
},
349+
): number {
335350
if (!Tracing._isEnabled()) {
336351
// Tracing is not enabled
337352
return 0;
@@ -355,6 +370,18 @@ export class Tracing implements Integration {
355370
};
356371
}
357372

373+
logger.log(`[Tracing] pushActivity: ${name}#${Tracing._currentIndex}`);
374+
logger.log('[Tracing] activies count', Object.keys(Tracing._activities).length);
375+
if (options && typeof options.autoPopAfter === 'number') {
376+
logger.log(`[Tracing] auto pop of: ${name}#${Tracing._currentIndex} in ${options.autoPopAfter}ms`);
377+
const index = Tracing._currentIndex;
378+
setTimeout(() => {
379+
Tracing.popActivity(index, {
380+
autoPop: true,
381+
status: SpanStatus.DeadlineExceeded,
382+
});
383+
}, options.autoPopAfter);
384+
}
358385
return Tracing._currentIndex++;
359386
}
360387

@@ -368,7 +395,9 @@ export class Tracing implements Integration {
368395
}
369396

370397
const activity = Tracing._activities[id];
398+
371399
if (activity) {
400+
logger.log(`[Tracing] popActivity ${activity.name}#${id}`);
372401
const span = activity.span;
373402
if (span) {
374403
if (spanData) {
@@ -377,6 +406,9 @@ export class Tracing implements Integration {
377406
if (key === 'status_code') {
378407
span.setHttpStatus(spanData[key] as number);
379408
}
409+
if (key === 'status') {
410+
span.setStatus(spanData[key] as SpanStatus);
411+
}
380412
});
381413
}
382414
span.finish();
@@ -388,8 +420,11 @@ export class Tracing implements Integration {
388420
const count = Object.keys(Tracing._activities).length;
389421
clearTimeout(Tracing._debounce);
390422

423+
logger.log('[Tracing] activies count', count);
424+
391425
if (count === 0) {
392426
const timeout = Tracing.options && Tracing.options.idleTimeout;
427+
logger.log(`[Tracing] Flushing Transaction in ${timeout}ms`);
393428
Tracing._debounce = (setTimeout(() => {
394429
Tracing.finishIdleTransaction();
395430
}, timeout) as any) as number;

packages/browser/src/integrations/breadcrumbs.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ function addSentryBreadcrumb(serializedData: string): void {
317317
const event = JSON.parse(serializedData);
318318
getCurrentHub().addBreadcrumb(
319319
{
320-
category: `sentry.${event.transaction ? 'transaction' : 'event'}`,
320+
category: `sentry.${event.type === 'transaction' ? 'transaction' : 'event'}`,
321321
event_id: event.event_id,
322322
level: event.level || Severity.fromString('error'),
323323
message: getEventDescription(event),

packages/browser/test/integration/suites/breadcrumbs.js

+39-2
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ describe("breadcrumbs", function() {
121121

122122
it(
123123
optional(
124-
"should transform XMLHttpRequests with transactions to the Sentry store endpoint as sentry.transaction type breadcrumb",
124+
"should transform XMLHttpRequests with transactions type to the Sentry store endpoint as sentry.transaction type breadcrumb",
125125
IS_LOADER
126126
),
127127
function() {
@@ -137,7 +137,7 @@ describe("breadcrumbs", function() {
137137
var xhr = new XMLHttpRequest();
138138
xhr.open("POST", store);
139139
xhr.send(
140-
'{"message":"someMessage","transaction":"wat","level":"warning"}'
140+
'{"message":"someMessage","transaction":"wat","level":"warning", "type": "transaction"}'
141141
);
142142
waitForXHR(xhr, function() {
143143
Sentry.captureMessage("test");
@@ -156,6 +156,43 @@ describe("breadcrumbs", function() {
156156
}
157157
);
158158

159+
it(
160+
optional(
161+
"should not transform XMLHttpRequests with transactions attribute to the Sentry store endpoint as sentry.transaction type breadcrumb",
162+
IS_LOADER
163+
),
164+
function() {
165+
return runInSandbox(sandbox, { manual: true }, function() {
166+
var store =
167+
document.location.protocol +
168+
"//" +
169+
document.location.hostname +
170+
(document.location.port ? ":" + document.location.port : "") +
171+
"/api/1/store/" +
172+
"?sentry_key=1337";
173+
174+
var xhr = new XMLHttpRequest();
175+
xhr.open("POST", store);
176+
xhr.send(
177+
'{"message":"someMessage","transaction":"wat","level":"warning"}'
178+
);
179+
waitForXHR(xhr, function() {
180+
Sentry.captureMessage("test");
181+
window.finalizeManualTest();
182+
});
183+
}).then(function(summary) {
184+
// The async loader doesn't wrap XHR
185+
if (IS_LOADER) {
186+
return;
187+
}
188+
assert.equal(summary.breadcrumbs.length, 1);
189+
assert.equal(summary.breadcrumbs[0].category, "sentry.event");
190+
assert.equal(summary.breadcrumbs[0].level, "warning");
191+
assert.equal(summary.breadcrumbs[0].message, "someMessage");
192+
});
193+
}
194+
);
195+
159196
it("should record a fetch request", function() {
160197
return runInSandbox(sandbox, { manual: true }, function() {
161198
fetch("/base/subjects/example.json", {

0 commit comments

Comments
 (0)