UNPKG

@sentry/profiling-node

Version:
813 lines (805 loc) 27.8 kB
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); const core = require('@sentry/core'); const nodeCpuProfiler = require('@sentry/node-cpu-profiler'); const worker_threads = require('worker_threads'); const os = require('os'); const process$1 = require('process'); const DEBUG_BUILD = (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__); const NODE_VERSION = core.parseSemver(process.versions.node); const NODE_MAJOR = NODE_VERSION.major; const PROFILER_THREAD_ID_STRING = String(worker_threads.threadId); const PROFILER_THREAD_NAME = worker_threads.isMainThread ? "main" : "worker"; const FORMAT_VERSION = "1"; const CONTINUOUS_FORMAT_VERSION = "2"; const PLATFORM = os.platform(); const RELEASE = os.release(); const VERSION = os.version(); const TYPE = os.type(); const MODEL = os.machine(); const ARCH = os.arch(); function isRawThreadCpuProfile(profile) { return !("thread_metadata" in profile); } function enrichWithThreadInformation(profile) { if (!isRawThreadCpuProfile(profile)) { return profile; } return { samples: profile.samples, frames: profile.frames, stacks: profile.stacks, thread_metadata: { [PROFILER_THREAD_ID_STRING]: { name: PROFILER_THREAD_NAME } } }; } function createProfilingEvent(client, profile, event) { if (!isValidProfile(profile)) { return null; } return createProfilePayload(client, profile, { release: event.release ?? "", environment: event.environment ?? "", event_id: event.event_id ?? "", transaction: event.transaction ?? "", start_timestamp: event.start_timestamp ? event.start_timestamp * 1e3 : Date.now(), trace_id: event.contexts?.trace?.trace_id ?? "", profile_id: profile.profile_id }); } function createProfilePayload(client, cpuProfile, { release, environment, event_id, transaction, start_timestamp, trace_id, profile_id }) { if (trace_id?.length !== 32) { DEBUG_BUILD && core.debug.log(`[Profiling] Invalid traceId: ${trace_id} on profiled event`); } const enrichedThreadProfile = enrichWithThreadInformation(cpuProfile); const profile = { event_id: profile_id, timestamp: new Date(start_timestamp).toISOString(), platform: "node", version: FORMAT_VERSION, release, environment, measurements: cpuProfile.measurements, runtime: { name: "node", version: process$1.versions.node || "" }, os: { name: PLATFORM, version: RELEASE, build_number: VERSION }, device: { locale: process$1.env["LC_ALL"] || process$1.env["LC_MESSAGES"] || process$1.env["LANG"] || process$1.env["LANGUAGE"] || "", model: MODEL, manufacturer: TYPE, architecture: ARCH, is_emulator: false }, debug_meta: { images: applyDebugMetadata(client, cpuProfile.resources) }, profile: enrichedThreadProfile, transaction: { name: transaction, id: event_id, trace_id: trace_id || "", active_thread_id: PROFILER_THREAD_ID_STRING } }; return profile; } function createProfileChunkPayload(client, cpuProfile, { release, environment, trace_id, profiler_id, chunk_id, sdk }) { if (trace_id?.length !== 32) { DEBUG_BUILD && core.debug.log(`[Profiling] Invalid traceId: ${trace_id} on profiled event`); } const enrichedThreadProfile = enrichWithThreadInformation(cpuProfile); const profile = { chunk_id, client_sdk: { name: sdk?.name ?? "sentry.javascript.node", version: sdk?.version ?? "0.0.0" }, profiler_id, platform: "node", version: CONTINUOUS_FORMAT_VERSION, release, environment, measurements: cpuProfile.measurements, debug_meta: { images: applyDebugMetadata(client, cpuProfile.resources) }, profile: enrichedThreadProfile }; return profile; } function createProfilingChunkEvent(client, options, profile, sdk, identifiers) { if (!isValidProfileChunk(profile)) { return null; } return createProfileChunkPayload(client, profile, { release: options.release ?? "", environment: options.environment ?? "", trace_id: identifiers.trace_id ?? "", chunk_id: identifiers.chunk_id, profiler_id: identifiers.profiler_id, sdk }); } function isValidSampleRate(rate) { if (typeof rate !== "number" && typeof rate !== "boolean" || typeof rate === "number" && isNaN(rate)) { DEBUG_BUILD && core.debug.warn( `[Profiling] Invalid sample rate. Sample rate must be a boolean or a number between 0 and 1. Got ${JSON.stringify( rate )} of type ${JSON.stringify(typeof rate)}.` ); return false; } if (rate === true || rate === false) { return true; } if (rate < 0 || rate > 1) { DEBUG_BUILD && core.debug.warn(`[Profiling] Invalid sample rate. Sample rate must be between 0 and 1. Got ${rate}.`); return false; } return true; } function isValidProfile(profile) { if (profile.samples.length <= 1) { DEBUG_BUILD && // Log a warning if the profile has less than 2 samples so users can know why // they are not seeing any profiling data and we cant avoid the back and forth // of asking them to provide us with a dump of the profile data. core.debug.log("[Profiling] Discarding profile because it contains less than 2 samples"); return false; } if (!profile.profile_id) { return false; } return true; } function isValidProfileChunk(profile) { if (profile.samples.length <= 1) { DEBUG_BUILD && // Log a warning if the profile has less than 2 samples so users can know why // they are not seeing any profiling data and we cant avoid the back and forth // of asking them to provide us with a dump of the profile data. core.debug.log("[Profiling] Discarding profile chunk because it contains less than 2 samples"); return false; } return true; } function addProfilesToEnvelope(envelope, profiles) { if (!profiles.length) { return envelope; } for (const profile of profiles) { envelope[1].push([{ type: "profile" }, profile]); } return envelope; } function findProfiledTransactionsFromEnvelope(envelope) { const events = []; core.forEachEnvelopeItem(envelope, (item, type) => { if (type !== "transaction") { return; } for (let j = 1; j < item.length; j++) { const event = item[j]; if (!event) { continue; } const profile_id = event.contexts?.profile?.profile_id; if (event && profile_id) { events.push(event); } } }); return events; } function createEventEnvelopeHeaders(sdkInfo, tunnel, dsn) { return { event_id: core.uuid4(), sent_at: (/* @__PURE__ */ new Date()).toISOString(), ...sdkInfo && { sdk: sdkInfo }, ...!!tunnel && dsn && { dsn: core.dsnToString(dsn) } }; } function makeProfileChunkEnvelope(platform, chunk, sdkInfo, tunnel, dsn) { const profileChunkHeader = { type: "profile_chunk", platform }; return core.createEnvelope(createEventEnvelopeHeaders(sdkInfo, tunnel, dsn), [ [profileChunkHeader, chunk] ]); } function applyDebugMetadata(client, resource_paths) { const options = client.getOptions(); if (!options?.stackParser) { return []; } return core.getDebugImagesForResources(options.stackParser, resource_paths); } const MAX_PROFILE_DURATION_MS = 30 * 1e3; function maybeProfileSpan(client, span, customSamplingContext) { if (!worker_threads.isMainThread) { DEBUG_BUILD && core.debug.log("[Profiling] Skipping span profiling in worker thread."); return; } if (!core.spanIsSampled(span)) { return; } if (!client) { DEBUG_BUILD && core.debug.log("[Profiling] Profiling disabled, no client found."); return; } const options = client.getOptions(); if (!options) { DEBUG_BUILD && core.debug.log("[Profiling] Profiling disabled, no options found."); return; } const profilesSampler = options.profilesSampler; let profilesSampleRate = options.profilesSampleRate; if (typeof profilesSampler === "function") { const { description: spanName = "<unknown>", data } = core.spanToJSON(span); const parentSampled = true; profilesSampleRate = profilesSampler({ name: spanName, attributes: data, parentSampled, ...customSamplingContext }); } if (!isValidSampleRate(profilesSampleRate)) { DEBUG_BUILD && core.debug.warn("[Profiling] Discarding profile because of invalid sample rate."); return; } if (!profilesSampleRate) { DEBUG_BUILD && core.debug.log( `[Profiling] Discarding profile because ${typeof profilesSampler === "function" ? "profileSampler returned 0 or false" : "a negative sampling decision was inherited or profileSampleRate is set to 0"}` ); return; } const sampled = profilesSampleRate === true ? true : Math.random() < profilesSampleRate; if (!sampled) { DEBUG_BUILD && core.debug.log( `[Profiling] Discarding profile because it's not included in the random sample (sampling rate = ${Number( profilesSampleRate )})` ); return; } const profile_id = core.uuid4(); nodeCpuProfiler.CpuProfilerBindings.startProfiling(profile_id); DEBUG_BUILD && core.debug.log(`[Profiling] started profiling transaction: ${core.spanToJSON(span).description}`); return profile_id; } function stopSpanProfile(span, profile_id) { if (!profile_id) { return null; } const profile = nodeCpuProfiler.CpuProfilerBindings.stopProfiling(profile_id, 0); DEBUG_BUILD && core.debug.log(`[Profiling] stopped profiling of transaction: ${core.spanToJSON(span).description}`); if (!profile) { DEBUG_BUILD && core.debug.log( `[Profiling] profiler returned null profile for: ${core.spanToJSON(span).description}`, "this may indicate an overlapping span or a call to stopProfiling with a profile title that was never started" ); return null; } profile.profile_id = profile_id; return profile; } const CHUNK_INTERVAL_MS = 1e3 * 60; const PROFILE_MAP = new core.LRUMap(50); const PROFILE_TIMEOUTS = {}; function addToProfileQueue(profile_id, profile) { PROFILE_MAP.set(profile_id, profile); } function takeFromProfileQueue(profile_id) { const profile = PROFILE_MAP.get(profile_id); PROFILE_MAP.remove(profile_id); return profile; } class ContinuousProfiler { constructor() { this._client = void 0; this._chunkData = void 0; this._mode = void 0; this._legacyProfilerMode = void 0; this._profileLifecycle = void 0; this._sampled = void 0; this._sessionSamplingRate = void 0; } /** * Called when the profiler is attached to the client (continuous mode is enabled). If of the profiler * methods called before the profiler is initialized will result in a noop action with debug logs. * @param client */ initialize(client) { if (!worker_threads.isMainThread) { DEBUG_BUILD && core.debug.warn( "[Profiling] nodeProfilingIntegration() does not support worker threads \u2014 profiling will be disabled for this thread." ); return; } this._client = client; const options = client.getOptions(); this._mode = getProfilingMode(options); this._sessionSamplingRate = Math.random(); this._sampled = this._sessionSamplingRate < (options.profileSessionSampleRate ?? 0); this._profileLifecycle = options.profileLifecycle ?? "manual"; switch (this._mode) { case "legacy": { this._legacyProfilerMode = "profilesSampleRate" in options || "profilesSampler" in options ? "span" : "continuous"; DEBUG_BUILD && core.debug.log(`[Profiling] Profiling mode is ${this._legacyProfilerMode}.`); switch (this._legacyProfilerMode) { case "span": { this._setupAutomaticSpanProfiling(); break; } case "continuous": { break; } default: { DEBUG_BUILD && core.debug.warn( `[Profiling] Unknown profiler mode: ${this._legacyProfilerMode}, profiler was not initialized` ); break; } } break; } case "current": { this._setupSpanChunkInstrumentation(); DEBUG_BUILD && core.debug.log(`[Profiling] Profiling mode is ${this._profileLifecycle}.`); switch (this._profileLifecycle) { case "trace": { this._startTraceLifecycleProfiling(); break; } case "manual": { break; } default: { DEBUG_BUILD && core.debug.warn(`[Profiling] Unknown profiler mode: ${this._profileLifecycle}, profiler was not initialized`); break; } } break; } default: { DEBUG_BUILD && core.debug.warn(`[Profiling] Unknown profiler mode: ${this._mode}, profiler was not initialized`); break; } } this._client.on("beforeSendEvent", this._onBeforeSendThreadContextAssignment.bind(this)); } /** * Initializes a new profilerId session and schedules chunk profiling. * @returns void */ start() { if (this._mode === "current") { this._startProfiler(); return; } if (!this._client) { DEBUG_BUILD && core.debug.log("[Profiling] Failed to start, sentry client was never attached to the profiler."); return; } if (this._mode !== "legacy") { DEBUG_BUILD && core.debug.log("[Profiling] Continuous profiling is not supported in the current mode."); return; } if (this._legacyProfilerMode === "span") { DEBUG_BUILD && core.debug.log("[Profiling] Calls to profiler.start() are not supported in span profiling mode."); return; } this._stopChunkProfiling(); this._setupSpanChunkInstrumentation(); this._restartChunkProfiling(); } /** * Stops the current chunk and flushes the profile to Sentry. * @returns void */ stop() { if (this._mode === "current") { this._stopProfiler(); return; } if (!this._client) { DEBUG_BUILD && core.debug.log("[Profiling] Failed to stop, sentry client was never attached to the profiler."); return; } if (this._mode !== "legacy") { DEBUG_BUILD && core.debug.log("[Profiling] Continuous profiling is not supported in the current mode."); return; } if (this._legacyProfilerMode === "span") { DEBUG_BUILD && core.debug.log("[Profiling] Calls to profiler.stop() are not supported in span profiling mode."); return; } this._stopChunkProfiling(); this._teardownSpanChunkInstrumentation(); } _startProfiler() { if (this._mode !== "current") { DEBUG_BUILD && core.debug.log("[Profiling] Continuous profiling is not supported in the current mode."); return; } if (this._chunkData !== void 0) { DEBUG_BUILD && core.debug.log("[Profiling] Profile session already running, no-op."); return; } if (this._mode === "current") { if (!this._sampled) { DEBUG_BUILD && core.debug.log("[Profiling] Profile session not sampled, no-op."); return; } } if (this._profileLifecycle === "trace") { DEBUG_BUILD && core.debug.log( "[Profiling] You are using the trace profile lifecycle, manual calls to profiler.startProfiler() and profiler.stopProfiler() will be ignored." ); return; } this._startChunkProfiling(); } _stopProfiler() { if (this._mode !== "current") { DEBUG_BUILD && core.debug.log("[Profiling] Continuous profiling is not supported in the current mode."); return; } if (this._profileLifecycle === "trace") { DEBUG_BUILD && core.debug.log( "[Profiling] You are using the trace profile lifecycle, manual calls to profiler.startProfiler() and profiler.stopProfiler() will be ignored." ); return; } if (!this._chunkData) { DEBUG_BUILD && core.debug.log("[Profiling] No profile session running, no-op."); return; } this._stopChunkProfiling(); } /** * Starts trace lifecycle profiling. Profiling will remain active as long as there is an active span. */ _startTraceLifecycleProfiling() { if (!this._client) { DEBUG_BUILD && core.debug.log( "[Profiling] Failed to start trace lifecycle profiling, sentry client was never attached to the profiler." ); return; } let activeSpanCounter = 0; this._client.on("spanStart", (_span) => { if (activeSpanCounter === 0) { this._startChunkProfiling(); } activeSpanCounter++; }); this._client.on("spanEnd", (_span) => { if (activeSpanCounter === 1) { this._stopChunkProfiling(); } activeSpanCounter--; }); } _setupAutomaticSpanProfiling() { if (!this._client) { DEBUG_BUILD && core.debug.log( "[Profiling] Failed to setup automatic span profiling, sentry client was never attached to the profiler." ); return; } const spanToProfileIdMap = /* @__PURE__ */ new WeakMap(); this._client.on("spanStart", (span) => { if (span !== core.getRootSpan(span)) { return; } const profile_id = maybeProfileSpan(this._client, span); if (profile_id) { const options = this._client.getOptions(); const maxProfileDurationMs = options._experiments?.maxProfileDurationMs || MAX_PROFILE_DURATION_MS; if (PROFILE_TIMEOUTS[profile_id]) { global.clearTimeout(PROFILE_TIMEOUTS[profile_id]); delete PROFILE_TIMEOUTS[profile_id]; } const timeout = global.setTimeout(() => { DEBUG_BUILD && core.debug.log( "[Profiling] max profile duration elapsed, stopping profiling for:", core.spanToJSON(span).description ); const profile = stopSpanProfile(span, profile_id); if (profile) { addToProfileQueue(profile_id, profile); } }, maxProfileDurationMs); timeout.unref(); core.getIsolationScope().setContext("profile", { profile_id }); spanToProfileIdMap.set(span, profile_id); } }); this._client.on("spanEnd", (span) => { const profile_id = spanToProfileIdMap.get(span); if (profile_id) { if (PROFILE_TIMEOUTS[profile_id]) { global.clearTimeout(PROFILE_TIMEOUTS[profile_id]); delete PROFILE_TIMEOUTS[profile_id]; } const profile = stopSpanProfile(span, profile_id); if (profile) { addToProfileQueue(profile_id, profile); } } }); this._client.on("beforeEnvelope", (envelope) => { if (!PROFILE_MAP.size) { return; } const profiledTransactionEvents = findProfiledTransactionsFromEnvelope(envelope); if (!profiledTransactionEvents.length) { return; } const profilesToAddToEnvelope = []; for (const profiledTransaction of profiledTransactionEvents) { const profileContext = profiledTransaction.contexts?.profile; const profile_id = profileContext?.profile_id; if (!profile_id) { throw new TypeError("[Profiling] cannot find profile for a transaction without a profile context"); } if (profileContext) { delete profiledTransaction.contexts?.profile; } const cpuProfile = takeFromProfileQueue(profile_id); if (!cpuProfile) { DEBUG_BUILD && core.debug.log(`[Profiling] Could not retrieve profile for transaction: ${profile_id}`); continue; } const profile = createProfilingEvent(this._client, cpuProfile, profiledTransaction); if (!profile) return; profilesToAddToEnvelope.push(profile); this._client.emit("preprocessEvent", profile, { event_id: profiledTransaction.event_id }); this._client.emit("postprocessEvent", profile, { event_id: profiledTransaction.event_id }); } addProfilesToEnvelope(envelope, profilesToAddToEnvelope); }); } /** * Stop profiler and initializes profiling of the next chunk */ _restartChunkProfiling() { if (!this._client) { DEBUG_BUILD && core.debug.log("[Profiling] Profiler was never attached to the client."); return; } if (this._chunkData) { DEBUG_BUILD && core.debug.log( `[Profiling] Chunk with chunk_id ${this._chunkData.id} is still running, current chunk will be stopped a new chunk will be started.` ); this._stopChunkProfiling(); } this._startChunkProfiling(); } /** * Stops profiling of the current chunks and flushes the profile to Sentry */ _stopChunkProfiling() { if (!this._chunkData) { DEBUG_BUILD && core.debug.log("[Profiling] No chunk data found, no-op."); return; } if (this._chunkData?.timer) { global.clearTimeout(this._chunkData.timer); this._chunkData.timer = void 0; DEBUG_BUILD && core.debug.log(`[Profiling] Stopping profiling chunk: ${this._chunkData.id}`); } if (!this._client) { DEBUG_BUILD && core.debug.log("[Profiling] Failed to collect profile, sentry client was never attached to the profiler."); this._resetChunkData(); return; } if (!this._chunkData?.id) { DEBUG_BUILD && core.debug.log(`[Profiling] Failed to collect profile for: ${this._chunkData?.id}, the chunk_id is missing.`); this._resetChunkData(); return; } const profile = nodeCpuProfiler.CpuProfilerBindings.stopProfiling(this._chunkData.id, nodeCpuProfiler.ProfileFormat.CHUNK); if (!profile) { DEBUG_BUILD && core.debug.log(`[Profiling] Failed to collect profile for: ${this._chunkData.id}`); this._resetChunkData(); return; } if (!this._profilerId) { DEBUG_BUILD && core.debug.log("[Profiling] Profile chunk does not contain a valid profiler_id, this is a bug in the SDK"); this._resetChunkData(); return; } if (profile) { DEBUG_BUILD && core.debug.log(`[Profiling] Sending profile chunk ${this._chunkData.id}.`); } DEBUG_BUILD && core.debug.log(`[Profiling] Profile chunk ${this._chunkData.id} sent to Sentry.`); const chunk = createProfilingChunkEvent( this._client, this._client.getOptions(), profile, this._client.getSdkMetadata()?.sdk, { chunk_id: this._chunkData.id, trace_id: this._chunkData.startTraceID, profiler_id: this._profilerId } ); if (!chunk) { DEBUG_BUILD && core.debug.log(`[Profiling] Failed to create profile chunk for: ${this._chunkData.id}`); this._resetChunkData(); return; } this._flush(chunk); this._resetChunkData(); } /** * Flushes the profile chunk to Sentry. * @param chunk */ _flush(chunk) { if (!this._client) { DEBUG_BUILD && core.debug.log("[Profiling] Failed to collect profile, sentry client was never attached to the profiler."); return; } const transport = this._client.getTransport(); if (!transport) { DEBUG_BUILD && core.debug.log("[Profiling] No transport available to send profile chunk."); return; } const dsn = this._client.getDsn(); const metadata = this._client.getSdkMetadata(); const tunnel = this._client.getOptions().tunnel; const envelope = makeProfileChunkEnvelope("node", chunk, metadata?.sdk, tunnel, dsn); transport.send(envelope).then(null, (reason) => { DEBUG_BUILD && core.debug.error("Error while sending profile chunk envelope:", reason); }); } /** * Starts the profiler and registers the flush timer for a given chunk. * @param chunk */ _startChunkProfiling() { if (this._chunkData) { DEBUG_BUILD && core.debug.log("[Profiling] Chunk is already running, no-op."); return; } const traceId = core.getCurrentScope().getPropagationContext().traceId || core.getIsolationScope().getPropagationContext().traceId; const chunk = this._initializeChunk(traceId); nodeCpuProfiler.CpuProfilerBindings.startProfiling(chunk.id); DEBUG_BUILD && core.debug.log(`[Profiling] starting profiling chunk: ${chunk.id}`); chunk.timer = global.setTimeout(() => { DEBUG_BUILD && core.debug.log(`[Profiling] Stopping profiling chunk: ${chunk.id}`); this._stopChunkProfiling(); DEBUG_BUILD && core.debug.log("[Profiling] Starting new profiling chunk."); setImmediate(this._restartChunkProfiling.bind(this)); }, CHUNK_INTERVAL_MS); chunk.timer.unref(); } /** * Attaches profiling information to spans that were started * during a profiling session. */ _setupSpanChunkInstrumentation() { if (!this._client) { DEBUG_BUILD && core.debug.log("[Profiling] Failed to initialize span profiling, sentry client was never attached to the profiler."); return; } this._profilerId = core.uuid4(); core.getGlobalScope().setContext("profile", { profiler_id: this._profilerId }); } /** * Assigns thread_id and thread name context to a profiled event if there is an active profiler session */ _onBeforeSendThreadContextAssignment(event) { if (!this._client || !this._profilerId) return; this._assignThreadIdContext(event); } /** * Clear profiling information from global context when a profile is not running. */ _teardownSpanChunkInstrumentation() { this._profilerId = void 0; const globalScope = core.getGlobalScope(); globalScope.setContext("profile", {}); } /** * Initializes new profile chunk metadata */ _initializeChunk(traceId) { this._chunkData = { id: core.uuid4(), startTraceID: traceId, timer: void 0 }; return this._chunkData; } /** * Assigns thread_id and thread name context to a profiled event. */ _assignThreadIdContext(event) { if (!event?.contexts?.profile) { return; } if (!event.contexts) { return; } event.contexts.trace = { ...event.contexts?.trace ?? {}, data: { ...event.contexts?.trace?.data ?? {}, ["thread.id"]: PROFILER_THREAD_ID_STRING, ["thread.name"]: PROFILER_THREAD_NAME } }; } /** * Resets the current chunk state. */ _resetChunkData() { this._chunkData = void 0; } } const _nodeProfilingIntegration = (() => { if (![16, 18, 20, 22, 24, 26].includes(NODE_MAJOR)) { core.consoleSandbox(() => { console.warn( `[Sentry Profiling] You are using a Node.js version that does not have prebuilt binaries (${NODE_MAJOR}).`, "The @sentry/profiling-node package only has prebuilt support for the following LTS versions of Node.js: 16, 18, 20, 22, 24, 26.", "To use the @sentry/profiling-node package with this version of Node.js, you will need to compile the native addon from source.", "See: https://github.com/getsentry/sentry-javascript/tree/develop/packages/profiling-node#building-the-package-from-source" ); }); } return { name: "ProfilingIntegration", _profiler: new ContinuousProfiler(), setup(client) { DEBUG_BUILD && core.debug.log("[Profiling] Profiling integration setup."); this._profiler.initialize(client); return; } }; }); function getProfilingMode(options) { if ("profilesSampleRate" in options || "profilesSampler" in options) { return "legacy"; } if ("profileSessionSampleRate" in options || "profileLifecycle" in options) { return "current"; } return "legacy"; } const nodeProfilingIntegration = core.defineIntegration(_nodeProfilingIntegration); exports.nodeProfilingIntegration = nodeProfilingIntegration; //# sourceMappingURL=index.js.map