@sentry/node-native 10.65.0 → 10.67.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.
@@ -163,6 +163,14 @@ function getExceptionAndThreads(crashedThreadId, threads) {
163
163
  }
164
164
  };
165
165
  }
166
+ function hydrateScope(data) {
167
+ const scope = new core.Scope();
168
+ if (data) {
169
+ scope.update(data);
170
+ data.breadcrumbs?.forEach((breadcrumb) => scope.addBreadcrumb(breadcrumb));
171
+ }
172
+ return scope;
173
+ }
166
174
  function applyScopeToEvent(event, scope) {
167
175
  core.applyScopeDataToEvent(event, scope);
168
176
  if (!event.contexts?.trace) {
@@ -204,7 +212,7 @@ async function sendBlockEvent(crashedThreadId) {
204
212
  tags,
205
213
  ...getExceptionAndThreads(crashedThreadId, threads)
206
214
  };
207
- const scope = crashedThread.pollState?.scope ? new core.Scope().update(crashedThread.pollState.scope).getScopeData() : new core.Scope().getScopeData();
215
+ const scope = hydrateScope(crashedThread.pollState?.scope).getScopeData();
208
216
  if (crashedThread?.asyncState?.isolationScope) {
209
217
  const isolationScope = Object.assign(new core.Scope(), crashedThread.asyncState.isolationScope).getScopeData();
210
218
  core.mergeScopeData(scope, isolationScope);
@@ -1 +1 @@
1
- {"version":3,"file":"event-loop-block-watchdog.js","sources":["../../src/event-loop-block-watchdog.ts"],"sourcesContent":["import { workerData } from 'node:worker_threads';\nimport type { DebugImage, Event, ScopeData, Session, StackFrame, Thread } from '@sentry/core';\nimport {\n applyScopeDataToEvent,\n createEventEnvelope,\n createSessionEnvelope,\n filenameIsInApp,\n generateSpanId,\n getEnvelopeEndpointWithUrlEncodedAuth,\n makeSession,\n mergeScopeData,\n normalizeUrlToBase,\n Scope,\n stripSentryFramesAndReverse,\n updateSession,\n uuid4,\n} from '@sentry/core';\nimport { makeNodeTransport } from '@sentry/node';\nimport { captureStackTrace, getThreadsLastSeen } from '@sentry/node-native-stacktrace';\nimport type { ThreadState, WorkerStartData } from './common';\nimport { POLL_RATIO } from './common';\n\ntype CurrentScopes = {\n isolationScope: Scope;\n};\n\nconst {\n threshold,\n appRootPath,\n contexts,\n debug,\n dist,\n dsn,\n environment,\n maxEventsPerHour,\n release,\n sdkMetadata,\n staticTags: tags,\n tunnel,\n} = workerData as WorkerStartData;\n\nconst pollInterval = threshold / POLL_RATIO;\nconst triggeredThreads = new Set<string>();\n\nfunction log(...msg: unknown[]): void {\n if (debug) {\n // eslint-disable-next-line no-console\n console.log('[Sentry Event Loop Blocked Watchdog]', ...msg);\n }\n}\n\nfunction createRateLimiter(maxEventsPerHour: number): () => boolean {\n let currentHour = 0;\n let currentCount = 0;\n\n return function isRateLimited(): boolean {\n const hour = new Date().getHours();\n\n if (hour !== currentHour) {\n currentHour = hour;\n currentCount = 0;\n }\n\n if (currentCount >= maxEventsPerHour) {\n if (currentCount === maxEventsPerHour) {\n currentCount += 1;\n log(`Rate limit reached: ${currentCount} events in this hour`);\n }\n return true;\n }\n\n currentCount += 1;\n return false;\n };\n}\n\nconst url = getEnvelopeEndpointWithUrlEncodedAuth(dsn, tunnel, sdkMetadata.sdk);\nconst transport = makeNodeTransport({\n url,\n recordDroppedEvent: () => {\n //\n },\n});\nconst isRateLimited = createRateLimiter(maxEventsPerHour);\n\nasync function sendAbnormalSession(serializedSession: Session | undefined): Promise<void> {\n if (!serializedSession) {\n return;\n }\n\n log('Sending abnormal session');\n const session = makeSession(serializedSession);\n\n updateSession(session, {\n status: 'abnormal',\n abnormal_mechanism: 'anr_foreground',\n release,\n environment,\n });\n\n const envelope = createSessionEnvelope(session, dsn, sdkMetadata, tunnel);\n // Log the envelope so to aid in testing\n log(JSON.stringify(envelope));\n\n await transport.send(envelope);\n}\n\nlog('Started');\n\nfunction prepareStackFrames(stackFrames: StackFrame[] | undefined): StackFrame[] | undefined {\n if (!stackFrames) {\n return undefined;\n }\n\n // Strip Sentry frames and reverse the stack frames so they are in the correct order\n const strippedFrames = stripSentryFramesAndReverse(stackFrames);\n\n for (const frame of strippedFrames) {\n if (!frame.filename) {\n continue;\n }\n\n frame.in_app = filenameIsInApp(frame.filename);\n\n // If we have an app root path, rewrite the filenames to be relative to the app root\n if (appRootPath) {\n frame.filename = normalizeUrlToBase(frame.filename, appRootPath);\n }\n }\n\n return strippedFrames;\n}\n\nfunction stripFileProtocol(filename: string | undefined): string | undefined {\n if (!filename) {\n return undefined;\n }\n return filename.replace(/^file:\\/\\//, '');\n}\n\n// eslint-disable-next-line complexity\nfunction applyDebugMeta(event: Event, debugImages: Record<string, string>): void {\n if (Object.keys(debugImages).length === 0) {\n return;\n }\n\n const normalisedDebugImages = appRootPath ? {} : debugImages;\n if (appRootPath) {\n for (const [path, debugId] of Object.entries(debugImages)) {\n normalisedDebugImages[normalizeUrlToBase(path, appRootPath)] = debugId;\n }\n }\n\n const filenameToDebugId = new Map<string, string>();\n\n for (const exception of event.exception?.values || []) {\n for (const frame of exception.stacktrace?.frames || []) {\n const filename = stripFileProtocol(frame.abs_path || frame.filename);\n if (filename && normalisedDebugImages[filename]) {\n filenameToDebugId.set(filename, normalisedDebugImages[filename]);\n }\n }\n }\n\n for (const thread of event.threads?.values || []) {\n for (const frame of thread.stacktrace?.frames || []) {\n const filename = stripFileProtocol(frame.abs_path || frame.filename);\n if (filename && normalisedDebugImages[filename]) {\n filenameToDebugId.set(filename, normalisedDebugImages[filename]);\n }\n }\n }\n\n if (filenameToDebugId.size > 0) {\n const images: DebugImage[] = [];\n for (const [code_file, debug_id] of filenameToDebugId.entries()) {\n images.push({\n type: 'sourcemap',\n code_file,\n debug_id,\n });\n }\n event.debug_meta = { images };\n }\n}\n\nfunction getExceptionAndThreads(\n crashedThreadId: string,\n threads: ReturnType<typeof captureStackTrace<CurrentScopes, ThreadState>>,\n): Event {\n const crashedThread = threads[crashedThreadId];\n\n return {\n exception: {\n values: [\n {\n type: 'EventLoopBlocked',\n value: `Event Loop Blocked for at least ${threshold} ms`,\n stacktrace: { frames: prepareStackFrames(crashedThread?.frames) },\n // This ensures the UI doesn't say 'Crashed in' for the stack trace\n mechanism: { type: 'ANR' },\n thread_id: crashedThreadId,\n },\n ],\n },\n threads: {\n values: Object.entries(threads).map(([threadId, threadState]) => {\n const crashed = threadId === crashedThreadId;\n\n const thread: Thread = {\n id: threadId,\n name: threadId === '0' ? 'main' : `worker-${threadId}`,\n crashed,\n current: true,\n main: threadId === '0',\n };\n\n if (!crashed) {\n thread.stacktrace = { frames: prepareStackFrames(threadState.frames) };\n }\n\n return thread;\n }),\n },\n };\n}\n\nfunction applyScopeToEvent(event: Event, scope: ScopeData): void {\n applyScopeDataToEvent(event, scope);\n\n if (!event.contexts?.trace) {\n const { traceId, parentSpanId, propagationSpanId } = scope.propagationContext;\n event.contexts = {\n trace: {\n trace_id: traceId,\n span_id: propagationSpanId || generateSpanId(),\n parent_span_id: parentSpanId,\n },\n ...event.contexts,\n };\n }\n}\n\nasync function sendBlockEvent(crashedThreadId: string): Promise<void> {\n if (isRateLimited()) {\n return;\n }\n\n const threads = captureStackTrace<CurrentScopes, ThreadState>();\n const crashedThread = threads[crashedThreadId];\n\n if (!crashedThread) {\n log(`No thread found with ID '${crashedThreadId}'`);\n return;\n }\n\n try {\n await sendAbnormalSession(crashedThread.pollState?.session);\n } catch (error) {\n log(`Failed to send abnormal session for thread '${crashedThreadId}':`, error);\n }\n\n log('Sending event');\n\n const event: Event = {\n event_id: uuid4(),\n contexts,\n release,\n environment,\n dist,\n platform: 'node',\n level: 'error',\n tags,\n ...getExceptionAndThreads(crashedThreadId, threads),\n };\n\n const scope = crashedThread.pollState?.scope\n ? new Scope().update(crashedThread.pollState.scope).getScopeData()\n : new Scope().getScopeData();\n\n if (crashedThread?.asyncState?.isolationScope) {\n // We need to rehydrate the scope from the serialized object with properties beginning with _user, etc\n const isolationScope = Object.assign(new Scope(), crashedThread.asyncState.isolationScope).getScopeData();\n mergeScopeData(scope, isolationScope);\n }\n applyScopeToEvent(event, scope);\n\n const allDebugImages: Record<string, string> = Object.values(threads).reduce((acc, threadState) => {\n return { ...acc, ...threadState.pollState?.debugImages };\n }, {});\n\n applyDebugMeta(event, allDebugImages);\n\n const envelope = createEventEnvelope(event, dsn, sdkMetadata, tunnel);\n // Log the envelope to aid in testing\n log(JSON.stringify(envelope));\n\n await transport.send(envelope);\n await transport.flush(2000);\n}\n\nsetInterval(async () => {\n for (const [threadId, time] of Object.entries(getThreadsLastSeen())) {\n if (time > threshold) {\n if (triggeredThreads.has(threadId)) {\n continue;\n }\n\n log(`Blocked thread detected '${threadId}' last polled ${time} ms ago.`);\n triggeredThreads.add(threadId);\n\n try {\n await sendBlockEvent(threadId);\n } catch (error) {\n log(`Failed to send event for thread '${threadId}':`, error);\n }\n } else {\n triggeredThreads.delete(threadId);\n }\n }\n}, pollInterval);\n"],"names":["workerData","POLL_RATIO","maxEventsPerHour","isRateLimited","getEnvelopeEndpointWithUrlEncodedAuth","makeNodeTransport","makeSession","updateSession","createSessionEnvelope","stripSentryFramesAndReverse","filenameIsInApp","normalizeUrlToBase","applyScopeDataToEvent","generateSpanId","captureStackTrace","uuid4","Scope","mergeScopeData","createEventEnvelope","getThreadsLastSeen"],"mappings":"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"}
1
+ {"version":3,"file":"event-loop-block-watchdog.js","sources":["../../src/event-loop-block-watchdog.ts"],"sourcesContent":["import { workerData } from 'node:worker_threads';\nimport type { DebugImage, Event, ScopeData, Session, StackFrame, Thread } from '@sentry/core';\nimport {\n applyScopeDataToEvent,\n createEventEnvelope,\n createSessionEnvelope,\n filenameIsInApp,\n generateSpanId,\n getEnvelopeEndpointWithUrlEncodedAuth,\n makeSession,\n mergeScopeData,\n normalizeUrlToBase,\n Scope,\n stripSentryFramesAndReverse,\n updateSession,\n uuid4,\n} from '@sentry/core';\nimport { makeNodeTransport } from '@sentry/node';\nimport { captureStackTrace, getThreadsLastSeen } from '@sentry/node-native-stacktrace';\nimport type { ThreadState, WorkerStartData } from './common';\nimport { POLL_RATIO } from './common';\n\ntype CurrentScopes = {\n isolationScope: Scope;\n};\n\nconst {\n threshold,\n appRootPath,\n contexts,\n debug,\n dist,\n dsn,\n environment,\n maxEventsPerHour,\n release,\n sdkMetadata,\n staticTags: tags,\n tunnel,\n} = workerData as WorkerStartData;\n\nconst pollInterval = threshold / POLL_RATIO;\nconst triggeredThreads = new Set<string>();\n\nfunction log(...msg: unknown[]): void {\n if (debug) {\n // eslint-disable-next-line no-console\n console.log('[Sentry Event Loop Blocked Watchdog]', ...msg);\n }\n}\n\nfunction createRateLimiter(maxEventsPerHour: number): () => boolean {\n let currentHour = 0;\n let currentCount = 0;\n\n return function isRateLimited(): boolean {\n const hour = new Date().getHours();\n\n if (hour !== currentHour) {\n currentHour = hour;\n currentCount = 0;\n }\n\n if (currentCount >= maxEventsPerHour) {\n if (currentCount === maxEventsPerHour) {\n currentCount += 1;\n log(`Rate limit reached: ${currentCount} events in this hour`);\n }\n return true;\n }\n\n currentCount += 1;\n return false;\n };\n}\n\nconst url = getEnvelopeEndpointWithUrlEncodedAuth(dsn, tunnel, sdkMetadata.sdk);\nconst transport = makeNodeTransport({\n url,\n recordDroppedEvent: () => {\n //\n },\n});\nconst isRateLimited = createRateLimiter(maxEventsPerHour);\n\nasync function sendAbnormalSession(serializedSession: Session | undefined): Promise<void> {\n if (!serializedSession) {\n return;\n }\n\n log('Sending abnormal session');\n const session = makeSession(serializedSession);\n\n updateSession(session, {\n status: 'abnormal',\n abnormal_mechanism: 'anr_foreground',\n release,\n environment,\n });\n\n const envelope = createSessionEnvelope(session, dsn, sdkMetadata, tunnel);\n // Log the envelope so to aid in testing\n log(JSON.stringify(envelope));\n\n await transport.send(envelope);\n}\n\nlog('Started');\n\nfunction prepareStackFrames(stackFrames: StackFrame[] | undefined): StackFrame[] | undefined {\n if (!stackFrames) {\n return undefined;\n }\n\n // Strip Sentry frames and reverse the stack frames so they are in the correct order\n const strippedFrames = stripSentryFramesAndReverse(stackFrames);\n\n for (const frame of strippedFrames) {\n if (!frame.filename) {\n continue;\n }\n\n frame.in_app = filenameIsInApp(frame.filename);\n\n // If we have an app root path, rewrite the filenames to be relative to the app root\n if (appRootPath) {\n frame.filename = normalizeUrlToBase(frame.filename, appRootPath);\n }\n }\n\n return strippedFrames;\n}\n\nfunction stripFileProtocol(filename: string | undefined): string | undefined {\n if (!filename) {\n return undefined;\n }\n return filename.replace(/^file:\\/\\//, '');\n}\n\n// eslint-disable-next-line complexity\nfunction applyDebugMeta(event: Event, debugImages: Record<string, string>): void {\n if (Object.keys(debugImages).length === 0) {\n return;\n }\n\n const normalisedDebugImages = appRootPath ? {} : debugImages;\n if (appRootPath) {\n for (const [path, debugId] of Object.entries(debugImages)) {\n normalisedDebugImages[normalizeUrlToBase(path, appRootPath)] = debugId;\n }\n }\n\n const filenameToDebugId = new Map<string, string>();\n\n for (const exception of event.exception?.values || []) {\n for (const frame of exception.stacktrace?.frames || []) {\n const filename = stripFileProtocol(frame.abs_path || frame.filename);\n if (filename && normalisedDebugImages[filename]) {\n filenameToDebugId.set(filename, normalisedDebugImages[filename]);\n }\n }\n }\n\n for (const thread of event.threads?.values || []) {\n for (const frame of thread.stacktrace?.frames || []) {\n const filename = stripFileProtocol(frame.abs_path || frame.filename);\n if (filename && normalisedDebugImages[filename]) {\n filenameToDebugId.set(filename, normalisedDebugImages[filename]);\n }\n }\n }\n\n if (filenameToDebugId.size > 0) {\n const images: DebugImage[] = [];\n for (const [code_file, debug_id] of filenameToDebugId.entries()) {\n images.push({\n type: 'sourcemap',\n code_file,\n debug_id,\n });\n }\n event.debug_meta = { images };\n }\n}\n\nfunction getExceptionAndThreads(\n crashedThreadId: string,\n threads: ReturnType<typeof captureStackTrace<CurrentScopes, ThreadState>>,\n): Event {\n const crashedThread = threads[crashedThreadId];\n\n return {\n exception: {\n values: [\n {\n type: 'EventLoopBlocked',\n value: `Event Loop Blocked for at least ${threshold} ms`,\n stacktrace: { frames: prepareStackFrames(crashedThread?.frames) },\n // This ensures the UI doesn't say 'Crashed in' for the stack trace\n mechanism: { type: 'ANR' },\n thread_id: crashedThreadId,\n },\n ],\n },\n threads: {\n values: Object.entries(threads).map(([threadId, threadState]) => {\n const crashed = threadId === crashedThreadId;\n\n const thread: Thread = {\n id: threadId,\n name: threadId === '0' ? 'main' : `worker-${threadId}`,\n crashed,\n current: true,\n main: threadId === '0',\n };\n\n if (!crashed) {\n thread.stacktrace = { frames: prepareStackFrames(threadState.frames) };\n }\n\n return thread;\n }),\n },\n };\n}\n\n/**\n * Rehydrates a Scope from serialized ScopeData that has been passed over a JSON serialization boundary.\n *\n * `Scope.update()` only handles `ScopeContext` fields, so breadcrumbs have to be carried over separately.\n * Attachments are deliberately not carried over since their binary data does not survive JSON serialization.\n */\nfunction hydrateScope(data: Partial<ScopeData> | undefined): Scope {\n const scope = new Scope();\n if (data) {\n scope.update(data);\n data.breadcrumbs?.forEach(breadcrumb => scope.addBreadcrumb(breadcrumb));\n }\n return scope;\n}\n\nfunction applyScopeToEvent(event: Event, scope: ScopeData): void {\n applyScopeDataToEvent(event, scope);\n\n if (!event.contexts?.trace) {\n const { traceId, parentSpanId, propagationSpanId } = scope.propagationContext;\n event.contexts = {\n trace: {\n trace_id: traceId,\n span_id: propagationSpanId || generateSpanId(),\n parent_span_id: parentSpanId,\n },\n ...event.contexts,\n };\n }\n}\n\nasync function sendBlockEvent(crashedThreadId: string): Promise<void> {\n if (isRateLimited()) {\n return;\n }\n\n const threads = captureStackTrace<CurrentScopes, ThreadState>();\n const crashedThread = threads[crashedThreadId];\n\n if (!crashedThread) {\n log(`No thread found with ID '${crashedThreadId}'`);\n return;\n }\n\n try {\n await sendAbnormalSession(crashedThread.pollState?.session);\n } catch (error) {\n log(`Failed to send abnormal session for thread '${crashedThreadId}':`, error);\n }\n\n log('Sending event');\n\n const event: Event = {\n event_id: uuid4(),\n contexts,\n release,\n environment,\n dist,\n platform: 'node',\n level: 'error',\n tags,\n ...getExceptionAndThreads(crashedThreadId, threads),\n };\n\n const scope = hydrateScope(crashedThread.pollState?.scope).getScopeData();\n\n if (crashedThread?.asyncState?.isolationScope) {\n // We need to rehydrate the scope from the serialized object with properties beginning with _user, etc\n const isolationScope = Object.assign(new Scope(), crashedThread.asyncState.isolationScope).getScopeData();\n mergeScopeData(scope, isolationScope);\n }\n applyScopeToEvent(event, scope);\n\n const allDebugImages: Record<string, string> = Object.values(threads).reduce((acc, threadState) => {\n return { ...acc, ...threadState.pollState?.debugImages };\n }, {});\n\n applyDebugMeta(event, allDebugImages);\n\n const envelope = createEventEnvelope(event, dsn, sdkMetadata, tunnel);\n // Log the envelope to aid in testing\n log(JSON.stringify(envelope));\n\n await transport.send(envelope);\n await transport.flush(2000);\n}\n\nsetInterval(async () => {\n for (const [threadId, time] of Object.entries(getThreadsLastSeen())) {\n if (time > threshold) {\n if (triggeredThreads.has(threadId)) {\n continue;\n }\n\n log(`Blocked thread detected '${threadId}' last polled ${time} ms ago.`);\n triggeredThreads.add(threadId);\n\n try {\n await sendBlockEvent(threadId);\n } catch (error) {\n log(`Failed to send event for thread '${threadId}':`, error);\n }\n } else {\n triggeredThreads.delete(threadId);\n }\n }\n}, pollInterval);\n"],"names":["workerData","POLL_RATIO","maxEventsPerHour","isRateLimited","getEnvelopeEndpointWithUrlEncodedAuth","makeNodeTransport","makeSession","updateSession","createSessionEnvelope","stripSentryFramesAndReverse","filenameIsInApp","normalizeUrlToBase","Scope","applyScopeDataToEvent","generateSpanId","captureStackTrace","uuid4","mergeScopeData","createEventEnvelope","getThreadsLastSeen"],"mappings":"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"}
@@ -163,6 +163,14 @@ function getExceptionAndThreads(crashedThreadId, threads) {
163
163
  }
164
164
  };
165
165
  }
166
+ function hydrateScope(data) {
167
+ const scope = new Scope();
168
+ if (data) {
169
+ scope.update(data);
170
+ data.breadcrumbs?.forEach((breadcrumb) => scope.addBreadcrumb(breadcrumb));
171
+ }
172
+ return scope;
173
+ }
166
174
  function applyScopeToEvent(event, scope) {
167
175
  applyScopeDataToEvent(event, scope);
168
176
  if (!event.contexts?.trace) {
@@ -204,7 +212,7 @@ async function sendBlockEvent(crashedThreadId) {
204
212
  tags,
205
213
  ...getExceptionAndThreads(crashedThreadId, threads)
206
214
  };
207
- const scope = crashedThread.pollState?.scope ? new Scope().update(crashedThread.pollState.scope).getScopeData() : new Scope().getScopeData();
215
+ const scope = hydrateScope(crashedThread.pollState?.scope).getScopeData();
208
216
  if (crashedThread?.asyncState?.isolationScope) {
209
217
  const isolationScope = Object.assign(new Scope(), crashedThread.asyncState.isolationScope).getScopeData();
210
218
  mergeScopeData(scope, isolationScope);
@@ -1 +1 @@
1
- {"version":3,"file":"event-loop-block-watchdog.js","sources":["../../src/event-loop-block-watchdog.ts"],"sourcesContent":["import { workerData } from 'node:worker_threads';\nimport type { DebugImage, Event, ScopeData, Session, StackFrame, Thread } from '@sentry/core';\nimport {\n applyScopeDataToEvent,\n createEventEnvelope,\n createSessionEnvelope,\n filenameIsInApp,\n generateSpanId,\n getEnvelopeEndpointWithUrlEncodedAuth,\n makeSession,\n mergeScopeData,\n normalizeUrlToBase,\n Scope,\n stripSentryFramesAndReverse,\n updateSession,\n uuid4,\n} from '@sentry/core';\nimport { makeNodeTransport } from '@sentry/node';\nimport { captureStackTrace, getThreadsLastSeen } from '@sentry/node-native-stacktrace';\nimport type { ThreadState, WorkerStartData } from './common';\nimport { POLL_RATIO } from './common';\n\ntype CurrentScopes = {\n isolationScope: Scope;\n};\n\nconst {\n threshold,\n appRootPath,\n contexts,\n debug,\n dist,\n dsn,\n environment,\n maxEventsPerHour,\n release,\n sdkMetadata,\n staticTags: tags,\n tunnel,\n} = workerData as WorkerStartData;\n\nconst pollInterval = threshold / POLL_RATIO;\nconst triggeredThreads = new Set<string>();\n\nfunction log(...msg: unknown[]): void {\n if (debug) {\n // eslint-disable-next-line no-console\n console.log('[Sentry Event Loop Blocked Watchdog]', ...msg);\n }\n}\n\nfunction createRateLimiter(maxEventsPerHour: number): () => boolean {\n let currentHour = 0;\n let currentCount = 0;\n\n return function isRateLimited(): boolean {\n const hour = new Date().getHours();\n\n if (hour !== currentHour) {\n currentHour = hour;\n currentCount = 0;\n }\n\n if (currentCount >= maxEventsPerHour) {\n if (currentCount === maxEventsPerHour) {\n currentCount += 1;\n log(`Rate limit reached: ${currentCount} events in this hour`);\n }\n return true;\n }\n\n currentCount += 1;\n return false;\n };\n}\n\nconst url = getEnvelopeEndpointWithUrlEncodedAuth(dsn, tunnel, sdkMetadata.sdk);\nconst transport = makeNodeTransport({\n url,\n recordDroppedEvent: () => {\n //\n },\n});\nconst isRateLimited = createRateLimiter(maxEventsPerHour);\n\nasync function sendAbnormalSession(serializedSession: Session | undefined): Promise<void> {\n if (!serializedSession) {\n return;\n }\n\n log('Sending abnormal session');\n const session = makeSession(serializedSession);\n\n updateSession(session, {\n status: 'abnormal',\n abnormal_mechanism: 'anr_foreground',\n release,\n environment,\n });\n\n const envelope = createSessionEnvelope(session, dsn, sdkMetadata, tunnel);\n // Log the envelope so to aid in testing\n log(JSON.stringify(envelope));\n\n await transport.send(envelope);\n}\n\nlog('Started');\n\nfunction prepareStackFrames(stackFrames: StackFrame[] | undefined): StackFrame[] | undefined {\n if (!stackFrames) {\n return undefined;\n }\n\n // Strip Sentry frames and reverse the stack frames so they are in the correct order\n const strippedFrames = stripSentryFramesAndReverse(stackFrames);\n\n for (const frame of strippedFrames) {\n if (!frame.filename) {\n continue;\n }\n\n frame.in_app = filenameIsInApp(frame.filename);\n\n // If we have an app root path, rewrite the filenames to be relative to the app root\n if (appRootPath) {\n frame.filename = normalizeUrlToBase(frame.filename, appRootPath);\n }\n }\n\n return strippedFrames;\n}\n\nfunction stripFileProtocol(filename: string | undefined): string | undefined {\n if (!filename) {\n return undefined;\n }\n return filename.replace(/^file:\\/\\//, '');\n}\n\n// eslint-disable-next-line complexity\nfunction applyDebugMeta(event: Event, debugImages: Record<string, string>): void {\n if (Object.keys(debugImages).length === 0) {\n return;\n }\n\n const normalisedDebugImages = appRootPath ? {} : debugImages;\n if (appRootPath) {\n for (const [path, debugId] of Object.entries(debugImages)) {\n normalisedDebugImages[normalizeUrlToBase(path, appRootPath)] = debugId;\n }\n }\n\n const filenameToDebugId = new Map<string, string>();\n\n for (const exception of event.exception?.values || []) {\n for (const frame of exception.stacktrace?.frames || []) {\n const filename = stripFileProtocol(frame.abs_path || frame.filename);\n if (filename && normalisedDebugImages[filename]) {\n filenameToDebugId.set(filename, normalisedDebugImages[filename]);\n }\n }\n }\n\n for (const thread of event.threads?.values || []) {\n for (const frame of thread.stacktrace?.frames || []) {\n const filename = stripFileProtocol(frame.abs_path || frame.filename);\n if (filename && normalisedDebugImages[filename]) {\n filenameToDebugId.set(filename, normalisedDebugImages[filename]);\n }\n }\n }\n\n if (filenameToDebugId.size > 0) {\n const images: DebugImage[] = [];\n for (const [code_file, debug_id] of filenameToDebugId.entries()) {\n images.push({\n type: 'sourcemap',\n code_file,\n debug_id,\n });\n }\n event.debug_meta = { images };\n }\n}\n\nfunction getExceptionAndThreads(\n crashedThreadId: string,\n threads: ReturnType<typeof captureStackTrace<CurrentScopes, ThreadState>>,\n): Event {\n const crashedThread = threads[crashedThreadId];\n\n return {\n exception: {\n values: [\n {\n type: 'EventLoopBlocked',\n value: `Event Loop Blocked for at least ${threshold} ms`,\n stacktrace: { frames: prepareStackFrames(crashedThread?.frames) },\n // This ensures the UI doesn't say 'Crashed in' for the stack trace\n mechanism: { type: 'ANR' },\n thread_id: crashedThreadId,\n },\n ],\n },\n threads: {\n values: Object.entries(threads).map(([threadId, threadState]) => {\n const crashed = threadId === crashedThreadId;\n\n const thread: Thread = {\n id: threadId,\n name: threadId === '0' ? 'main' : `worker-${threadId}`,\n crashed,\n current: true,\n main: threadId === '0',\n };\n\n if (!crashed) {\n thread.stacktrace = { frames: prepareStackFrames(threadState.frames) };\n }\n\n return thread;\n }),\n },\n };\n}\n\nfunction applyScopeToEvent(event: Event, scope: ScopeData): void {\n applyScopeDataToEvent(event, scope);\n\n if (!event.contexts?.trace) {\n const { traceId, parentSpanId, propagationSpanId } = scope.propagationContext;\n event.contexts = {\n trace: {\n trace_id: traceId,\n span_id: propagationSpanId || generateSpanId(),\n parent_span_id: parentSpanId,\n },\n ...event.contexts,\n };\n }\n}\n\nasync function sendBlockEvent(crashedThreadId: string): Promise<void> {\n if (isRateLimited()) {\n return;\n }\n\n const threads = captureStackTrace<CurrentScopes, ThreadState>();\n const crashedThread = threads[crashedThreadId];\n\n if (!crashedThread) {\n log(`No thread found with ID '${crashedThreadId}'`);\n return;\n }\n\n try {\n await sendAbnormalSession(crashedThread.pollState?.session);\n } catch (error) {\n log(`Failed to send abnormal session for thread '${crashedThreadId}':`, error);\n }\n\n log('Sending event');\n\n const event: Event = {\n event_id: uuid4(),\n contexts,\n release,\n environment,\n dist,\n platform: 'node',\n level: 'error',\n tags,\n ...getExceptionAndThreads(crashedThreadId, threads),\n };\n\n const scope = crashedThread.pollState?.scope\n ? new Scope().update(crashedThread.pollState.scope).getScopeData()\n : new Scope().getScopeData();\n\n if (crashedThread?.asyncState?.isolationScope) {\n // We need to rehydrate the scope from the serialized object with properties beginning with _user, etc\n const isolationScope = Object.assign(new Scope(), crashedThread.asyncState.isolationScope).getScopeData();\n mergeScopeData(scope, isolationScope);\n }\n applyScopeToEvent(event, scope);\n\n const allDebugImages: Record<string, string> = Object.values(threads).reduce((acc, threadState) => {\n return { ...acc, ...threadState.pollState?.debugImages };\n }, {});\n\n applyDebugMeta(event, allDebugImages);\n\n const envelope = createEventEnvelope(event, dsn, sdkMetadata, tunnel);\n // Log the envelope to aid in testing\n log(JSON.stringify(envelope));\n\n await transport.send(envelope);\n await transport.flush(2000);\n}\n\nsetInterval(async () => {\n for (const [threadId, time] of Object.entries(getThreadsLastSeen())) {\n if (time > threshold) {\n if (triggeredThreads.has(threadId)) {\n continue;\n }\n\n log(`Blocked thread detected '${threadId}' last polled ${time} ms ago.`);\n triggeredThreads.add(threadId);\n\n try {\n await sendBlockEvent(threadId);\n } catch (error) {\n log(`Failed to send event for thread '${threadId}':`, error);\n }\n } else {\n triggeredThreads.delete(threadId);\n }\n }\n}, pollInterval);\n"],"names":["maxEventsPerHour","isRateLimited"],"mappings":";;;;;;AA0BA,MAAM;AAAA,EACJ,SAAA;AAAA,EACA,WAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,GAAA;AAAA,EACA,WAAA;AAAA,EACA,gBAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA;AAAA,EACA,UAAA,EAAY,IAAA;AAAA,EACZ;AACF,CAAA,GAAI,UAAA;AAEJ,MAAM,eAAe,SAAA,GAAY,UAAA;AACjC,MAAM,gBAAA,uBAAuB,GAAA,EAAY;AAEzC,SAAS,OAAO,GAAA,EAAsB;AACpC,EAAA,IAAI,KAAA,EAAO;AAET,IAAA,OAAA,CAAQ,GAAA,CAAI,sCAAA,EAAwC,GAAG,GAAG,CAAA;AAAA,EAC5D;AACF;AAEA,SAAS,kBAAkBA,iBAAAA,EAAyC;AAClE,EAAA,IAAI,WAAA,GAAc,CAAA;AAClB,EAAA,IAAI,YAAA,GAAe,CAAA;AAEnB,EAAA,OAAO,SAASC,cAAAA,GAAyB;AACvC,IAAA,MAAM,IAAA,GAAA,iBAAO,IAAI,IAAA,EAAK,EAAE,QAAA,EAAS;AAEjC,IAAA,IAAI,SAAS,WAAA,EAAa;AACxB,MAAA,WAAA,GAAc,IAAA;AACd,MAAA,YAAA,GAAe,CAAA;AAAA,IACjB;AAEA,IAAA,IAAI,gBAAgBD,iBAAAA,EAAkB;AACpC,MAAA,IAAI,iBAAiBA,iBAAAA,EAAkB;AACrC,QAAA,YAAA,IAAgB,CAAA;AAChB,QAAA,GAAA,CAAI,CAAA,oBAAA,EAAuB,YAAY,CAAA,oBAAA,CAAsB,CAAA;AAAA,MAC/D;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,YAAA,IAAgB,CAAA;AAChB,IAAA,OAAO,KAAA;AAAA,EACT,CAAA;AACF;AAEA,MAAM,GAAA,GAAM,qCAAA,CAAsC,GAAA,EAAK,MAAA,EAAQ,YAAY,GAAG,CAAA;AAC9E,MAAM,YAAY,iBAAA,CAAkB;AAAA,EAClC,GAAA;AAAA,EACA,oBAAoB,MAAM;AAAA,EAE1B;AACF,CAAC,CAAA;AACD,MAAM,aAAA,GAAgB,kBAAkB,gBAAgB,CAAA;AAExD,eAAe,oBAAoB,iBAAA,EAAuD;AACxF,EAAA,IAAI,CAAC,iBAAA,EAAmB;AACtB,IAAA;AAAA,EACF;AAEA,EAAA,GAAA,CAAI,0BAA0B,CAAA;AAC9B,EAAA,MAAM,OAAA,GAAU,YAAY,iBAAiB,CAAA;AAE7C,EAAA,aAAA,CAAc,OAAA,EAAS;AAAA,IACrB,MAAA,EAAQ,UAAA;AAAA,IACR,kBAAA,EAAoB,gBAAA;AAAA,IACpB,OAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,QAAA,GAAW,qBAAA,CAAsB,OAAA,EAAS,GAAA,EAAK,aAAa,MAAM,CAAA;AAExE,EAAA,GAAA,CAAI,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAC,CAAA;AAE5B,EAAA,MAAM,SAAA,CAAU,KAAK,QAAQ,CAAA;AAC/B;AAEA,GAAA,CAAI,SAAS,CAAA;AAEb,SAAS,mBAAmB,WAAA,EAAiE;AAC3F,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,OAAO,MAAA;AAAA,EACT;AAGA,EAAA,MAAM,cAAA,GAAiB,4BAA4B,WAAW,CAAA;AAE9D,EAAA,KAAA,MAAW,SAAS,cAAA,EAAgB;AAClC,IAAA,IAAI,CAAC,MAAM,QAAA,EAAU;AACnB,MAAA;AAAA,IACF;AAEA,IAAA,KAAA,CAAM,MAAA,GAAS,eAAA,CAAgB,KAAA,CAAM,QAAQ,CAAA;AAG7C,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,KAAA,CAAM,QAAA,GAAW,kBAAA,CAAmB,KAAA,CAAM,QAAA,EAAU,WAAW,CAAA;AAAA,IACjE;AAAA,EACF;AAEA,EAAA,OAAO,cAAA;AACT;AAEA,SAAS,kBAAkB,QAAA,EAAkD;AAC3E,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,QAAA,CAAS,OAAA,CAAQ,YAAA,EAAc,EAAE,CAAA;AAC1C;AAGA,SAAS,cAAA,CAAe,OAAc,WAAA,EAA2C;AAC/E,EAAA,IAAI,MAAA,CAAO,IAAA,CAAK,WAAW,CAAA,CAAE,WAAW,CAAA,EAAG;AACzC,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,qBAAA,GAAwB,WAAA,GAAc,EAAC,GAAI,WAAA;AACjD,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,OAAO,KAAK,MAAA,CAAO,OAAA,CAAQ,WAAW,CAAA,EAAG;AACzD,MAAA,qBAAA,CAAsB,kBAAA,CAAmB,IAAA,EAAM,WAAW,CAAC,CAAA,GAAI,OAAA;AAAA,IACjE;AAAA,EACF;AAEA,EAAA,MAAM,iBAAA,uBAAwB,GAAA,EAAoB;AAElD,EAAA,KAAA,MAAW,SAAA,IAAa,KAAA,CAAM,SAAA,EAAW,MAAA,IAAU,EAAC,EAAG;AACrD,IAAA,KAAA,MAAW,KAAA,IAAS,SAAA,CAAU,UAAA,EAAY,MAAA,IAAU,EAAC,EAAG;AACtD,MAAA,MAAM,QAAA,GAAW,iBAAA,CAAkB,KAAA,CAAM,QAAA,IAAY,MAAM,QAAQ,CAAA;AACnE,MAAA,IAAI,QAAA,IAAY,qBAAA,CAAsB,QAAQ,CAAA,EAAG;AAC/C,QAAA,iBAAA,CAAkB,GAAA,CAAI,QAAA,EAAU,qBAAA,CAAsB,QAAQ,CAAC,CAAA;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAEA,EAAA,KAAA,MAAW,MAAA,IAAU,KAAA,CAAM,OAAA,EAAS,MAAA,IAAU,EAAC,EAAG;AAChD,IAAA,KAAA,MAAW,KAAA,IAAS,MAAA,CAAO,UAAA,EAAY,MAAA,IAAU,EAAC,EAAG;AACnD,MAAA,MAAM,QAAA,GAAW,iBAAA,CAAkB,KAAA,CAAM,QAAA,IAAY,MAAM,QAAQ,CAAA;AACnE,MAAA,IAAI,QAAA,IAAY,qBAAA,CAAsB,QAAQ,CAAA,EAAG;AAC/C,QAAA,iBAAA,CAAkB,GAAA,CAAI,QAAA,EAAU,qBAAA,CAAsB,QAAQ,CAAC,CAAA;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAEA,EAAA,IAAI,iBAAA,CAAkB,OAAO,CAAA,EAAG;AAC9B,IAAA,MAAM,SAAuB,EAAC;AAC9B,IAAA,KAAA,MAAW,CAAC,SAAA,EAAW,QAAQ,CAAA,IAAK,iBAAA,CAAkB,SAAQ,EAAG;AAC/D,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,WAAA;AAAA,QACN,SAAA;AAAA,QACA;AAAA,OACD,CAAA;AAAA,IACH;AACA,IAAA,KAAA,CAAM,UAAA,GAAa,EAAE,MAAA,EAAO;AAAA,EAC9B;AACF;AAEA,SAAS,sBAAA,CACP,iBACA,OAAA,EACO;AACP,EAAA,MAAM,aAAA,GAAgB,QAAQ,eAAe,CAAA;AAE7C,EAAA,OAAO;AAAA,IACL,SAAA,EAAW;AAAA,MACT,MAAA,EAAQ;AAAA,QACN;AAAA,UACE,IAAA,EAAM,kBAAA;AAAA,UACN,KAAA,EAAO,mCAAmC,SAAS,CAAA,GAAA,CAAA;AAAA,UACnD,YAAY,EAAE,MAAA,EAAQ,kBAAA,CAAmB,aAAA,EAAe,MAAM,CAAA,EAAE;AAAA;AAAA,UAEhE,SAAA,EAAW,EAAE,IAAA,EAAM,KAAA,EAAM;AAAA,UACzB,SAAA,EAAW;AAAA;AACb;AACF,KACF;AAAA,IACA,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,CAAE,IAAI,CAAC,CAAC,QAAA,EAAU,WAAW,CAAA,KAAM;AAC/D,QAAA,MAAM,UAAU,QAAA,KAAa,eAAA;AAE7B,QAAA,MAAM,MAAA,GAAiB;AAAA,UACrB,EAAA,EAAI,QAAA;AAAA,UACJ,IAAA,EAAM,QAAA,KAAa,GAAA,GAAM,MAAA,GAAS,UAAU,QAAQ,CAAA,CAAA;AAAA,UACpD,OAAA;AAAA,UACA,OAAA,EAAS,IAAA;AAAA,UACT,MAAM,QAAA,KAAa;AAAA,SACrB;AAEA,QAAA,IAAI,CAAC,OAAA,EAAS;AACZ,UAAA,MAAA,CAAO,aAAa,EAAE,MAAA,EAAQ,kBAAA,CAAmB,WAAA,CAAY,MAAM,CAAA,EAAE;AAAA,QACvE;AAEA,QAAA,OAAO,MAAA;AAAA,MACT,CAAC;AAAA;AACH,GACF;AACF;AAEA,SAAS,iBAAA,CAAkB,OAAc,KAAA,EAAwB;AAC/D,EAAA,qBAAA,CAAsB,OAAO,KAAK,CAAA;AAElC,EAAA,IAAI,CAAC,KAAA,CAAM,QAAA,EAAU,KAAA,EAAO;AAC1B,IAAA,MAAM,EAAE,OAAA,EAAS,YAAA,EAAc,iBAAA,KAAsB,KAAA,CAAM,kBAAA;AAC3D,IAAA,KAAA,CAAM,QAAA,GAAW;AAAA,MACf,KAAA,EAAO;AAAA,QACL,QAAA,EAAU,OAAA;AAAA,QACV,OAAA,EAAS,qBAAqB,cAAA,EAAe;AAAA,QAC7C,cAAA,EAAgB;AAAA,OAClB;AAAA,MACA,GAAG,KAAA,CAAM;AAAA,KACX;AAAA,EACF;AACF;AAEA,eAAe,eAAe,eAAA,EAAwC;AACpE,EAAA,IAAI,eAAc,EAAG;AACnB,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,UAAU,iBAAA,EAA8C;AAC9D,EAAA,MAAM,aAAA,GAAgB,QAAQ,eAAe,CAAA;AAE7C,EAAA,IAAI,CAAC,aAAA,EAAe;AAClB,IAAA,GAAA,CAAI,CAAA,yBAAA,EAA4B,eAAe,CAAA,CAAA,CAAG,CAAA;AAClD,IAAA;AAAA,EACF;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,mBAAA,CAAoB,aAAA,CAAc,SAAA,EAAW,OAAO,CAAA;AAAA,EAC5D,SAAS,KAAA,EAAO;AACd,IAAA,GAAA,CAAI,CAAA,4CAAA,EAA+C,eAAe,CAAA,EAAA,CAAA,EAAM,KAAK,CAAA;AAAA,EAC/E;AAEA,EAAA,GAAA,CAAI,eAAe,CAAA;AAEnB,EAAA,MAAM,KAAA,GAAe;AAAA,IACnB,UAAU,KAAA,EAAM;AAAA,IAChB,QAAA;AAAA,IACA,OAAA;AAAA,IACA,WAAA;AAAA,IACA,IAAA;AAAA,IACA,QAAA,EAAU,MAAA;AAAA,IACV,KAAA,EAAO,OAAA;AAAA,IACP,IAAA;AAAA,IACA,GAAG,sBAAA,CAAuB,eAAA,EAAiB,OAAO;AAAA,GACpD;AAEA,EAAA,MAAM,QAAQ,aAAA,CAAc,SAAA,EAAW,KAAA,GACnC,IAAI,OAAM,CAAE,MAAA,CAAO,aAAA,CAAc,SAAA,CAAU,KAAK,CAAA,CAAE,YAAA,KAClD,IAAI,KAAA,GAAQ,YAAA,EAAa;AAE7B,EAAA,IAAI,aAAA,EAAe,YAAY,cAAA,EAAgB;AAE7C,IAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,MAAA,CAAO,IAAI,KAAA,IAAS,aAAA,CAAc,UAAA,CAAW,cAAc,CAAA,CAAE,YAAA,EAAa;AACxG,IAAA,cAAA,CAAe,OAAO,cAAc,CAAA;AAAA,EACtC;AACA,EAAA,iBAAA,CAAkB,OAAO,KAAK,CAAA;AAE9B,EAAA,MAAM,cAAA,GAAyC,OAAO,MAAA,CAAO,OAAO,EAAE,MAAA,CAAO,CAAC,KAAK,WAAA,KAAgB;AACjG,IAAA,OAAO,EAAE,GAAG,GAAA,EAAK,GAAG,WAAA,CAAY,WAAW,WAAA,EAAY;AAAA,EACzD,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,cAAA,CAAe,OAAO,cAAc,CAAA;AAEpC,EAAA,MAAM,QAAA,GAAW,mBAAA,CAAoB,KAAA,EAAO,GAAA,EAAK,aAAa,MAAM,CAAA;AAEpE,EAAA,GAAA,CAAI,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAC,CAAA;AAE5B,EAAA,MAAM,SAAA,CAAU,KAAK,QAAQ,CAAA;AAC7B,EAAA,MAAM,SAAA,CAAU,MAAM,GAAI,CAAA;AAC5B;AAEA,WAAA,CAAY,YAAY;AACtB,EAAA,KAAA,MAAW,CAAC,UAAU,IAAI,CAAA,IAAK,OAAO,OAAA,CAAQ,kBAAA,EAAoB,CAAA,EAAG;AACnE,IAAA,IAAI,OAAO,SAAA,EAAW;AACpB,MAAA,IAAI,gBAAA,CAAiB,GAAA,CAAI,QAAQ,CAAA,EAAG;AAClC,QAAA;AAAA,MACF;AAEA,MAAA,GAAA,CAAI,CAAA,yBAAA,EAA4B,QAAQ,CAAA,cAAA,EAAiB,IAAI,CAAA,QAAA,CAAU,CAAA;AACvE,MAAA,gBAAA,CAAiB,IAAI,QAAQ,CAAA;AAE7B,MAAA,IAAI;AACF,QAAA,MAAM,eAAe,QAAQ,CAAA;AAAA,MAC/B,SAAS,KAAA,EAAO;AACd,QAAA,GAAA,CAAI,CAAA,iCAAA,EAAoC,QAAQ,CAAA,EAAA,CAAA,EAAM,KAAK,CAAA;AAAA,MAC7D;AAAA,IACF,CAAA,MAAO;AACL,MAAA,gBAAA,CAAiB,OAAO,QAAQ,CAAA;AAAA,IAClC;AAAA,EACF;AACF,CAAA,EAAG,YAAY,CAAA"}
1
+ {"version":3,"file":"event-loop-block-watchdog.js","sources":["../../src/event-loop-block-watchdog.ts"],"sourcesContent":["import { workerData } from 'node:worker_threads';\nimport type { DebugImage, Event, ScopeData, Session, StackFrame, Thread } from '@sentry/core';\nimport {\n applyScopeDataToEvent,\n createEventEnvelope,\n createSessionEnvelope,\n filenameIsInApp,\n generateSpanId,\n getEnvelopeEndpointWithUrlEncodedAuth,\n makeSession,\n mergeScopeData,\n normalizeUrlToBase,\n Scope,\n stripSentryFramesAndReverse,\n updateSession,\n uuid4,\n} from '@sentry/core';\nimport { makeNodeTransport } from '@sentry/node';\nimport { captureStackTrace, getThreadsLastSeen } from '@sentry/node-native-stacktrace';\nimport type { ThreadState, WorkerStartData } from './common';\nimport { POLL_RATIO } from './common';\n\ntype CurrentScopes = {\n isolationScope: Scope;\n};\n\nconst {\n threshold,\n appRootPath,\n contexts,\n debug,\n dist,\n dsn,\n environment,\n maxEventsPerHour,\n release,\n sdkMetadata,\n staticTags: tags,\n tunnel,\n} = workerData as WorkerStartData;\n\nconst pollInterval = threshold / POLL_RATIO;\nconst triggeredThreads = new Set<string>();\n\nfunction log(...msg: unknown[]): void {\n if (debug) {\n // eslint-disable-next-line no-console\n console.log('[Sentry Event Loop Blocked Watchdog]', ...msg);\n }\n}\n\nfunction createRateLimiter(maxEventsPerHour: number): () => boolean {\n let currentHour = 0;\n let currentCount = 0;\n\n return function isRateLimited(): boolean {\n const hour = new Date().getHours();\n\n if (hour !== currentHour) {\n currentHour = hour;\n currentCount = 0;\n }\n\n if (currentCount >= maxEventsPerHour) {\n if (currentCount === maxEventsPerHour) {\n currentCount += 1;\n log(`Rate limit reached: ${currentCount} events in this hour`);\n }\n return true;\n }\n\n currentCount += 1;\n return false;\n };\n}\n\nconst url = getEnvelopeEndpointWithUrlEncodedAuth(dsn, tunnel, sdkMetadata.sdk);\nconst transport = makeNodeTransport({\n url,\n recordDroppedEvent: () => {\n //\n },\n});\nconst isRateLimited = createRateLimiter(maxEventsPerHour);\n\nasync function sendAbnormalSession(serializedSession: Session | undefined): Promise<void> {\n if (!serializedSession) {\n return;\n }\n\n log('Sending abnormal session');\n const session = makeSession(serializedSession);\n\n updateSession(session, {\n status: 'abnormal',\n abnormal_mechanism: 'anr_foreground',\n release,\n environment,\n });\n\n const envelope = createSessionEnvelope(session, dsn, sdkMetadata, tunnel);\n // Log the envelope so to aid in testing\n log(JSON.stringify(envelope));\n\n await transport.send(envelope);\n}\n\nlog('Started');\n\nfunction prepareStackFrames(stackFrames: StackFrame[] | undefined): StackFrame[] | undefined {\n if (!stackFrames) {\n return undefined;\n }\n\n // Strip Sentry frames and reverse the stack frames so they are in the correct order\n const strippedFrames = stripSentryFramesAndReverse(stackFrames);\n\n for (const frame of strippedFrames) {\n if (!frame.filename) {\n continue;\n }\n\n frame.in_app = filenameIsInApp(frame.filename);\n\n // If we have an app root path, rewrite the filenames to be relative to the app root\n if (appRootPath) {\n frame.filename = normalizeUrlToBase(frame.filename, appRootPath);\n }\n }\n\n return strippedFrames;\n}\n\nfunction stripFileProtocol(filename: string | undefined): string | undefined {\n if (!filename) {\n return undefined;\n }\n return filename.replace(/^file:\\/\\//, '');\n}\n\n// eslint-disable-next-line complexity\nfunction applyDebugMeta(event: Event, debugImages: Record<string, string>): void {\n if (Object.keys(debugImages).length === 0) {\n return;\n }\n\n const normalisedDebugImages = appRootPath ? {} : debugImages;\n if (appRootPath) {\n for (const [path, debugId] of Object.entries(debugImages)) {\n normalisedDebugImages[normalizeUrlToBase(path, appRootPath)] = debugId;\n }\n }\n\n const filenameToDebugId = new Map<string, string>();\n\n for (const exception of event.exception?.values || []) {\n for (const frame of exception.stacktrace?.frames || []) {\n const filename = stripFileProtocol(frame.abs_path || frame.filename);\n if (filename && normalisedDebugImages[filename]) {\n filenameToDebugId.set(filename, normalisedDebugImages[filename]);\n }\n }\n }\n\n for (const thread of event.threads?.values || []) {\n for (const frame of thread.stacktrace?.frames || []) {\n const filename = stripFileProtocol(frame.abs_path || frame.filename);\n if (filename && normalisedDebugImages[filename]) {\n filenameToDebugId.set(filename, normalisedDebugImages[filename]);\n }\n }\n }\n\n if (filenameToDebugId.size > 0) {\n const images: DebugImage[] = [];\n for (const [code_file, debug_id] of filenameToDebugId.entries()) {\n images.push({\n type: 'sourcemap',\n code_file,\n debug_id,\n });\n }\n event.debug_meta = { images };\n }\n}\n\nfunction getExceptionAndThreads(\n crashedThreadId: string,\n threads: ReturnType<typeof captureStackTrace<CurrentScopes, ThreadState>>,\n): Event {\n const crashedThread = threads[crashedThreadId];\n\n return {\n exception: {\n values: [\n {\n type: 'EventLoopBlocked',\n value: `Event Loop Blocked for at least ${threshold} ms`,\n stacktrace: { frames: prepareStackFrames(crashedThread?.frames) },\n // This ensures the UI doesn't say 'Crashed in' for the stack trace\n mechanism: { type: 'ANR' },\n thread_id: crashedThreadId,\n },\n ],\n },\n threads: {\n values: Object.entries(threads).map(([threadId, threadState]) => {\n const crashed = threadId === crashedThreadId;\n\n const thread: Thread = {\n id: threadId,\n name: threadId === '0' ? 'main' : `worker-${threadId}`,\n crashed,\n current: true,\n main: threadId === '0',\n };\n\n if (!crashed) {\n thread.stacktrace = { frames: prepareStackFrames(threadState.frames) };\n }\n\n return thread;\n }),\n },\n };\n}\n\n/**\n * Rehydrates a Scope from serialized ScopeData that has been passed over a JSON serialization boundary.\n *\n * `Scope.update()` only handles `ScopeContext` fields, so breadcrumbs have to be carried over separately.\n * Attachments are deliberately not carried over since their binary data does not survive JSON serialization.\n */\nfunction hydrateScope(data: Partial<ScopeData> | undefined): Scope {\n const scope = new Scope();\n if (data) {\n scope.update(data);\n data.breadcrumbs?.forEach(breadcrumb => scope.addBreadcrumb(breadcrumb));\n }\n return scope;\n}\n\nfunction applyScopeToEvent(event: Event, scope: ScopeData): void {\n applyScopeDataToEvent(event, scope);\n\n if (!event.contexts?.trace) {\n const { traceId, parentSpanId, propagationSpanId } = scope.propagationContext;\n event.contexts = {\n trace: {\n trace_id: traceId,\n span_id: propagationSpanId || generateSpanId(),\n parent_span_id: parentSpanId,\n },\n ...event.contexts,\n };\n }\n}\n\nasync function sendBlockEvent(crashedThreadId: string): Promise<void> {\n if (isRateLimited()) {\n return;\n }\n\n const threads = captureStackTrace<CurrentScopes, ThreadState>();\n const crashedThread = threads[crashedThreadId];\n\n if (!crashedThread) {\n log(`No thread found with ID '${crashedThreadId}'`);\n return;\n }\n\n try {\n await sendAbnormalSession(crashedThread.pollState?.session);\n } catch (error) {\n log(`Failed to send abnormal session for thread '${crashedThreadId}':`, error);\n }\n\n log('Sending event');\n\n const event: Event = {\n event_id: uuid4(),\n contexts,\n release,\n environment,\n dist,\n platform: 'node',\n level: 'error',\n tags,\n ...getExceptionAndThreads(crashedThreadId, threads),\n };\n\n const scope = hydrateScope(crashedThread.pollState?.scope).getScopeData();\n\n if (crashedThread?.asyncState?.isolationScope) {\n // We need to rehydrate the scope from the serialized object with properties beginning with _user, etc\n const isolationScope = Object.assign(new Scope(), crashedThread.asyncState.isolationScope).getScopeData();\n mergeScopeData(scope, isolationScope);\n }\n applyScopeToEvent(event, scope);\n\n const allDebugImages: Record<string, string> = Object.values(threads).reduce((acc, threadState) => {\n return { ...acc, ...threadState.pollState?.debugImages };\n }, {});\n\n applyDebugMeta(event, allDebugImages);\n\n const envelope = createEventEnvelope(event, dsn, sdkMetadata, tunnel);\n // Log the envelope to aid in testing\n log(JSON.stringify(envelope));\n\n await transport.send(envelope);\n await transport.flush(2000);\n}\n\nsetInterval(async () => {\n for (const [threadId, time] of Object.entries(getThreadsLastSeen())) {\n if (time > threshold) {\n if (triggeredThreads.has(threadId)) {\n continue;\n }\n\n log(`Blocked thread detected '${threadId}' last polled ${time} ms ago.`);\n triggeredThreads.add(threadId);\n\n try {\n await sendBlockEvent(threadId);\n } catch (error) {\n log(`Failed to send event for thread '${threadId}':`, error);\n }\n } else {\n triggeredThreads.delete(threadId);\n }\n }\n}, pollInterval);\n"],"names":["maxEventsPerHour","isRateLimited"],"mappings":"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"}
@@ -1 +1 @@
1
- {"type":"module","version":"10.65.0","sideEffects":false}
1
+ {"type":"module","version":"10.67.0","sideEffects":false}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/node-native",
3
- "version": "10.65.0",
3
+ "version": "10.67.0",
4
4
  "description": "Native Tools for the Official Sentry Node.js SDK",
5
5
  "repository": "git://github.com/getsentry/sentry-javascript.git",
6
6
  "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/node-native",
@@ -63,8 +63,8 @@
63
63
  },
64
64
  "dependencies": {
65
65
  "@sentry/node-native-stacktrace": "^0.5.1",
66
- "@sentry/core": "10.65.0",
67
- "@sentry/node": "10.65.0"
66
+ "@sentry/core": "10.67.0",
67
+ "@sentry/node": "10.67.0"
68
68
  },
69
69
  "devDependencies": {
70
70
  "@types/node": "^18.19.1"