@sentry/profiling-node 11.0.0-alpha.0 → 11.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/build/cjs/index.js +13 -393
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.js +14 -394
- package/build/esm/index.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/types/integration.d.ts +0 -6
- package/build/types/integration.d.ts.map +1 -1
- package/build/types/utils.d.ts +5 -39
- package/build/types/utils.d.ts.map +1 -1
- package/package.json +4 -3
- package/build/types/spanProfileUtils.d.ts +0 -17
- package/build/types/spanProfileUtils.d.ts.map +0 -1
package/build/esm/index.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { parseSemver,
|
|
1
|
+
import { parseSemver, createEnvelope, debug, dsnToString, uuid4, getDebugImagesForResources, defineIntegration, consoleSandbox, getCurrentScope, getGlobalScope } from '@sentry/core';
|
|
2
2
|
import { CpuProfilerBindings, ProfileFormat } from '@sentry/node-cpu-profiler';
|
|
3
3
|
import { isMainThread, threadId } from 'worker_threads';
|
|
4
|
-
import * as os from 'os';
|
|
5
|
-
import { env, versions } from 'process';
|
|
6
4
|
|
|
7
5
|
const DEBUG_BUILD = (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__);
|
|
8
6
|
|
|
@@ -11,14 +9,7 @@ const NODE_MAJOR = NODE_VERSION.major;
|
|
|
11
9
|
|
|
12
10
|
const PROFILER_THREAD_ID_STRING = String(threadId);
|
|
13
11
|
const PROFILER_THREAD_NAME = isMainThread ? "main" : "worker";
|
|
14
|
-
const FORMAT_VERSION = "1";
|
|
15
12
|
const CONTINUOUS_FORMAT_VERSION = "2";
|
|
16
|
-
const PLATFORM = os.platform();
|
|
17
|
-
const RELEASE = os.release();
|
|
18
|
-
const VERSION = os.version();
|
|
19
|
-
const TYPE = os.type();
|
|
20
|
-
const MODEL = os.machine();
|
|
21
|
-
const ARCH = os.arch();
|
|
22
13
|
function isRawThreadCpuProfile(profile) {
|
|
23
14
|
return !("thread_metadata" in profile);
|
|
24
15
|
}
|
|
@@ -37,70 +28,6 @@ function enrichWithThreadInformation(profile) {
|
|
|
37
28
|
}
|
|
38
29
|
};
|
|
39
30
|
}
|
|
40
|
-
function createProfilingEvent(client, profile, event) {
|
|
41
|
-
if (!isValidProfile(profile)) {
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
return createProfilePayload(client, profile, {
|
|
45
|
-
release: event.release ?? "",
|
|
46
|
-
environment: event.environment ?? "",
|
|
47
|
-
event_id: event.event_id ?? "",
|
|
48
|
-
transaction: event.transaction ?? "",
|
|
49
|
-
start_timestamp: event.start_timestamp ? event.start_timestamp * 1e3 : Date.now(),
|
|
50
|
-
trace_id: event.contexts?.trace?.trace_id ?? "",
|
|
51
|
-
profile_id: profile.profile_id
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
function createProfilePayload(client, cpuProfile, {
|
|
55
|
-
release,
|
|
56
|
-
environment,
|
|
57
|
-
event_id,
|
|
58
|
-
transaction,
|
|
59
|
-
start_timestamp,
|
|
60
|
-
trace_id,
|
|
61
|
-
profile_id
|
|
62
|
-
}) {
|
|
63
|
-
if (trace_id?.length !== 32) {
|
|
64
|
-
DEBUG_BUILD && debug.log(`[Profiling] Invalid traceId: ${trace_id} on profiled event`);
|
|
65
|
-
}
|
|
66
|
-
const enrichedThreadProfile = enrichWithThreadInformation(cpuProfile);
|
|
67
|
-
const profile = {
|
|
68
|
-
event_id: profile_id,
|
|
69
|
-
timestamp: new Date(start_timestamp).toISOString(),
|
|
70
|
-
platform: "node",
|
|
71
|
-
version: FORMAT_VERSION,
|
|
72
|
-
release,
|
|
73
|
-
environment,
|
|
74
|
-
measurements: cpuProfile.measurements,
|
|
75
|
-
runtime: {
|
|
76
|
-
name: "node",
|
|
77
|
-
version: versions.node || ""
|
|
78
|
-
},
|
|
79
|
-
os: {
|
|
80
|
-
name: PLATFORM,
|
|
81
|
-
version: RELEASE,
|
|
82
|
-
build_number: VERSION
|
|
83
|
-
},
|
|
84
|
-
device: {
|
|
85
|
-
locale: env["LC_ALL"] || env["LC_MESSAGES"] || env["LANG"] || env["LANGUAGE"] || "",
|
|
86
|
-
model: MODEL,
|
|
87
|
-
manufacturer: TYPE,
|
|
88
|
-
architecture: ARCH,
|
|
89
|
-
is_emulator: false
|
|
90
|
-
},
|
|
91
|
-
debug_meta: {
|
|
92
|
-
images: applyDebugMetadata(client, cpuProfile.resources)
|
|
93
|
-
},
|
|
94
|
-
profile: enrichedThreadProfile,
|
|
95
|
-
transaction: {
|
|
96
|
-
name: transaction,
|
|
97
|
-
id: event_id,
|
|
98
|
-
trace_id: trace_id || "",
|
|
99
|
-
active_thread_id: PROFILER_THREAD_ID_STRING
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
return profile;
|
|
103
|
-
}
|
|
104
31
|
function createProfileChunkPayload(client, cpuProfile, {
|
|
105
32
|
release,
|
|
106
33
|
environment,
|
|
@@ -145,37 +72,6 @@ function createProfilingChunkEvent(client, options, profile, sdk, identifiers) {
|
|
|
145
72
|
sdk
|
|
146
73
|
});
|
|
147
74
|
}
|
|
148
|
-
function isValidSampleRate(rate) {
|
|
149
|
-
if (typeof rate !== "number" && typeof rate !== "boolean" || typeof rate === "number" && isNaN(rate)) {
|
|
150
|
-
DEBUG_BUILD && debug.warn(
|
|
151
|
-
`[Profiling] Invalid sample rate. Sample rate must be a boolean or a number between 0 and 1. Got ${JSON.stringify(
|
|
152
|
-
rate
|
|
153
|
-
)} of type ${JSON.stringify(typeof rate)}.`
|
|
154
|
-
);
|
|
155
|
-
return false;
|
|
156
|
-
}
|
|
157
|
-
if (rate === true || rate === false) {
|
|
158
|
-
return true;
|
|
159
|
-
}
|
|
160
|
-
if (rate < 0 || rate > 1) {
|
|
161
|
-
DEBUG_BUILD && debug.warn(`[Profiling] Invalid sample rate. Sample rate must be between 0 and 1. Got ${rate}.`);
|
|
162
|
-
return false;
|
|
163
|
-
}
|
|
164
|
-
return true;
|
|
165
|
-
}
|
|
166
|
-
function isValidProfile(profile) {
|
|
167
|
-
if (profile.samples.length <= 1) {
|
|
168
|
-
DEBUG_BUILD && // Log a warning if the profile has less than 2 samples so users can know why
|
|
169
|
-
// they are not seeing any profiling data and we cant avoid the back and forth
|
|
170
|
-
// of asking them to provide us with a dump of the profile data.
|
|
171
|
-
debug.log("[Profiling] Discarding profile because it contains less than 2 samples");
|
|
172
|
-
return false;
|
|
173
|
-
}
|
|
174
|
-
if (!profile.profile_id) {
|
|
175
|
-
return false;
|
|
176
|
-
}
|
|
177
|
-
return true;
|
|
178
|
-
}
|
|
179
75
|
function isValidProfileChunk(profile) {
|
|
180
76
|
if (profile.samples.length <= 1) {
|
|
181
77
|
DEBUG_BUILD && // Log a warning if the profile has less than 2 samples so users can know why
|
|
@@ -186,34 +82,6 @@ function isValidProfileChunk(profile) {
|
|
|
186
82
|
}
|
|
187
83
|
return true;
|
|
188
84
|
}
|
|
189
|
-
function addProfilesToEnvelope(envelope, profiles) {
|
|
190
|
-
if (!profiles.length) {
|
|
191
|
-
return envelope;
|
|
192
|
-
}
|
|
193
|
-
for (const profile of profiles) {
|
|
194
|
-
envelope[1].push([{ type: "profile" }, profile]);
|
|
195
|
-
}
|
|
196
|
-
return envelope;
|
|
197
|
-
}
|
|
198
|
-
function findProfiledTransactionsFromEnvelope(envelope) {
|
|
199
|
-
const events = [];
|
|
200
|
-
forEachEnvelopeItem(envelope, (item, type) => {
|
|
201
|
-
if (type !== "transaction") {
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
for (let j = 1; j < item.length; j++) {
|
|
205
|
-
const event = item[j];
|
|
206
|
-
if (!event) {
|
|
207
|
-
continue;
|
|
208
|
-
}
|
|
209
|
-
const profile_id = event.contexts?.profile?.profile_id;
|
|
210
|
-
if (event && profile_id) {
|
|
211
|
-
events.push(event);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
return events;
|
|
216
|
-
}
|
|
217
85
|
function createEventEnvelopeHeaders(sdkInfo, tunnel, dsn) {
|
|
218
86
|
return {
|
|
219
87
|
event_id: uuid4(),
|
|
@@ -239,94 +107,11 @@ function applyDebugMetadata(client, resource_paths) {
|
|
|
239
107
|
return getDebugImagesForResources(options.stackParser, resource_paths);
|
|
240
108
|
}
|
|
241
109
|
|
|
242
|
-
const MAX_PROFILE_DURATION_MS = 30 * 1e3;
|
|
243
|
-
function maybeProfileSpan(client, span, customSamplingContext) {
|
|
244
|
-
if (!isMainThread) {
|
|
245
|
-
DEBUG_BUILD && debug.log("[Profiling] Skipping span profiling in worker thread.");
|
|
246
|
-
return;
|
|
247
|
-
}
|
|
248
|
-
if (!spanIsSampled(span)) {
|
|
249
|
-
return;
|
|
250
|
-
}
|
|
251
|
-
if (!client) {
|
|
252
|
-
DEBUG_BUILD && debug.log("[Profiling] Profiling disabled, no client found.");
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
const options = client.getOptions();
|
|
256
|
-
if (!options) {
|
|
257
|
-
DEBUG_BUILD && debug.log("[Profiling] Profiling disabled, no options found.");
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
const profilesSampler = options.profilesSampler;
|
|
261
|
-
let profilesSampleRate = options.profilesSampleRate;
|
|
262
|
-
if (typeof profilesSampler === "function") {
|
|
263
|
-
const { description: spanName = "<unknown>", data } = spanToJSON(span);
|
|
264
|
-
const parentSampled = true;
|
|
265
|
-
profilesSampleRate = profilesSampler({
|
|
266
|
-
name: spanName,
|
|
267
|
-
attributes: data,
|
|
268
|
-
parentSampled,
|
|
269
|
-
...customSamplingContext
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
if (!isValidSampleRate(profilesSampleRate)) {
|
|
273
|
-
DEBUG_BUILD && debug.warn("[Profiling] Discarding profile because of invalid sample rate.");
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
if (!profilesSampleRate) {
|
|
277
|
-
DEBUG_BUILD && debug.log(
|
|
278
|
-
`[Profiling] Discarding profile because ${typeof profilesSampler === "function" ? "profileSampler returned 0 or false" : "a negative sampling decision was inherited or profileSampleRate is set to 0"}`
|
|
279
|
-
);
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
const sampled = profilesSampleRate === true ? true : Math.random() < profilesSampleRate;
|
|
283
|
-
if (!sampled) {
|
|
284
|
-
DEBUG_BUILD && debug.log(
|
|
285
|
-
`[Profiling] Discarding profile because it's not included in the random sample (sampling rate = ${Number(
|
|
286
|
-
profilesSampleRate
|
|
287
|
-
)})`
|
|
288
|
-
);
|
|
289
|
-
return;
|
|
290
|
-
}
|
|
291
|
-
const profile_id = uuid4();
|
|
292
|
-
CpuProfilerBindings.startProfiling(profile_id);
|
|
293
|
-
DEBUG_BUILD && debug.log(`[Profiling] started profiling transaction: ${spanToJSON(span).description}`);
|
|
294
|
-
return profile_id;
|
|
295
|
-
}
|
|
296
|
-
function stopSpanProfile(span, profile_id) {
|
|
297
|
-
if (!profile_id) {
|
|
298
|
-
return null;
|
|
299
|
-
}
|
|
300
|
-
const profile = CpuProfilerBindings.stopProfiling(profile_id, 0);
|
|
301
|
-
DEBUG_BUILD && debug.log(`[Profiling] stopped profiling of transaction: ${spanToJSON(span).description}`);
|
|
302
|
-
if (!profile) {
|
|
303
|
-
DEBUG_BUILD && debug.log(
|
|
304
|
-
`[Profiling] profiler returned null profile for: ${spanToJSON(span).description}`,
|
|
305
|
-
"this may indicate an overlapping span or a call to stopProfiling with a profile title that was never started"
|
|
306
|
-
);
|
|
307
|
-
return null;
|
|
308
|
-
}
|
|
309
|
-
profile.profile_id = profile_id;
|
|
310
|
-
return profile;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
110
|
const CHUNK_INTERVAL_MS = 1e3 * 60;
|
|
314
|
-
const PROFILE_MAP = new LRUMap(50);
|
|
315
|
-
const PROFILE_TIMEOUTS = {};
|
|
316
|
-
function addToProfileQueue(profile_id, profile) {
|
|
317
|
-
PROFILE_MAP.set(profile_id, profile);
|
|
318
|
-
}
|
|
319
|
-
function takeFromProfileQueue(profile_id) {
|
|
320
|
-
const profile = PROFILE_MAP.get(profile_id);
|
|
321
|
-
PROFILE_MAP.remove(profile_id);
|
|
322
|
-
return profile;
|
|
323
|
-
}
|
|
324
111
|
class ContinuousProfiler {
|
|
325
112
|
constructor() {
|
|
326
113
|
this._client = void 0;
|
|
327
114
|
this._chunkData = void 0;
|
|
328
|
-
this._mode = void 0;
|
|
329
|
-
this._legacyProfilerMode = void 0;
|
|
330
115
|
this._profileLifecycle = void 0;
|
|
331
116
|
this._sampled = void 0;
|
|
332
117
|
this._sessionSamplingRate = void 0;
|
|
@@ -345,51 +130,21 @@ class ContinuousProfiler {
|
|
|
345
130
|
}
|
|
346
131
|
this._client = client;
|
|
347
132
|
const options = client.getOptions();
|
|
348
|
-
this._mode = getProfilingMode(options);
|
|
349
133
|
this._sessionSamplingRate = Math.random();
|
|
350
134
|
this._sampled = this._sessionSamplingRate < (options.profileSessionSampleRate ?? 0);
|
|
351
135
|
this._profileLifecycle = options.profileLifecycle ?? "manual";
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
case "span": {
|
|
358
|
-
this._setupAutomaticSpanProfiling();
|
|
359
|
-
break;
|
|
360
|
-
}
|
|
361
|
-
case "continuous": {
|
|
362
|
-
break;
|
|
363
|
-
}
|
|
364
|
-
default: {
|
|
365
|
-
DEBUG_BUILD && debug.warn(
|
|
366
|
-
`[Profiling] Unknown profiler mode: ${this._legacyProfilerMode}, profiler was not initialized`
|
|
367
|
-
);
|
|
368
|
-
break;
|
|
369
|
-
}
|
|
370
|
-
}
|
|
136
|
+
this._setupSpanChunkInstrumentation();
|
|
137
|
+
DEBUG_BUILD && debug.log(`[Profiling] Profiling mode is ${this._profileLifecycle}.`);
|
|
138
|
+
switch (this._profileLifecycle) {
|
|
139
|
+
case "trace": {
|
|
140
|
+
this._startTraceLifecycleProfiling();
|
|
371
141
|
break;
|
|
372
142
|
}
|
|
373
|
-
case "
|
|
374
|
-
this._setupSpanChunkInstrumentation();
|
|
375
|
-
DEBUG_BUILD && debug.log(`[Profiling] Profiling mode is ${this._profileLifecycle}.`);
|
|
376
|
-
switch (this._profileLifecycle) {
|
|
377
|
-
case "trace": {
|
|
378
|
-
this._startTraceLifecycleProfiling();
|
|
379
|
-
break;
|
|
380
|
-
}
|
|
381
|
-
case "manual": {
|
|
382
|
-
break;
|
|
383
|
-
}
|
|
384
|
-
default: {
|
|
385
|
-
DEBUG_BUILD && debug.warn(`[Profiling] Unknown profiler mode: ${this._profileLifecycle}, profiler was not initialized`);
|
|
386
|
-
break;
|
|
387
|
-
}
|
|
388
|
-
}
|
|
143
|
+
case "manual": {
|
|
389
144
|
break;
|
|
390
145
|
}
|
|
391
146
|
default: {
|
|
392
|
-
DEBUG_BUILD && debug.warn(`[Profiling] Unknown profiler mode: ${this.
|
|
147
|
+
DEBUG_BUILD && debug.warn(`[Profiling] Unknown profiler mode: ${this._profileLifecycle}, profiler was not initialized`);
|
|
393
148
|
break;
|
|
394
149
|
}
|
|
395
150
|
}
|
|
@@ -400,64 +155,26 @@ class ContinuousProfiler {
|
|
|
400
155
|
* @returns void
|
|
401
156
|
*/
|
|
402
157
|
start() {
|
|
403
|
-
if (this._mode === "current") {
|
|
404
|
-
this._startProfiler();
|
|
405
|
-
return;
|
|
406
|
-
}
|
|
407
158
|
if (!this._client) {
|
|
408
|
-
DEBUG_BUILD && debug.log("[Profiling] Failed to start,
|
|
409
|
-
return;
|
|
410
|
-
}
|
|
411
|
-
if (this._mode !== "legacy") {
|
|
412
|
-
DEBUG_BUILD && debug.log("[Profiling] Continuous profiling is not supported in the current mode.");
|
|
413
|
-
return;
|
|
414
|
-
}
|
|
415
|
-
if (this._legacyProfilerMode === "span") {
|
|
416
|
-
DEBUG_BUILD && debug.log("[Profiling] Calls to profiler.start() are not supported in span profiling mode.");
|
|
159
|
+
DEBUG_BUILD && debug.log("[Profiling] Failed to start, Sentry client was never attached to the profiler.");
|
|
417
160
|
return;
|
|
418
161
|
}
|
|
419
|
-
this.
|
|
420
|
-
this._setupSpanChunkInstrumentation();
|
|
421
|
-
this._restartChunkProfiling();
|
|
162
|
+
this._startProfiler();
|
|
422
163
|
}
|
|
423
164
|
/**
|
|
424
165
|
* Stops the current chunk and flushes the profile to Sentry.
|
|
425
|
-
* @returns void
|
|
426
166
|
*/
|
|
427
167
|
stop() {
|
|
428
|
-
|
|
429
|
-
this._stopProfiler();
|
|
430
|
-
return;
|
|
431
|
-
}
|
|
432
|
-
if (!this._client) {
|
|
433
|
-
DEBUG_BUILD && debug.log("[Profiling] Failed to stop, sentry client was never attached to the profiler.");
|
|
434
|
-
return;
|
|
435
|
-
}
|
|
436
|
-
if (this._mode !== "legacy") {
|
|
437
|
-
DEBUG_BUILD && debug.log("[Profiling] Continuous profiling is not supported in the current mode.");
|
|
438
|
-
return;
|
|
439
|
-
}
|
|
440
|
-
if (this._legacyProfilerMode === "span") {
|
|
441
|
-
DEBUG_BUILD && debug.log("[Profiling] Calls to profiler.stop() are not supported in span profiling mode.");
|
|
442
|
-
return;
|
|
443
|
-
}
|
|
444
|
-
this._stopChunkProfiling();
|
|
445
|
-
this._teardownSpanChunkInstrumentation();
|
|
168
|
+
this._stopProfiler();
|
|
446
169
|
}
|
|
447
170
|
_startProfiler() {
|
|
448
|
-
if (this._mode !== "current") {
|
|
449
|
-
DEBUG_BUILD && debug.log("[Profiling] Continuous profiling is not supported in the current mode.");
|
|
450
|
-
return;
|
|
451
|
-
}
|
|
452
171
|
if (this._chunkData !== void 0) {
|
|
453
172
|
DEBUG_BUILD && debug.log("[Profiling] Profile session already running, no-op.");
|
|
454
173
|
return;
|
|
455
174
|
}
|
|
456
|
-
if (this.
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
return;
|
|
460
|
-
}
|
|
175
|
+
if (!this._sampled) {
|
|
176
|
+
DEBUG_BUILD && debug.log("[Profiling] Profile session not sampled, no-op.");
|
|
177
|
+
return;
|
|
461
178
|
}
|
|
462
179
|
if (this._profileLifecycle === "trace") {
|
|
463
180
|
DEBUG_BUILD && debug.log(
|
|
@@ -468,10 +185,6 @@ class ContinuousProfiler {
|
|
|
468
185
|
this._startChunkProfiling();
|
|
469
186
|
}
|
|
470
187
|
_stopProfiler() {
|
|
471
|
-
if (this._mode !== "current") {
|
|
472
|
-
DEBUG_BUILD && debug.log("[Profiling] Continuous profiling is not supported in the current mode.");
|
|
473
|
-
return;
|
|
474
|
-
}
|
|
475
188
|
if (this._profileLifecycle === "trace") {
|
|
476
189
|
DEBUG_BUILD && debug.log(
|
|
477
190
|
"[Profiling] You are using the trace profile lifecycle, manual calls to profiler.startProfiler() and profiler.stopProfiler() will be ignored."
|
|
@@ -512,90 +225,6 @@ class ContinuousProfiler {
|
|
|
512
225
|
activeSpanCounter--;
|
|
513
226
|
});
|
|
514
227
|
}
|
|
515
|
-
_setupAutomaticSpanProfiling() {
|
|
516
|
-
if (!this._client) {
|
|
517
|
-
DEBUG_BUILD && debug.log(
|
|
518
|
-
"[Profiling] Failed to setup automatic span profiling, sentry client was never attached to the profiler."
|
|
519
|
-
);
|
|
520
|
-
return;
|
|
521
|
-
}
|
|
522
|
-
const spanToProfileIdMap = /* @__PURE__ */ new WeakMap();
|
|
523
|
-
this._client.on("spanStart", (span) => {
|
|
524
|
-
if (span !== getRootSpan(span)) {
|
|
525
|
-
return;
|
|
526
|
-
}
|
|
527
|
-
const profile_id = maybeProfileSpan(this._client, span);
|
|
528
|
-
if (profile_id) {
|
|
529
|
-
const options = this._client.getOptions();
|
|
530
|
-
const maxProfileDurationMs = options._experiments?.maxProfileDurationMs || MAX_PROFILE_DURATION_MS;
|
|
531
|
-
if (PROFILE_TIMEOUTS[profile_id]) {
|
|
532
|
-
global.clearTimeout(PROFILE_TIMEOUTS[profile_id]);
|
|
533
|
-
delete PROFILE_TIMEOUTS[profile_id];
|
|
534
|
-
}
|
|
535
|
-
const timeout = global.setTimeout(() => {
|
|
536
|
-
DEBUG_BUILD && debug.log(
|
|
537
|
-
"[Profiling] max profile duration elapsed, stopping profiling for:",
|
|
538
|
-
spanToJSON(span).description
|
|
539
|
-
);
|
|
540
|
-
const profile = stopSpanProfile(span, profile_id);
|
|
541
|
-
if (profile) {
|
|
542
|
-
addToProfileQueue(profile_id, profile);
|
|
543
|
-
}
|
|
544
|
-
}, maxProfileDurationMs);
|
|
545
|
-
timeout.unref();
|
|
546
|
-
getIsolationScope().setContext("profile", { profile_id });
|
|
547
|
-
spanToProfileIdMap.set(span, profile_id);
|
|
548
|
-
}
|
|
549
|
-
});
|
|
550
|
-
this._client.on("spanEnd", (span) => {
|
|
551
|
-
const profile_id = spanToProfileIdMap.get(span);
|
|
552
|
-
if (profile_id) {
|
|
553
|
-
if (PROFILE_TIMEOUTS[profile_id]) {
|
|
554
|
-
global.clearTimeout(PROFILE_TIMEOUTS[profile_id]);
|
|
555
|
-
delete PROFILE_TIMEOUTS[profile_id];
|
|
556
|
-
}
|
|
557
|
-
const profile = stopSpanProfile(span, profile_id);
|
|
558
|
-
if (profile) {
|
|
559
|
-
addToProfileQueue(profile_id, profile);
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
});
|
|
563
|
-
this._client.on("beforeEnvelope", (envelope) => {
|
|
564
|
-
if (!PROFILE_MAP.size) {
|
|
565
|
-
return;
|
|
566
|
-
}
|
|
567
|
-
const profiledTransactionEvents = findProfiledTransactionsFromEnvelope(envelope);
|
|
568
|
-
if (!profiledTransactionEvents.length) {
|
|
569
|
-
return;
|
|
570
|
-
}
|
|
571
|
-
const profilesToAddToEnvelope = [];
|
|
572
|
-
for (const profiledTransaction of profiledTransactionEvents) {
|
|
573
|
-
const profileContext = profiledTransaction.contexts?.profile;
|
|
574
|
-
const profile_id = profileContext?.profile_id;
|
|
575
|
-
if (!profile_id) {
|
|
576
|
-
throw new TypeError("[Profiling] cannot find profile for a transaction without a profile context");
|
|
577
|
-
}
|
|
578
|
-
if (profileContext) {
|
|
579
|
-
delete profiledTransaction.contexts?.profile;
|
|
580
|
-
}
|
|
581
|
-
const cpuProfile = takeFromProfileQueue(profile_id);
|
|
582
|
-
if (!cpuProfile) {
|
|
583
|
-
DEBUG_BUILD && debug.log(`[Profiling] Could not retrieve profile for transaction: ${profile_id}`);
|
|
584
|
-
continue;
|
|
585
|
-
}
|
|
586
|
-
const profile = createProfilingEvent(this._client, cpuProfile, profiledTransaction);
|
|
587
|
-
if (!profile) return;
|
|
588
|
-
profilesToAddToEnvelope.push(profile);
|
|
589
|
-
this._client.emit("preprocessEvent", profile, {
|
|
590
|
-
event_id: profiledTransaction.event_id
|
|
591
|
-
});
|
|
592
|
-
this._client.emit("postprocessEvent", profile, {
|
|
593
|
-
event_id: profiledTransaction.event_id
|
|
594
|
-
});
|
|
595
|
-
}
|
|
596
|
-
addProfilesToEnvelope(envelope, profilesToAddToEnvelope);
|
|
597
|
-
});
|
|
598
|
-
}
|
|
599
228
|
/**
|
|
600
229
|
* Stop profiler and initializes profiling of the next chunk
|
|
601
230
|
*/
|
|
@@ -799,15 +428,6 @@ const _nodeProfilingIntegration = (() => {
|
|
|
799
428
|
}
|
|
800
429
|
};
|
|
801
430
|
});
|
|
802
|
-
function getProfilingMode(options) {
|
|
803
|
-
if ("profilesSampleRate" in options || "profilesSampler" in options) {
|
|
804
|
-
return "legacy";
|
|
805
|
-
}
|
|
806
|
-
if ("profileSessionSampleRate" in options || "profileLifecycle" in options) {
|
|
807
|
-
return "current";
|
|
808
|
-
}
|
|
809
|
-
return "legacy";
|
|
810
|
-
}
|
|
811
431
|
const nodeProfilingIntegration = defineIntegration(_nodeProfilingIntegration);
|
|
812
432
|
|
|
813
433
|
export { nodeProfilingIntegration };
|