@sentry/profiling-node 8.29.0 → 8.31.0-beta.0
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/bindings/cpu_profiler.cc +16 -15
- package/lib/cjs/index.js +73 -34
- package/lib/cjs/index.js.map +1 -1
- package/lib/esm/index.js +89 -43
- package/lib/esm/index.js.map +1 -1
- package/lib/sentry_cpu_profiler-darwin-arm64-108.node +0 -0
- package/lib/sentry_cpu_profiler-darwin-arm64-115.node +0 -0
- package/lib/sentry_cpu_profiler-darwin-arm64-127.node +0 -0
- package/lib/sentry_cpu_profiler-darwin-arm64-93.node +0 -0
- package/lib/sentry_cpu_profiler-darwin-x64-108.node +0 -0
- package/lib/sentry_cpu_profiler-darwin-x64-115.node +0 -0
- package/lib/sentry_cpu_profiler-darwin-x64-127.node +0 -0
- package/lib/sentry_cpu_profiler-darwin-x64-93.node +0 -0
- package/lib/sentry_cpu_profiler-linux-arm64-glibc-108.node +0 -0
- package/lib/sentry_cpu_profiler-linux-arm64-glibc-115.node +0 -0
- package/lib/sentry_cpu_profiler-linux-arm64-glibc-127.node +0 -0
- package/lib/sentry_cpu_profiler-linux-arm64-glibc-93.node +0 -0
- package/lib/sentry_cpu_profiler-linux-arm64-musl-108.node +0 -0
- package/lib/sentry_cpu_profiler-linux-arm64-musl-115.node +0 -0
- package/lib/sentry_cpu_profiler-linux-arm64-musl-127.node +0 -0
- package/lib/sentry_cpu_profiler-linux-arm64-musl-93.node +0 -0
- package/lib/sentry_cpu_profiler-linux-x64-glibc-108.node +0 -0
- package/lib/sentry_cpu_profiler-linux-x64-glibc-115.node +0 -0
- package/lib/sentry_cpu_profiler-linux-x64-glibc-127.node +0 -0
- package/lib/sentry_cpu_profiler-linux-x64-glibc-93.node +0 -0
- package/lib/sentry_cpu_profiler-linux-x64-musl-108.node +0 -0
- package/lib/sentry_cpu_profiler-linux-x64-musl-115.node +0 -0
- package/lib/sentry_cpu_profiler-linux-x64-musl-127.node +0 -0
- package/lib/sentry_cpu_profiler-linux-x64-musl-93.node +0 -0
- package/lib/sentry_cpu_profiler-win32-x64-108.node +0 -0
- package/lib/sentry_cpu_profiler-win32-x64-115.node +0 -0
- package/lib/sentry_cpu_profiler-win32-x64-127.node +0 -0
- package/lib/sentry_cpu_profiler-win32-x64-93.node +0 -0
- package/lib/types/cpu_profiler.d.ts.map +1 -1
- package/lib/types/integration.d.ts.map +1 -1
- package/package.json +5 -5
package/lib/esm/index.js
CHANGED
|
@@ -2,23 +2,17 @@ import { _nullishCoalesce, _optionalChain, _optionalChainDelete } from '@sentry/
|
|
|
2
2
|
import { spanIsSampled, spanToJSON, defineIntegration, getRootSpan, getCurrentScope, getIsolationScope, getGlobalScope } from '@sentry/core';
|
|
3
3
|
import { logger, GLOBAL_OBJ, parseSemver, forEachEnvelopeItem, createEnvelope, uuid4, dsnToString, LRUMap } from '@sentry/utils';
|
|
4
4
|
import { platform as platform$1, arch as arch$1 } from 'node:os';
|
|
5
|
-
import { resolve, join } from 'node:path';
|
|
5
|
+
import cjsPath, { resolve, join } from 'node:path';
|
|
6
6
|
import { versions, env } from 'node:process';
|
|
7
7
|
import { threadId } from 'node:worker_threads';
|
|
8
8
|
import { familySync } from 'detect-libc';
|
|
9
9
|
import { getAbi } from 'node-abi';
|
|
10
|
+
import cjsUrl from 'node:url';
|
|
11
|
+
import cjsModule from 'node:module';
|
|
10
12
|
import * as os from 'os';
|
|
11
13
|
import { versions as versions$1, env as env$1 } from 'process';
|
|
12
14
|
import { threadId as threadId$1, isMainThread } from 'worker_threads';
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
// -- Shims --
|
|
16
|
-
import cjsUrl from 'node:url';
|
|
17
|
-
import cjsPath from 'node:path';
|
|
18
|
-
import cjsModule from 'node:module';
|
|
19
|
-
const __filename = cjsUrl.fileURLToPath(import.meta.url);
|
|
20
|
-
const __dirname = cjsPath.dirname(__filename);
|
|
21
|
-
const require = cjsModule.createRequire(import.meta.url);
|
|
22
16
|
/**
|
|
23
17
|
* This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code.
|
|
24
18
|
*
|
|
@@ -26,6 +20,19 @@ const require = cjsModule.createRequire(import.meta.url);
|
|
|
26
20
|
*/
|
|
27
21
|
const DEBUG_BUILD = (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__);
|
|
28
22
|
|
|
23
|
+
if(typeof __filename === 'undefined'){
|
|
24
|
+
globalThis.__filename = cjsUrl.fileURLToPath(import.meta.url);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if(typeof __dirname === 'undefined'){
|
|
28
|
+
globalThis.__dirname = cjsPath.dirname(__filename);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if(typeof require === 'undefined'){
|
|
32
|
+
globalThis.require = cjsModule.createRequire(import.meta.url);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
29
36
|
const stdlib = familySync();
|
|
30
37
|
const platform = process.env['BUILD_PLATFORM'] || platform$1();
|
|
31
38
|
const arch = process.env['BUILD_ARCH'] || arch$1();
|
|
@@ -905,10 +912,10 @@ function setupAutomatedSpanProfiling(client) {
|
|
|
905
912
|
});
|
|
906
913
|
}
|
|
907
914
|
|
|
908
|
-
class ContinuousProfiler {constructor() { ContinuousProfiler.prototype.__init.call(this);ContinuousProfiler.prototype.__init2.call(this);
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
915
|
+
class ContinuousProfiler {constructor() { ContinuousProfiler.prototype.__init.call(this);ContinuousProfiler.prototype.__init2.call(this); }
|
|
916
|
+
|
|
917
|
+
__init() {this._client = undefined;}
|
|
918
|
+
__init2() {this._chunkData = undefined;}
|
|
912
919
|
|
|
913
920
|
/**
|
|
914
921
|
* Called when the profiler is attached to the client (continuous mode is enabled). If of the profiler
|
|
@@ -917,15 +924,48 @@ class ContinuousProfiler {constructor() { ContinuousProfiler.prototype.__init.ca
|
|
|
917
924
|
*/
|
|
918
925
|
initialize(client) {
|
|
919
926
|
this._client = client;
|
|
927
|
+
|
|
928
|
+
// Attaches a listener to beforeSend which will add the threadId data to the event being sent.
|
|
929
|
+
// This adds a constant overhead to all events being sent which could be improved to only attach
|
|
930
|
+
// and detach the listener during a profiler session
|
|
931
|
+
this._client.on('beforeSendEvent', this._onBeforeSendThreadContextAssignment.bind(this));
|
|
920
932
|
}
|
|
921
933
|
|
|
922
934
|
/**
|
|
923
|
-
*
|
|
924
|
-
* Once the user calls stop(), the current chunk will be stopped and flushed to Sentry and no new chunks will
|
|
925
|
-
* will be started. To restart continuous mode after calling stop(), the user must call start() again.
|
|
935
|
+
* Initializes a new profilerId session and schedules chunk profiling.
|
|
926
936
|
* @returns void
|
|
927
937
|
*/
|
|
928
938
|
start() {
|
|
939
|
+
if (!this._client) {
|
|
940
|
+
DEBUG_BUILD && logger.log('[Profiling] Failed to start, sentry client was never attached to the profiler.');
|
|
941
|
+
return;
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
// Flush any existing chunks before starting a new one.
|
|
945
|
+
this._chunkStop();
|
|
946
|
+
|
|
947
|
+
// Restart the profiler session
|
|
948
|
+
this._setupSpanChunkInstrumentation();
|
|
949
|
+
this._chunkStart();
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
/**
|
|
953
|
+
* Stops the current chunk and flushes the profile to Sentry.
|
|
954
|
+
* @returns void
|
|
955
|
+
*/
|
|
956
|
+
stop() {
|
|
957
|
+
if (!this._client) {
|
|
958
|
+
DEBUG_BUILD && logger.log('[Profiling] Failed to stop, sentry client was never attached to the profiler.');
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
961
|
+
this._chunkStop();
|
|
962
|
+
this._teardownSpanChunkInstrumentation();
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
/**
|
|
966
|
+
* Stop profiler and initializes profiling of the next chunk
|
|
967
|
+
*/
|
|
968
|
+
_chunkStart() {
|
|
929
969
|
if (!this._client) {
|
|
930
970
|
// The client is not attached to the profiler if the user has not enabled continuous profiling.
|
|
931
971
|
// In this case, calling start() and stop() is a noop action.The reason this exists is because
|
|
@@ -938,20 +978,16 @@ class ContinuousProfiler {constructor() { ContinuousProfiler.prototype.__init.ca
|
|
|
938
978
|
logger.log(
|
|
939
979
|
`[Profiling] Chunk with chunk_id ${this._chunkData.id} is still running, current chunk will be stopped a new chunk will be started.`,
|
|
940
980
|
);
|
|
941
|
-
this.
|
|
981
|
+
this._chunkStop();
|
|
942
982
|
}
|
|
943
983
|
|
|
944
|
-
|
|
945
|
-
getCurrentScope().getPropagationContext().traceId || getIsolationScope().getPropagationContext().traceId;
|
|
946
|
-
this._initializeChunk(traceId);
|
|
947
|
-
this._startChunkProfiling(this._chunkData);
|
|
984
|
+
this._startChunkProfiling();
|
|
948
985
|
}
|
|
949
986
|
|
|
950
987
|
/**
|
|
951
|
-
* Stops the current
|
|
952
|
-
* @returns void
|
|
988
|
+
* Stops profiling of the current chunks and flushes the profile to Sentry
|
|
953
989
|
*/
|
|
954
|
-
|
|
990
|
+
_chunkStop() {
|
|
955
991
|
if (_optionalChain([this, 'access', _6 => _6._chunkData, 'optionalAccess', _7 => _7.timer])) {
|
|
956
992
|
global.clearTimeout(this._chunkData.timer);
|
|
957
993
|
this._chunkData.timer = undefined;
|
|
@@ -968,12 +1004,17 @@ class ContinuousProfiler {constructor() { ContinuousProfiler.prototype.__init.ca
|
|
|
968
1004
|
return;
|
|
969
1005
|
}
|
|
970
1006
|
|
|
971
|
-
const profile =
|
|
1007
|
+
const profile = CpuProfilerBindings.stopProfiling(this._chunkData.id, ProfileFormat.CHUNK);
|
|
972
1008
|
|
|
973
1009
|
if (!profile) {
|
|
974
1010
|
DEBUG_BUILD && logger.log(`[Profiling] _chunkiledStartTraceID to collect profile for: ${this._chunkData.id}`);
|
|
975
1011
|
return;
|
|
976
1012
|
}
|
|
1013
|
+
if (!this._profilerId) {
|
|
1014
|
+
DEBUG_BUILD &&
|
|
1015
|
+
logger.log('[Profiling] Profile chunk does not contain a valid profiler_id, this is a bug in the SDK');
|
|
1016
|
+
return;
|
|
1017
|
+
}
|
|
977
1018
|
if (profile) {
|
|
978
1019
|
DEBUG_BUILD && logger.log(`[Profiling] Sending profile chunk ${this._chunkData.id}.`);
|
|
979
1020
|
}
|
|
@@ -993,7 +1034,7 @@ class ContinuousProfiler {constructor() { ContinuousProfiler.prototype.__init.ca
|
|
|
993
1034
|
|
|
994
1035
|
if (!chunk) {
|
|
995
1036
|
DEBUG_BUILD && logger.log(`[Profiling] Failed to create profile chunk for: ${this._chunkData.id}`);
|
|
996
|
-
this.
|
|
1037
|
+
this._resetChunkData();
|
|
997
1038
|
return;
|
|
998
1039
|
}
|
|
999
1040
|
|
|
@@ -1002,7 +1043,7 @@ class ContinuousProfiler {constructor() { ContinuousProfiler.prototype.__init.ca
|
|
|
1002
1043
|
// the format may negatively impact the performance of the application. To avoid
|
|
1003
1044
|
// blocking for too long, enqueue the next chunk start inside the next macrotask.
|
|
1004
1045
|
// clear current chunk
|
|
1005
|
-
this.
|
|
1046
|
+
this._resetChunkData();
|
|
1006
1047
|
}
|
|
1007
1048
|
|
|
1008
1049
|
/**
|
|
@@ -1032,29 +1073,23 @@ class ContinuousProfiler {constructor() { ContinuousProfiler.prototype.__init.ca
|
|
|
1032
1073
|
});
|
|
1033
1074
|
}
|
|
1034
1075
|
|
|
1035
|
-
/**
|
|
1036
|
-
* Stops the profile and clears chunk instrumentation from global scope
|
|
1037
|
-
* @returns void
|
|
1038
|
-
*/
|
|
1039
|
-
_stopChunkProfiling(chunk) {
|
|
1040
|
-
this._teardownSpanChunkInstrumentation();
|
|
1041
|
-
return CpuProfilerBindings.stopProfiling(chunk.id, ProfileFormat.CHUNK);
|
|
1042
|
-
}
|
|
1043
|
-
|
|
1044
1076
|
/**
|
|
1045
1077
|
* Starts the profiler and registers the flush timer for a given chunk.
|
|
1046
1078
|
* @param chunk
|
|
1047
1079
|
*/
|
|
1048
|
-
_startChunkProfiling(
|
|
1049
|
-
|
|
1080
|
+
_startChunkProfiling() {
|
|
1081
|
+
const traceId =
|
|
1082
|
+
getCurrentScope().getPropagationContext().traceId || getIsolationScope().getPropagationContext().traceId;
|
|
1083
|
+
const chunk = this._initializeChunk(traceId);
|
|
1084
|
+
|
|
1050
1085
|
CpuProfilerBindings.startProfiling(chunk.id);
|
|
1051
1086
|
DEBUG_BUILD && logger.log(`[Profiling] starting profiling chunk: ${chunk.id}`);
|
|
1052
1087
|
|
|
1053
1088
|
chunk.timer = global.setTimeout(() => {
|
|
1054
1089
|
DEBUG_BUILD && logger.log(`[Profiling] Stopping profiling chunk: ${chunk.id}`);
|
|
1055
|
-
this.
|
|
1090
|
+
this._chunkStop();
|
|
1056
1091
|
DEBUG_BUILD && logger.log('[Profiling] Starting new profiling chunk.');
|
|
1057
|
-
setImmediate(this.
|
|
1092
|
+
setImmediate(this._chunkStart.bind(this));
|
|
1058
1093
|
}, CHUNK_INTERVAL_MS);
|
|
1059
1094
|
|
|
1060
1095
|
// Unref timeout so it doesn't keep the process alive.
|
|
@@ -1068,21 +1103,31 @@ class ContinuousProfiler {constructor() { ContinuousProfiler.prototype.__init.ca
|
|
|
1068
1103
|
_setupSpanChunkInstrumentation() {
|
|
1069
1104
|
if (!this._client) {
|
|
1070
1105
|
DEBUG_BUILD &&
|
|
1071
|
-
logger.log(
|
|
1106
|
+
logger.log(
|
|
1107
|
+
'[Profiling] Failed to initialize span profiling, sentry client was never attached to the profiler.',
|
|
1108
|
+
);
|
|
1072
1109
|
return;
|
|
1073
1110
|
}
|
|
1074
1111
|
|
|
1112
|
+
this._profilerId = uuid4();
|
|
1075
1113
|
getGlobalScope().setContext('profile', {
|
|
1076
1114
|
profiler_id: this._profilerId,
|
|
1077
1115
|
});
|
|
1116
|
+
}
|
|
1078
1117
|
|
|
1079
|
-
|
|
1118
|
+
/**
|
|
1119
|
+
* Assigns thread_id and thread name context to a profiled event if there is an active profiler session
|
|
1120
|
+
*/
|
|
1121
|
+
_onBeforeSendThreadContextAssignment(event) {
|
|
1122
|
+
if (!this._client || !this._profilerId) return;
|
|
1123
|
+
this._assignThreadIdContext(event);
|
|
1080
1124
|
}
|
|
1081
1125
|
|
|
1082
1126
|
/**
|
|
1083
1127
|
* Clear profiling information from global context when a profile is not running.
|
|
1084
1128
|
*/
|
|
1085
1129
|
_teardownSpanChunkInstrumentation() {
|
|
1130
|
+
this._profilerId = undefined;
|
|
1086
1131
|
const globalScope = getGlobalScope();
|
|
1087
1132
|
globalScope.setContext('profile', {});
|
|
1088
1133
|
}
|
|
@@ -1096,6 +1141,7 @@ class ContinuousProfiler {constructor() { ContinuousProfiler.prototype.__init.ca
|
|
|
1096
1141
|
startTraceID: traceId,
|
|
1097
1142
|
timer: undefined,
|
|
1098
1143
|
};
|
|
1144
|
+
return this._chunkData;
|
|
1099
1145
|
}
|
|
1100
1146
|
|
|
1101
1147
|
/**
|
|
@@ -1125,7 +1171,7 @@ class ContinuousProfiler {constructor() { ContinuousProfiler.prototype.__init.ca
|
|
|
1125
1171
|
/**
|
|
1126
1172
|
* Resets the current chunk state.
|
|
1127
1173
|
*/
|
|
1128
|
-
|
|
1174
|
+
_resetChunkData() {
|
|
1129
1175
|
this._chunkData = undefined;
|
|
1130
1176
|
}
|
|
1131
1177
|
}
|
package/lib/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/debug-build.ts","../../src/cpu_profiler.ts","../../src/nodeVersion.ts","../../src/utils.ts","../../src/spanProfileUtils.ts","../../src/types.ts","../../src/integration.ts"],"sourcesContent":["declare const __DEBUG_BUILD__: boolean;\n\n/**\n * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code.\n *\n * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking.\n */\nexport const DEBUG_BUILD = __DEBUG_BUILD__;\n","import { arch as _arch, platform as _platform } from 'node:os';\nimport { join, resolve } from 'node:path';\nimport { env, versions } from 'node:process';\nimport { threadId } from 'node:worker_threads';\nimport { familySync } from 'detect-libc';\nimport { getAbi } from 'node-abi';\n\nimport { GLOBAL_OBJ, logger } from '@sentry/utils';\nimport { DEBUG_BUILD } from './debug-build';\nimport type {\n PrivateV8CpuProfilerBindings,\n RawChunkCpuProfile,\n RawThreadCpuProfile,\n V8CpuProfilerBindings,\n} from './types';\nimport type { ProfileFormat } from './types';\n\nconst stdlib = familySync();\nconst platform = process.env['BUILD_PLATFORM'] || _platform();\nconst arch = process.env['BUILD_ARCH'] || _arch();\nconst abi = getAbi(versions.node, 'node');\nconst identifier = [platform, arch, stdlib, abi].filter(c => c !== undefined && c !== null).join('-');\n\nconst built_from_source_path = resolve(__dirname, '..', `./sentry_cpu_profiler-${identifier}`);\n\n/**\n * Imports cpp bindings based on the current platform and architecture.\n */\n// eslint-disable-next-line complexity\nexport function importCppBindingsModule(): PrivateV8CpuProfilerBindings {\n // If a binary path is specified, use that.\n if (env['SENTRY_PROFILER_BINARY_PATH']) {\n const envPath = env['SENTRY_PROFILER_BINARY_PATH'];\n return require(envPath);\n }\n\n // If a user specifies a different binary dir, they are in control of the binaries being moved there\n if (env['SENTRY_PROFILER_BINARY_DIR']) {\n const binaryPath = join(resolve(env['SENTRY_PROFILER_BINARY_DIR']), `sentry_cpu_profiler-${identifier}`);\n return require(`${binaryPath}.node`);\n }\n\n // We need the fallthrough so that in the end, we can fallback to the require dynamice require.\n // This is for cases where precompiled binaries were not provided, but may have been compiled from source.\n if (platform === 'darwin') {\n if (arch === 'x64') {\n if (abi === '93') {\n return require('../sentry_cpu_profiler-darwin-x64-93.node');\n }\n if (abi === '108') {\n return require('../sentry_cpu_profiler-darwin-x64-108.node');\n }\n if (abi === '115') {\n return require('../sentry_cpu_profiler-darwin-x64-115.node');\n }\n if (abi === '127') {\n return require('../sentry_cpu_profiler-darwin-x64-127.node');\n }\n }\n\n if (arch === 'arm64') {\n if (abi === '93') {\n return require('../sentry_cpu_profiler-darwin-arm64-93.node');\n }\n if (abi === '108') {\n return require('../sentry_cpu_profiler-darwin-arm64-108.node');\n }\n if (abi === '115') {\n return require('../sentry_cpu_profiler-darwin-arm64-115.node');\n }\n if (abi === '127') {\n return require('../sentry_cpu_profiler-darwin-arm64-127.node');\n }\n }\n }\n\n if (platform === 'win32') {\n if (arch === 'x64') {\n if (abi === '93') {\n return require('../sentry_cpu_profiler-win32-x64-93.node');\n }\n if (abi === '108') {\n return require('../sentry_cpu_profiler-win32-x64-108.node');\n }\n if (abi === '115') {\n return require('../sentry_cpu_profiler-win32-x64-115.node');\n }\n if (abi === '127') {\n return require('../sentry_cpu_profiler-win32-x64-127.node');\n }\n }\n }\n\n if (platform === 'linux') {\n if (arch === 'x64') {\n if (stdlib === 'musl') {\n if (abi === '93') {\n return require('../sentry_cpu_profiler-linux-x64-musl-93.node');\n }\n if (abi === '108') {\n return require('../sentry_cpu_profiler-linux-x64-musl-108.node');\n }\n if (abi === '115') {\n return require('../sentry_cpu_profiler-linux-x64-musl-115.node');\n }\n if (abi === '127') {\n return require('../sentry_cpu_profiler-linux-x64-musl-127.node');\n }\n }\n if (stdlib === 'glibc') {\n if (abi === '93') {\n return require('../sentry_cpu_profiler-linux-x64-glibc-93.node');\n }\n if (abi === '108') {\n return require('../sentry_cpu_profiler-linux-x64-glibc-108.node');\n }\n if (abi === '115') {\n return require('../sentry_cpu_profiler-linux-x64-glibc-115.node');\n }\n if (abi === '127') {\n return require('../sentry_cpu_profiler-linux-x64-glibc-127.node');\n }\n }\n }\n if (arch === 'arm64') {\n if (stdlib === 'musl') {\n if (abi === '93') {\n return require('../sentry_cpu_profiler-linux-arm64-musl-93.node');\n }\n if (abi === '108') {\n return require('../sentry_cpu_profiler-linux-arm64-musl-108.node');\n }\n if (abi === '115') {\n return require('../sentry_cpu_profiler-linux-arm64-musl-115.node');\n }\n if (abi === '127') {\n return require('../sentry_cpu_profiler-linux-arm64-musl-127.node');\n }\n }\n if (stdlib === 'glibc') {\n if (abi === '93') {\n return require('../sentry_cpu_profiler-linux-arm64-glibc-93.node');\n }\n if (abi === '108') {\n return require('../sentry_cpu_profiler-linux-arm64-glibc-108.node');\n }\n if (abi === '115') {\n return require('../sentry_cpu_profiler-linux-arm64-glibc-115.node');\n }\n if (abi === '127') {\n return require('../sentry_cpu_profiler-linux-arm64-glibc-127.node');\n }\n }\n }\n }\n return require(`${built_from_source_path}.node`);\n}\n\nconst PrivateCpuProfilerBindings: PrivateV8CpuProfilerBindings = importCppBindingsModule();\n\nclass Bindings implements V8CpuProfilerBindings {\n public startProfiling(name: string): void {\n if (!PrivateCpuProfilerBindings) {\n DEBUG_BUILD && logger.log('[Profiling] Bindings not loaded, ignoring call to startProfiling.');\n return;\n }\n\n return PrivateCpuProfilerBindings.startProfiling(name);\n }\n\n public stopProfiling(name: string, format: ProfileFormat.THREAD): RawThreadCpuProfile | null;\n public stopProfiling(name: string, format: ProfileFormat.CHUNK): RawChunkCpuProfile | null;\n public stopProfiling(\n name: string,\n format: ProfileFormat.CHUNK | ProfileFormat.THREAD,\n ): RawThreadCpuProfile | RawChunkCpuProfile | null {\n if (!PrivateCpuProfilerBindings) {\n DEBUG_BUILD &&\n logger.log('[Profiling] Bindings not loaded or profile was never started, ignoring call to stopProfiling.');\n return null;\n }\n\n return PrivateCpuProfilerBindings.stopProfiling(\n name,\n format as unknown as any,\n threadId,\n !!GLOBAL_OBJ._sentryDebugIds,\n );\n }\n}\n\nconst CpuProfilerBindings = new Bindings();\n\nexport { PrivateCpuProfilerBindings };\nexport { CpuProfilerBindings };\n","import { parseSemver } from '@sentry/utils';\n\nexport const NODE_VERSION = parseSemver(process.versions.node) as { major: number; minor: number; patch: number };\nexport const NODE_MAJOR = NODE_VERSION.major;\n","/* eslint-disable max-lines */\nimport * as os from 'os';\nimport type {\n Client,\n Context,\n ContinuousThreadCpuProfile,\n DebugImage,\n DsnComponents,\n Envelope,\n Event,\n EventEnvelopeHeaders,\n Profile,\n ProfileChunk,\n ProfileChunkEnvelope,\n ProfileChunkItem,\n SdkInfo,\n StackFrame,\n StackParser,\n ThreadCpuProfile,\n} from '@sentry/types';\nimport { GLOBAL_OBJ, createEnvelope, dsnToString, forEachEnvelopeItem, logger, uuid4 } from '@sentry/utils';\n\nimport { env, versions } from 'process';\nimport { isMainThread, threadId } from 'worker_threads';\n\nimport { DEBUG_BUILD } from './debug-build';\nimport type { RawChunkCpuProfile, RawThreadCpuProfile } from './types';\n\n// We require the file because if we import it, it will be included in the bundle.\n// I guess tsc does not check file contents when it's imported.\nexport const PROFILER_THREAD_ID_STRING = String(threadId);\nexport const PROFILER_THREAD_NAME = isMainThread ? 'main' : 'worker';\nconst FORMAT_VERSION = '1';\nconst CONTINUOUS_FORMAT_VERSION = '2';\n\n// Os machine was backported to 16.18, but this was not reflected in the types\n// @ts-expect-error ignore missing\nconst machine = typeof os.machine === 'function' ? os.machine() : os.arch();\n\n// Machine properties (eval only once)\nconst PLATFORM = os.platform();\nconst RELEASE = os.release();\nconst VERSION = os.version();\nconst TYPE = os.type();\nconst MODEL = machine;\nconst ARCH = os.arch();\n\n/**\n * Checks if the profile is a raw profile or a profile enriched with thread information.\n * @param {ThreadCpuProfile | RawThreadCpuProfile} profile\n * @returns {boolean}\n */\nfunction isRawThreadCpuProfile(\n profile: ThreadCpuProfile | RawThreadCpuProfile | ContinuousThreadCpuProfile | RawChunkCpuProfile,\n): profile is RawThreadCpuProfile | RawChunkCpuProfile {\n return !('thread_metadata' in profile);\n}\n\n/**\n * Enriches the profile with threadId of the current thread.\n * This is done in node as we seem to not be able to get the info from C native code.\n *\n * @param {ThreadCpuProfile | RawThreadCpuProfile} profile\n * @returns {ThreadCpuProfile}\n */\nexport function enrichWithThreadInformation(\n profile: ThreadCpuProfile | RawThreadCpuProfile | ContinuousThreadCpuProfile | RawChunkCpuProfile,\n): ThreadCpuProfile | ContinuousThreadCpuProfile {\n if (!isRawThreadCpuProfile(profile)) {\n return profile;\n }\n\n return {\n samples: profile.samples,\n frames: profile.frames,\n stacks: profile.stacks,\n thread_metadata: {\n [PROFILER_THREAD_ID_STRING]: {\n name: PROFILER_THREAD_NAME,\n },\n },\n } as ThreadCpuProfile | ContinuousThreadCpuProfile;\n}\n\n/**\n * Creates a profiling envelope item, if the profile does not pass validation, returns null.\n * @param {RawThreadCpuProfile}\n * @param {Event}\n * @returns {Profile | null}\n */\nexport function createProfilingEvent(client: Client, profile: RawThreadCpuProfile, event: Event): Profile | null {\n if (!isValidProfile(profile)) {\n return null;\n }\n\n return createProfilePayload(client, profile, {\n release: event.release ?? '',\n environment: event.environment ?? '',\n event_id: event.event_id ?? '',\n transaction: event.transaction ?? '',\n start_timestamp: event.start_timestamp ? event.start_timestamp * 1000 : Date.now(),\n trace_id: event.contexts?.['trace']?.['trace_id'] ?? '',\n profile_id: profile.profile_id,\n });\n}\n\n/**\n * Create a profile\n * @param {RawThreadCpuProfile} cpuProfile\n * @param {options}\n * @returns {Profile}\n */\nfunction createProfilePayload(\n client: Client,\n cpuProfile: RawThreadCpuProfile,\n {\n release,\n environment,\n event_id,\n transaction,\n start_timestamp,\n trace_id,\n profile_id,\n }: {\n release: string;\n environment: string;\n event_id: string;\n transaction: string;\n start_timestamp: number;\n trace_id: string | undefined;\n profile_id: string;\n },\n): Profile {\n // Log a warning if the profile has an invalid traceId (should be uuidv4).\n // All profiles and transactions are rejected if this is the case and we want to\n // warn users that this is happening if they enable debug flag\n if (trace_id && trace_id.length !== 32) {\n DEBUG_BUILD && logger.log(`[Profiling] Invalid traceId: ${trace_id} on profiled event`);\n }\n\n const enrichedThreadProfile = enrichWithThreadInformation(cpuProfile);\n\n const profile: Profile = {\n event_id: profile_id,\n timestamp: new Date(start_timestamp).toISOString(),\n platform: 'node',\n version: FORMAT_VERSION,\n release: release,\n environment: environment,\n measurements: cpuProfile.measurements,\n runtime: {\n name: 'node',\n version: versions.node || '',\n },\n os: {\n name: PLATFORM,\n version: RELEASE,\n build_number: VERSION,\n },\n device: {\n locale: env['LC_ALL'] || env['LC_MESSAGES'] || env['LANG'] || env['LANGUAGE'] || '',\n model: MODEL,\n manufacturer: TYPE,\n architecture: ARCH,\n is_emulator: false,\n },\n debug_meta: {\n images: applyDebugMetadata(client, cpuProfile.resources),\n },\n profile: enrichedThreadProfile as ThreadCpuProfile,\n transaction: {\n name: transaction,\n id: event_id,\n trace_id: trace_id || '',\n active_thread_id: PROFILER_THREAD_ID_STRING,\n },\n };\n\n return profile;\n}\n\n/**\n * Create a profile chunk from raw thread profile\n * @param {RawThreadCpuProfile} cpuProfile\n * @param {options}\n * @returns {Profile}\n */\nfunction createProfileChunkPayload(\n client: Client,\n cpuProfile: RawChunkCpuProfile,\n {\n release,\n environment,\n trace_id,\n profiler_id,\n chunk_id,\n sdk,\n }: {\n release: string;\n environment: string;\n trace_id: string | undefined;\n chunk_id: string;\n profiler_id: string;\n sdk: SdkInfo | undefined;\n },\n): ProfileChunk {\n // Log a warning if the profile has an invalid traceId (should be uuidv4).\n // All profiles and transactions are rejected if this is the case and we want to\n // warn users that this is happening if they enable debug flag\n if (trace_id && trace_id.length !== 32) {\n DEBUG_BUILD && logger.log(`[Profiling] Invalid traceId: ${trace_id} on profiled event`);\n }\n\n const enrichedThreadProfile = enrichWithThreadInformation(cpuProfile);\n\n const profile: ProfileChunk = {\n chunk_id: chunk_id,\n client_sdk: {\n name: sdk?.name ?? 'sentry.javascript.node',\n version: sdk?.version ?? '0.0.0',\n },\n profiler_id: profiler_id,\n platform: 'node',\n version: CONTINUOUS_FORMAT_VERSION,\n release: release,\n environment: environment,\n measurements: cpuProfile.measurements,\n debug_meta: {\n images: applyDebugMetadata(client, cpuProfile.resources),\n },\n profile: enrichedThreadProfile as ContinuousThreadCpuProfile,\n };\n\n return profile;\n}\n\n/**\n * Creates a profiling chunk envelope item, if the profile does not pass validation, returns null.\n */\nexport function createProfilingChunkEvent(\n client: Client,\n options: { release?: string; environment?: string },\n profile: RawChunkCpuProfile,\n sdk: SdkInfo | undefined,\n identifiers: { trace_id: string | undefined; chunk_id: string; profiler_id: string },\n): ProfileChunk | null {\n if (!isValidProfileChunk(profile)) {\n return null;\n }\n\n return createProfileChunkPayload(client, profile, {\n release: options.release ?? '',\n environment: options.environment ?? '',\n trace_id: identifiers.trace_id ?? '',\n chunk_id: identifiers.chunk_id,\n profiler_id: identifiers.profiler_id,\n sdk,\n });\n}\n\n/**\n * Checks the given sample rate to make sure it is valid type and value (a boolean, or a number between 0 and 1).\n * @param {unknown} rate\n * @returns {boolean}\n */\nexport function isValidSampleRate(rate: unknown): boolean {\n // we need to check NaN explicitly because it's of type 'number' and therefore wouldn't get caught by this typecheck\n if ((typeof rate !== 'number' && typeof rate !== 'boolean') || (typeof rate === 'number' && isNaN(rate))) {\n DEBUG_BUILD &&\n logger.warn(\n `[Profiling] Invalid sample rate. Sample rate must be a boolean or a number between 0 and 1. Got ${JSON.stringify(\n rate,\n )} of type ${JSON.stringify(typeof rate)}.`,\n );\n return false;\n }\n\n // Boolean sample rates are always valid\n if (rate === true || rate === false) {\n return true;\n }\n\n // in case sampleRate is a boolean, it will get automatically cast to 1 if it's true and 0 if it's false\n if (rate < 0 || rate > 1) {\n DEBUG_BUILD && logger.warn(`[Profiling] Invalid sample rate. Sample rate must be between 0 and 1. Got ${rate}.`);\n return false;\n }\n return true;\n}\n\n/**\n * Checks if the profile is valid and can be sent to Sentry.\n * @param {RawThreadCpuProfile} profile\n * @returns {boolean}\n */\nexport function isValidProfile(profile: RawThreadCpuProfile): profile is RawThreadCpuProfile & { profile_id: string } {\n if (profile.samples.length <= 1) {\n DEBUG_BUILD &&\n // Log a warning if the profile has less than 2 samples so users can know why\n // they are not seeing any profiling data and we cant avoid the back and forth\n // of asking them to provide us with a dump of the profile data.\n logger.log('[Profiling] Discarding profile because it contains less than 2 samples');\n return false;\n }\n\n if (!profile.profile_id) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Checks if the profile chunk is valid and can be sent to Sentry.\n * @param profile\n * @returns\n */\nexport function isValidProfileChunk(profile: RawChunkCpuProfile): profile is RawChunkCpuProfile {\n if (profile.samples.length <= 1) {\n DEBUG_BUILD &&\n // Log a warning if the profile has less than 2 samples so users can know why\n // they are not seeing any profiling data and we cant avoid the back and forth\n // of asking them to provide us with a dump of the profile data.\n logger.log('[Profiling] Discarding profile chunk because it contains less than 2 samples');\n return false;\n }\n\n return true;\n}\n\n/**\n * Adds items to envelope if they are not already present - mutates the envelope.\n * @param {Envelope} envelope\n * @param {Profile[]} profiles\n * @returns {Envelope}\n */\nexport function addProfilesToEnvelope(envelope: Envelope, profiles: Profile[]): Envelope {\n if (!profiles.length) {\n return envelope;\n }\n\n for (const profile of profiles) {\n // @ts-expect-error untyped envelope\n envelope[1].push([{ type: 'profile' }, profile]);\n }\n return envelope;\n}\n\n/**\n * Finds transactions with profile_id context in the envelope\n * @param {Envelope} envelope\n * @returns {Event[]}\n */\nexport function findProfiledTransactionsFromEnvelope(envelope: Envelope): Event[] {\n const events: Event[] = [];\n\n forEachEnvelopeItem(envelope, (item, type) => {\n if (type !== 'transaction') {\n return;\n }\n\n // First item is the type, so we can skip it, everything else is an event\n for (let j = 1; j < item.length; j++) {\n const event = item[j];\n\n if (!event) {\n // Shouldnt happen, but lets be safe\n continue;\n }\n\n // @ts-expect-error profile_id is not part of the metadata type\n const profile_id = (event.contexts as Context)?.['profile']?.['profile_id'];\n\n if (event && profile_id) {\n events.push(item[j] as Event);\n }\n }\n });\n\n return events;\n}\n\n/**\n * Creates event envelope headers for a profile chunk. This is separate from createEventEnvelopeHeaders util\n * as the profile chunk does not conform to the sentry event type\n */\nexport function createEventEnvelopeHeaders(\n sdkInfo: SdkInfo | undefined,\n tunnel: string | undefined,\n dsn?: DsnComponents,\n): EventEnvelopeHeaders {\n return {\n event_id: uuid4(),\n sent_at: new Date().toISOString(),\n ...(sdkInfo && { sdk: sdkInfo }),\n ...(!!tunnel && dsn && { dsn: dsnToString(dsn) }),\n };\n}\n\n/**\n * Creates a standalone profile_chunk envelope.\n */\nexport function makeProfileChunkEnvelope(\n chunk: ProfileChunk,\n sdkInfo: SdkInfo | undefined,\n tunnel: string | undefined,\n dsn?: DsnComponents,\n): ProfileChunkEnvelope {\n const profileChunkHeader: ProfileChunkItem[0] = {\n type: 'profile_chunk',\n };\n\n return createEnvelope<ProfileChunkEnvelope>(createEventEnvelopeHeaders(sdkInfo, tunnel, dsn), [\n [profileChunkHeader, chunk],\n ]);\n}\n\nconst debugIdStackParserCache = new WeakMap<StackParser, Map<string, StackFrame[]>>();\n\n/**\n * Cross reference profile collected resources with debug_ids and return a list of debug images.\n * @param {string[]} resource_paths\n * @returns {DebugImage[]}\n */\nexport function applyDebugMetadata(client: Client, resource_paths: ReadonlyArray<string>): DebugImage[] {\n const debugIdMap = GLOBAL_OBJ._sentryDebugIds;\n if (!debugIdMap) {\n return [];\n }\n\n const options = client.getOptions();\n\n if (!options || !options.stackParser) {\n return [];\n }\n\n let debugIdStackFramesCache: Map<string, StackFrame[]>;\n const cachedDebugIdStackFrameCache = debugIdStackParserCache.get(options.stackParser);\n if (cachedDebugIdStackFrameCache) {\n debugIdStackFramesCache = cachedDebugIdStackFrameCache;\n } else {\n debugIdStackFramesCache = new Map<string, StackFrame[]>();\n debugIdStackParserCache.set(options.stackParser, debugIdStackFramesCache);\n }\n\n // Build a map of filename -> debug_id.\n const filenameDebugIdMap = Object.keys(debugIdMap).reduce<Record<string, string>>((acc, debugIdStackTrace) => {\n let parsedStack: StackFrame[];\n\n const cachedParsedStack = debugIdStackFramesCache.get(debugIdStackTrace);\n if (cachedParsedStack) {\n parsedStack = cachedParsedStack;\n } else {\n parsedStack = options.stackParser(debugIdStackTrace);\n debugIdStackFramesCache.set(debugIdStackTrace, parsedStack);\n }\n\n for (let i = parsedStack.length - 1; i >= 0; i--) {\n const stackFrame = parsedStack[i];\n const file = stackFrame && stackFrame.filename;\n\n if (stackFrame && file) {\n acc[file] = debugIdMap[debugIdStackTrace] as string;\n break;\n }\n }\n return acc;\n }, {});\n\n const images: DebugImage[] = [];\n\n for (const resource of resource_paths) {\n if (resource && filenameDebugIdMap[resource]) {\n images.push({\n type: 'sourcemap',\n code_file: resource,\n debug_id: filenameDebugIdMap[resource] as string,\n });\n }\n }\n\n return images;\n}\n","import { spanIsSampled, spanToJSON } from '@sentry/core';\nimport type { NodeClient } from '@sentry/node';\nimport type { CustomSamplingContext, Span } from '@sentry/types';\nimport { logger, uuid4 } from '@sentry/utils';\n\nimport { CpuProfilerBindings } from './cpu_profiler';\nimport { DEBUG_BUILD } from './debug-build';\nimport type { RawThreadCpuProfile } from './types';\nimport { isValidSampleRate } from './utils';\n\nexport const MAX_PROFILE_DURATION_MS = 30 * 1000;\n\n/**\n * Takes a transaction and determines if it should be profiled or not. If it should be profiled, it returns the\n * profile_id, otherwise returns undefined. Takes care of setting profile context on transaction as well\n */\nexport function maybeProfileSpan(\n client: NodeClient | undefined,\n span: Span,\n customSamplingContext?: CustomSamplingContext,\n): string | undefined {\n // profilesSampleRate is multiplied with tracesSampleRate to get the final sampling rate. We dont perform\n // the actual multiplication to get the final rate, but we discard the profile if the span was sampled,\n // so anything after this block from here is based on the span sampling.\n if (!spanIsSampled(span)) {\n return;\n }\n\n // Client and options are required for profiling\n if (!client) {\n DEBUG_BUILD && logger.log('[Profiling] Profiling disabled, no client found.');\n return;\n }\n\n const options = client.getOptions();\n if (!options) {\n DEBUG_BUILD && logger.log('[Profiling] Profiling disabled, no options found.');\n return;\n }\n\n const profilesSampler = options.profilesSampler;\n let profilesSampleRate: number | boolean | undefined = options.profilesSampleRate;\n\n // Prefer sampler to sample rate if both are provided.\n if (typeof profilesSampler === 'function') {\n const { description: spanName = '<unknown>', data } = spanToJSON(span);\n // We bail out early if that is not the case\n const parentSampled = true;\n\n profilesSampleRate = profilesSampler({\n name: spanName,\n attributes: data,\n transactionContext: {\n name: spanName,\n parentSampled,\n },\n parentSampled,\n ...customSamplingContext,\n });\n }\n\n // Since this is coming from the user (or from a function provided by the user), who knows what we might get. (The\n // only valid values are booleans or numbers between 0 and 1.)\n if (!isValidSampleRate(profilesSampleRate)) {\n DEBUG_BUILD && logger.warn('[Profiling] Discarding profile because of invalid sample rate.');\n return;\n }\n\n // if the function returned 0 (or false), or if `profileSampleRate` is 0, it's a sign the profile should be dropped\n if (!profilesSampleRate) {\n DEBUG_BUILD &&\n logger.log(\n `[Profiling] Discarding profile because ${\n typeof profilesSampler === 'function'\n ? 'profileSampler returned 0 or false'\n : 'a negative sampling decision was inherited or profileSampleRate is set to 0'\n }`,\n );\n return;\n }\n\n // Now we roll the dice. Math.random is inclusive of 0, but not of 1, so strict < is safe here. In case sampleRate is\n // a boolean, the < comparison will cause it to be automatically cast to 1 if it's true and 0 if it's false.\n const sampled = profilesSampleRate === true ? true : Math.random() < profilesSampleRate;\n // Check if we should sample this profile\n if (!sampled) {\n DEBUG_BUILD &&\n logger.log(\n `[Profiling] Discarding profile because it's not included in the random sample (sampling rate = ${Number(\n profilesSampleRate,\n )})`,\n );\n return;\n }\n\n const profile_id = uuid4();\n CpuProfilerBindings.startProfiling(profile_id);\n DEBUG_BUILD && logger.log(`[Profiling] started profiling transaction: ${spanToJSON(span).description}`);\n\n // set transaction context - do this regardless if profiling fails down the line\n // so that we can still see the profile_id in the transaction context\n return profile_id;\n}\n\n/**\n * Stops the profiler for profile_id and returns the profile\n * @param transaction\n * @param profile_id\n * @returns\n */\nexport function stopSpanProfile(span: Span, profile_id: string | undefined): RawThreadCpuProfile | null {\n // Should not happen, but satisfy the type checker and be safe regardless.\n if (!profile_id) {\n return null;\n }\n\n const profile = CpuProfilerBindings.stopProfiling(profile_id, 0);\n DEBUG_BUILD && logger.log(`[Profiling] stopped profiling of transaction: ${spanToJSON(span).description}`);\n\n // In case of an overlapping span, stopProfiling may return null and silently ignore the overlapping profile.\n if (!profile) {\n DEBUG_BUILD &&\n logger.log(\n `[Profiling] profiler returned null profile for: ${spanToJSON(span).description}`,\n 'this may indicate an overlapping span or a call to stopProfiling with a profile title that was never started',\n );\n return null;\n }\n\n // Assign profile_id to the profile\n profile.profile_id = profile_id;\n return profile;\n}\n","import type { Event } from '@sentry/types';\n\ninterface Sample {\n stack_id: number;\n thread_id: string;\n elapsed_since_start_ns: string;\n}\n\ninterface ChunkSample {\n stack_id: number;\n thread_id: string;\n timestamp: number;\n}\n\ntype Frame = {\n function: string;\n file: string;\n lineno: number;\n colno: number;\n};\n\ninterface Measurement {\n unit: string;\n values: {\n elapsed_since_start_ns: number;\n value: number;\n }[];\n}\n\n// Profile is marked as optional because it is deleted from the metadata\n// by the integration before the event is processed by other integrations.\nexport interface ProfiledEvent extends Event {\n sdkProcessingMetadata: {\n profile?: RawThreadCpuProfile;\n };\n}\n\ninterface BaseProfile {\n profile_id?: string;\n stacks: number[][];\n frames: Frame[];\n resources: string[];\n profiler_logging_mode: 'eager' | 'lazy';\n measurements: Record<string, Measurement>;\n}\nexport interface RawThreadCpuProfile extends BaseProfile {\n samples: Sample[];\n}\n\nexport interface RawChunkCpuProfile extends BaseProfile {\n samples: ChunkSample[];\n}\n\nexport interface PrivateV8CpuProfilerBindings {\n startProfiling(name: string): void;\n\n stopProfiling(\n name: string,\n format: ProfileFormat.THREAD,\n threadId: number,\n collectResources: boolean,\n ): RawThreadCpuProfile | null;\n stopProfiling(\n name: string,\n format: ProfileFormat.CHUNK,\n threadId: number,\n collectResources: boolean,\n ): RawChunkCpuProfile | null;\n\n // Helper methods exposed for testing\n getFrameModule(abs_path: string): string;\n}\n\nexport enum ProfileFormat {\n THREAD = 0,\n CHUNK = 1,\n}\n\nexport interface V8CpuProfilerBindings {\n startProfiling(name: string): void;\n\n stopProfiling(name: string, format: ProfileFormat.THREAD): RawThreadCpuProfile | null;\n stopProfiling(name: string, format: ProfileFormat.CHUNK): RawChunkCpuProfile | null;\n}\n","/* eslint-disable max-lines */\n\nimport {\n defineIntegration,\n getCurrentScope,\n getGlobalScope,\n getIsolationScope,\n getRootSpan,\n spanToJSON,\n} from '@sentry/core';\nimport type { NodeClient } from '@sentry/node';\nimport type { Event, IntegrationFn, Profile, ProfileChunk, ProfilingIntegration, Span } from '@sentry/types';\n\nimport { LRUMap, logger, uuid4 } from '@sentry/utils';\n\nimport { CpuProfilerBindings } from './cpu_profiler';\nimport { DEBUG_BUILD } from './debug-build';\nimport { NODE_MAJOR, NODE_VERSION } from './nodeVersion';\nimport { MAX_PROFILE_DURATION_MS, maybeProfileSpan, stopSpanProfile } from './spanProfileUtils';\nimport type { RawChunkCpuProfile, RawThreadCpuProfile } from './types';\nimport { ProfileFormat } from './types';\nimport { PROFILER_THREAD_NAME } from './utils';\n\nimport {\n PROFILER_THREAD_ID_STRING,\n addProfilesToEnvelope,\n createProfilingChunkEvent,\n createProfilingEvent,\n findProfiledTransactionsFromEnvelope,\n makeProfileChunkEnvelope,\n} from './utils';\n\nconst CHUNK_INTERVAL_MS = 5000;\nconst PROFILE_MAP = new LRUMap<string, RawThreadCpuProfile>(50);\nconst PROFILE_TIMEOUTS: Record<string, NodeJS.Timeout> = {};\n\nfunction addToProfileQueue(profile_id: string, profile: RawThreadCpuProfile): void {\n PROFILE_MAP.set(profile_id, profile);\n}\n\nfunction takeFromProfileQueue(profile_id: string): RawThreadCpuProfile | undefined {\n const profile = PROFILE_MAP.get(profile_id);\n PROFILE_MAP.remove(profile_id);\n return profile;\n}\n\n/**\n * Instruments the client to automatically invoke the profiler on span start and stop events.\n * @param client\n */\nfunction setupAutomatedSpanProfiling(client: NodeClient): void {\n const spanToProfileIdMap = new WeakMap<Span, string>();\n\n client.on('spanStart', span => {\n if (span !== getRootSpan(span)) {\n return;\n }\n\n const profile_id = maybeProfileSpan(client, span);\n\n if (profile_id) {\n const options = client.getOptions();\n // Not intended for external use, hence missing types, but we want to profile a couple of things at Sentry that\n // currently exceed the default timeout set by the SDKs.\n const maxProfileDurationMs =\n (options._experiments && options._experiments['maxProfileDurationMs']) || MAX_PROFILE_DURATION_MS;\n\n if (PROFILE_TIMEOUTS[profile_id]) {\n global.clearTimeout(PROFILE_TIMEOUTS[profile_id]);\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete PROFILE_TIMEOUTS[profile_id];\n }\n\n // Enqueue a timeout to prevent profiles from running over max duration.\n const timeout = global.setTimeout(() => {\n DEBUG_BUILD &&\n logger.log('[Profiling] max profile duration elapsed, stopping profiling for:', spanToJSON(span).description);\n\n const profile = stopSpanProfile(span, profile_id);\n if (profile) {\n addToProfileQueue(profile_id, profile);\n }\n }, maxProfileDurationMs);\n\n // Unref timeout so it doesn't keep the process alive.\n timeout.unref();\n\n getCurrentScope().setContext('profile', { profile_id });\n spanToProfileIdMap.set(span, profile_id);\n }\n });\n\n client.on('spanEnd', span => {\n const profile_id = spanToProfileIdMap.get(span);\n\n if (profile_id) {\n if (PROFILE_TIMEOUTS[profile_id]) {\n global.clearTimeout(PROFILE_TIMEOUTS[profile_id]);\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete PROFILE_TIMEOUTS[profile_id];\n }\n const profile = stopSpanProfile(span, profile_id);\n\n if (profile) {\n addToProfileQueue(profile_id, profile);\n }\n }\n });\n\n client.on('beforeEnvelope', (envelope): void => {\n // if not profiles are in queue, there is nothing to add to the envelope.\n if (!PROFILE_MAP.size) {\n return;\n }\n\n const profiledTransactionEvents = findProfiledTransactionsFromEnvelope(envelope);\n if (!profiledTransactionEvents.length) {\n return;\n }\n\n const profilesToAddToEnvelope: Profile[] = [];\n\n for (const profiledTransaction of profiledTransactionEvents) {\n const profileContext = profiledTransaction.contexts?.['profile'];\n const profile_id = profileContext?.['profile_id'];\n\n if (!profile_id) {\n throw new TypeError('[Profiling] cannot find profile for a transaction without a profile context');\n }\n\n // Remove the profile from the transaction context before sending, relay will take care of the rest.\n if (profileContext) {\n delete profiledTransaction.contexts?.['profile'];\n }\n\n const cpuProfile = takeFromProfileQueue(profile_id);\n if (!cpuProfile) {\n DEBUG_BUILD && logger.log(`[Profiling] Could not retrieve profile for transaction: ${profile_id}`);\n continue;\n }\n\n const profile = createProfilingEvent(client, cpuProfile, profiledTransaction);\n if (!profile) return;\n\n profilesToAddToEnvelope.push(profile);\n\n // @ts-expect-error profile does not inherit from Event\n client.emit('preprocessEvent', profile, {\n event_id: profiledTransaction.event_id,\n });\n }\n\n addProfilesToEnvelope(envelope, profilesToAddToEnvelope);\n });\n}\n\ninterface ChunkData {\n id: string;\n timer: NodeJS.Timeout | undefined;\n startTraceID: string;\n}\n\nclass ContinuousProfiler {\n private _profilerId = uuid4();\n private _client: NodeClient | undefined = undefined;\n private _chunkData: ChunkData | undefined = undefined;\n\n /**\n * Called when the profiler is attached to the client (continuous mode is enabled). If of the profiler\n * methods called before the profiler is initialized will result in a noop action with debug logs.\n * @param client\n */\n public initialize(client: NodeClient): void {\n this._client = client;\n }\n\n /**\n * Recursively schedules chunk profiling to start and stop at a set interval.\n * Once the user calls stop(), the current chunk will be stopped and flushed to Sentry and no new chunks will\n * will be started. To restart continuous mode after calling stop(), the user must call start() again.\n * @returns void\n */\n public start(): void {\n if (!this._client) {\n // The client is not attached to the profiler if the user has not enabled continuous profiling.\n // In this case, calling start() and stop() is a noop action.The reason this exists is because\n // it makes the types easier to work with and avoids users having to do null checks.\n DEBUG_BUILD && logger.log('[Profiling] Profiler was never attached to the client.');\n return;\n }\n if (this._chunkData) {\n DEBUG_BUILD &&\n logger.log(\n `[Profiling] Chunk with chunk_id ${this._chunkData.id} is still running, current chunk will be stopped a new chunk will be started.`,\n );\n this.stop();\n }\n\n const traceId =\n getCurrentScope().getPropagationContext().traceId || getIsolationScope().getPropagationContext().traceId;\n this._initializeChunk(traceId);\n this._startChunkProfiling(this._chunkData!);\n }\n\n /**\n * Stops the current chunk and flushes the profile to Sentry.\n * @returns void\n */\n public stop(): void {\n if (this._chunkData?.timer) {\n global.clearTimeout(this._chunkData.timer);\n this._chunkData.timer = undefined;\n DEBUG_BUILD && logger.log(`[Profiling] Stopping profiling chunk: ${this._chunkData.id}`);\n }\n if (!this._client) {\n DEBUG_BUILD &&\n logger.log('[Profiling] Failed to collect profile, sentry client was never attached to the profiler.');\n return;\n }\n if (!this._chunkData?.id) {\n DEBUG_BUILD &&\n logger.log(`[Profiling] Failed to collect profile for: ${this._chunkData?.id}, the chunk_id is missing.`);\n return;\n }\n\n const profile = this._stopChunkProfiling(this._chunkData);\n\n if (!profile) {\n DEBUG_BUILD && logger.log(`[Profiling] _chunkiledStartTraceID to collect profile for: ${this._chunkData.id}`);\n return;\n }\n if (profile) {\n DEBUG_BUILD && logger.log(`[Profiling] Sending profile chunk ${this._chunkData.id}.`);\n }\n\n DEBUG_BUILD && logger.log(`[Profiling] Profile chunk ${this._chunkData.id} sent to Sentry.`);\n const chunk = createProfilingChunkEvent(\n this._client,\n this._client.getOptions(),\n profile,\n this._client.getSdkMetadata()?.sdk,\n {\n chunk_id: this._chunkData.id,\n trace_id: this._chunkData.startTraceID,\n profiler_id: this._profilerId,\n },\n );\n\n if (!chunk) {\n DEBUG_BUILD && logger.log(`[Profiling] Failed to create profile chunk for: ${this._chunkData.id}`);\n this._reset();\n return;\n }\n\n this._flush(chunk);\n // Depending on the profile and stack sizes, stopping the profile and converting\n // the format may negatively impact the performance of the application. To avoid\n // blocking for too long, enqueue the next chunk start inside the next macrotask.\n // clear current chunk\n this._reset();\n }\n\n /**\n * Flushes the profile chunk to Sentry.\n * @param chunk\n */\n private _flush(chunk: ProfileChunk): void {\n if (!this._client) {\n DEBUG_BUILD &&\n logger.log('[Profiling] Failed to collect profile, sentry client was never attached to the profiler.');\n return;\n }\n\n const transport = this._client.getTransport();\n if (!transport) {\n DEBUG_BUILD && logger.log('[Profiling] No transport available to send profile chunk.');\n return;\n }\n\n const dsn = this._client.getDsn();\n const metadata = this._client.getSdkMetadata();\n const tunnel = this._client.getOptions().tunnel;\n\n const envelope = makeProfileChunkEnvelope(chunk, metadata?.sdk, tunnel, dsn);\n transport.send(envelope).then(null, reason => {\n DEBUG_BUILD && logger.error('Error while sending profile chunk envelope:', reason);\n });\n }\n\n /**\n * Stops the profile and clears chunk instrumentation from global scope\n * @returns void\n */\n private _stopChunkProfiling(chunk: ChunkData): RawChunkCpuProfile | null {\n this._teardownSpanChunkInstrumentation();\n return CpuProfilerBindings.stopProfiling(chunk.id, ProfileFormat.CHUNK);\n }\n\n /**\n * Starts the profiler and registers the flush timer for a given chunk.\n * @param chunk\n */\n private _startChunkProfiling(chunk: ChunkData): void {\n this._setupSpanChunkInstrumentation();\n CpuProfilerBindings.startProfiling(chunk.id);\n DEBUG_BUILD && logger.log(`[Profiling] starting profiling chunk: ${chunk.id}`);\n\n chunk.timer = global.setTimeout(() => {\n DEBUG_BUILD && logger.log(`[Profiling] Stopping profiling chunk: ${chunk.id}`);\n this.stop();\n DEBUG_BUILD && logger.log('[Profiling] Starting new profiling chunk.');\n setImmediate(this.start.bind(this));\n }, CHUNK_INTERVAL_MS);\n\n // Unref timeout so it doesn't keep the process alive.\n chunk.timer.unref();\n }\n\n /**\n * Attaches profiling information to spans that were started\n * during a profiling session.\n */\n private _setupSpanChunkInstrumentation(): void {\n if (!this._client) {\n DEBUG_BUILD &&\n logger.log('[Profiling] Failed to collect profile, sentry client was never attached to the profiler.');\n return;\n }\n\n getGlobalScope().setContext('profile', {\n profiler_id: this._profilerId,\n });\n\n this._client.on('beforeSendEvent', e => this._assignThreadIdContext(e));\n }\n\n /**\n * Clear profiling information from global context when a profile is not running.\n */\n private _teardownSpanChunkInstrumentation(): void {\n const globalScope = getGlobalScope();\n globalScope.setContext('profile', {});\n }\n\n /**\n * Initializes new profile chunk metadata\n */\n private _initializeChunk(traceId: string): void {\n this._chunkData = {\n id: uuid4(),\n startTraceID: traceId,\n timer: undefined,\n };\n }\n\n /**\n * Assigns thread_id and thread name context to a profiled event.\n */\n private _assignThreadIdContext(event: Event): any {\n if (!event?.['contexts']?.['profile']) {\n return;\n }\n\n if (!event.contexts) {\n return;\n }\n\n // @ts-expect-error the trace fallback value is wrong, though it should never happen\n // and in case it does, we dont want to override whatever was passed initially.\n event.contexts['trace'] = {\n ...(event.contexts?.['trace'] ?? {}),\n data: {\n ...(event.contexts?.['trace']?.['data'] ?? {}),\n ['thread.id']: PROFILER_THREAD_ID_STRING,\n ['thread.name']: PROFILER_THREAD_NAME,\n },\n };\n }\n\n /**\n * Resets the current chunk state.\n */\n private _reset(): void {\n this._chunkData = undefined;\n }\n}\n\n/** Exported only for tests. */\nexport const _nodeProfilingIntegration = ((): ProfilingIntegration<NodeClient> => {\n if (DEBUG_BUILD && ![16, 18, 20, 22].includes(NODE_MAJOR)) {\n logger.warn(\n `[Profiling] You are using a Node.js version that does not have prebuilt binaries (${NODE_VERSION}).`,\n 'The @sentry/profiling-node package only has prebuilt support for the following LTS versions of Node.js: 16, 18, 20, 22.',\n 'To use the @sentry/profiling-node package with this version of Node.js, you will need to compile the native addon from source.',\n 'See: https://github.com/getsentry/sentry-javascript/tree/develop/packages/profiling-node#building-the-package-from-source',\n );\n }\n\n return {\n name: 'ProfilingIntegration',\n _profiler: new ContinuousProfiler(),\n setup(client: NodeClient) {\n DEBUG_BUILD && logger.log('[Profiling] Profiling integration setup.');\n const options = client.getOptions();\n\n const mode =\n (options.profilesSampleRate === undefined ||\n options.profilesSampleRate === null ||\n options.profilesSampleRate === 0) &&\n !options.profilesSampler\n ? 'continuous'\n : 'span';\n switch (mode) {\n case 'continuous': {\n DEBUG_BUILD && logger.log('[Profiling] Continuous profiler mode enabled.');\n this._profiler.initialize(client);\n break;\n }\n // Default to span profiling when no mode profiler mode is set\n case 'span':\n case undefined: {\n DEBUG_BUILD && logger.log('[Profiling] Span profiler mode enabled.');\n setupAutomatedSpanProfiling(client);\n break;\n }\n default: {\n DEBUG_BUILD && logger.warn(`[Profiling] Unknown profiler mode: ${mode}, profiler was not initialized`);\n }\n }\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * We need this integration in order to send data to Sentry. We hook into the event processor\n * and inspect each event to see if it is a transaction event and if that transaction event\n * contains a profile on it's metadata. If that is the case, we create a profiling event envelope\n * and delete the profile from the transaction metadata.\n */\nexport const nodeProfilingIntegration = defineIntegration(_nodeProfilingIntegration);\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;AAEA;AACA;AACA;;;AAGO;;ACUP;AACA;AACA;AACA;AACA;;AAEA;;AAE4F;;;AAGA;AACA;AACA;AACA;;;AAGA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;;AAGA;;;;AAMA;;AAEA;;;;AAIA;;;;AAIA;AACA;;;AAGA;AACA;;AAEA;;AC7LrF;AACA;;ACHP;;AA4BA;AACA;AACO;AACA;AACP;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACE;AACF;AACE;AACF;;AAEA;;AAEA;AACA;;;;AAIO;AACL;AACF;AACE;;AAEA;;AAEA;;AAEE;AACA;AACA;;;;;;AAMJ;;AAEA;AACA;;;;;AAKO;;;AAGL;;AAEA;;;;;AAKE;AACA;;AAEJ;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACE;;AAEA;AACE;;AAEA;;AAEA;AACA;;AAED;;AAQD;AACF;;AAEA;;AAEE;AACE;AACF;;AAEA;;;AAGE;;AAEA;;AAEA;;AAEA;AACA;;;;AAIA;;AAEE;AACA;;AAEF;AACE;;AAEA;AACA;AACA;;;;;;;AAOA;;AAEA;AACA;;;;;AAKN;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACE;;AAEA;AACE;;AAEA;;AAEA;AACA;AACD;;AAOD;AACF;;AAEA;;AAEE;AACE;AACF;;AAEA;;;AAGE;;;;;;AAMA;AACA;AACA;;AAEA;;;;;;;;AAQJ;;AAEA;AACA;;AAEO;AACL;AACA;AACA;AACA;;AAEF;AACE;;AAEA;;;;;;;AAOE;AACA;AACJ;AACA;;AAEA;AACA;AACA;AACA;;AAEO;;AAEL;;;;;AAKF;;;AAGE;;AAEF;;;AAGE;;AAEF;AACE;;;AAGA;;AAEF;;AAEA;;AAEA;AACA;;AAEO;;;;AAIP;;AAEM;;AAEJ;;;;AAIA;;;AAGF;;AAEA;;;AAGA;;AAEO;;;;AAIP;;AAEM;;AAEJ;;;AAGF;;AAEA;AACA;;;AAGA;;AAEO;AACL;AACE;AACF;;;AAGF;AACI;AACF;AACA;AACF;;AAEA;;;AAGA;;AAEO;AACL;;AAEA;;AAEI;AACF;;;;AAIE;;;;AAIE;AACF;;;;;AAKA;AACE;AACF;AACF;AACJ;;;AAGA;;AAEA;AACA;;;AAGO;AACL;AACA;AACA;AACF;AACE;AACE;AACA;;AAEA;;AAEJ;;AAEA;AACA;;AAEO;;AAEL;AACA;AACA;AACF;;AAEI;;;AAGF;;AAEF;AACA;;AAEA;;AAEA;AACA;AACA;;;AAGO;AACL;AACA;AACE;AACF;;AAEA;;AAEA;AACE;AACF;;;AAGA;AACA;;;AAGE;AACA;AACF;;AAEF;AACE;AACE;;AAEA;AACA;;;;;AAKA;;AAEA;AACE;AACA;;AAEA;AACE;;AAEF;AACF;AACA;;;AAGF;;AAEA;AACE;;AAEI;AACA;AACA;AACR;AACI;AACF;;;AAGF;;ACxdO;;AAEP;AACA;AACA;;AAEO;AACL;;AAEA;AACF;AACA;AACA;;;AAGI;AACF;;AAEF;;AAEI;AACA;AACF;;AAEA;;AAEE;AACA;AACF;;AAEA;;;AAGF;AACE;;AAEF;;;AAGI;;AAEE;AACA;;;;;;AAMN;AACE;;AAEF;;AAEE;AACE;AACA;AACF;;;;;;AAMM;AACE;AACV;AACA;AACA;;AAES;AACA;;AAEA;AACA;AACA;AACA;;;;AAIA;AACA;;;AAGA;AACA;;;;;;AAMA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;;;;;AAKA;;;;AAIA;AACA;;;AAGA;;;;;AAKA;;AC3DiB;AACxB;AACA;AACF;;AC5EA;;AAgCA;AACA;AACA;;AAEA;AACE;AACF;;AAEA;AACE;AACA;;AAEF;;AAEA;AACA;;;AAGA;AACE;;;;AAII;AACF;;AAEA;;AAEA;AACE;AACN;;;AAGQ;;AAEF;;;AAGE;AACF;;;AAGA;;;;AAIE;;AAEE;AACF;;;AAGR;AACM;;;AAGA;AACF;AACJ;;;AAGI;;AAEA;AACE;;;AAGE;AACF;AACA;;;AAGE;AACF;AACF;AACJ;;AAEE;;AAEE;AACE;AACF;;AAEA;AACA;AACE;AACF;;AAEA;;;;AAIE;;AAEA;AACE;AACF;;AAEN;AACM;;AAEA;;;AAGA;AACE;AACgG;AACA;;AAEA;AACA;;AAEA;;;AAGA;AACA;AACA;AACA;;;AAGA;AACA;;AAQA;AACA;AACA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;AACA;;AAEA;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;AAMA;;;;AAIA;AACA;AACA;;AAEA;;;;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;;;;;AAMA;AACA;;AAEA;AACA;;AAEA;AACA;;;AAGA;AACA;AACA;;AAEA;;;;;;AAMA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;;;AAIA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;AACA;AACA;;AAEA;;;;;AAKA;AACA;AACA;;AAEA;;;;;AAKA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;;;AAIA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;;AAGA;;AAEA;AACA;;AAEA;;AAEA;;;;;AAKA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;;;AAIA;AACA;AACA;;;AAGA;;AAEA;;;AAGA;;AAEA;AACA;;AAEA;AACA;;;AAGA;;;;;AAKA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;;AAGA;;AAEA;AACA;AACA;;AAEA;;;AAGA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;;AAGA;;AAEA;AACA;AACA;AACA;;;AAGA;;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cpu_profiler.d.ts","sourceRoot":"","sources":["../../src/cpu_profiler.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,4BAA4B,EAC5B,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"cpu_profiler.d.ts","sourceRoot":"","sources":["../../src/cpu_profiler.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,4BAA4B,EAC5B,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAgB7C;;GAEG;AAEH,wBAAgB,uBAAuB,IAAI,4BAA4B,CA+HtE;AAED,QAAA,MAAM,0BAA0B,EAAE,4BAAwD,CAAC;AAE3F,cAAM,QAAS,YAAW,qBAAqB;IACtC,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IASlC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,MAAM,GAAG,mBAAmB,GAAG,IAAI;IACrF,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,KAAK,GAAG,kBAAkB,GAAG,IAAI;CAkB3F;AAED,QAAA,MAAM,mBAAmB,UAAiB,CAAC;AAE3C,OAAO,EAAE,0BAA0B,EAAE,CAAC;AACtC,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../../src/integration.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAA+C,oBAAoB,EAAQ,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../../src/integration.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAA+C,oBAAoB,EAAQ,MAAM,eAAe,CAAC;AA+Z7G,+BAA+B;AAC/B,eAAO,MAAM,yBAAyB,QAAQ,qBAAqB,UAAU,CA2CnD,CAAC;AAE3B;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,2CAA+C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/profiling-node",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.31.0-beta.0",
|
|
4
4
|
"description": "Official Sentry SDK for Node.js Profiling",
|
|
5
5
|
"repository": "git://github.com/getsentry/sentry-javascript.git",
|
|
6
6
|
"homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/profiling-node",
|
|
@@ -75,10 +75,10 @@
|
|
|
75
75
|
"test": "cross-env SENTRY_PROFILER_BINARY_DIR=lib jest --config jest.config.js"
|
|
76
76
|
},
|
|
77
77
|
"dependencies": {
|
|
78
|
-
"@sentry/core": "8.
|
|
79
|
-
"@sentry/node": "8.
|
|
80
|
-
"@sentry/types": "8.
|
|
81
|
-
"@sentry/utils": "8.
|
|
78
|
+
"@sentry/core": "8.31.0-beta.0",
|
|
79
|
+
"@sentry/node": "8.31.0-beta.0",
|
|
80
|
+
"@sentry/types": "8.31.0-beta.0",
|
|
81
|
+
"@sentry/utils": "8.31.0-beta.0",
|
|
82
82
|
"detect-libc": "^2.0.2",
|
|
83
83
|
"node-abi": "^3.61.0"
|
|
84
84
|
},
|