Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Sentry.init({
traceLifecycle: 'static',
dsn: 'https://public@dsn.ingest.sentry.io/1337',
release: '1.0',
integrations: [Sentry.childProcessIntegration({ captureWorkerErrors: false })],
integrations: [Sentry.childProcessIntegration(), Sentry.workerIntegration({ captureWorkerErrors: false })],
transport: loggingTransport,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const WORKER_EVENT: Event = {
type: 'Error',
value: 'Test error',
mechanism: {
type: 'auto.child_process.worker_thread',
type: 'auto.worker_thread',
handled: false,
data: {
threadId: expect.any(String),
Expand Down
1 change: 1 addition & 0 deletions packages/aws-serverless/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ export {
processSessionIntegration,
prismaIntegration,
childProcessIntegration,
workerIntegration,
createSentryWinstonTransport,
hapiIntegration,
setupHapiErrorHandler,
Expand Down
1 change: 1 addition & 0 deletions packages/google-cloud-serverless/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export {
anthropicAIIntegration,
googleGenAIIntegration,
childProcessIntegration,
workerIntegration,
createSentryWinstonTransport,
vercelAIIntegration,
logger,
Expand Down
1 change: 1 addition & 0 deletions packages/node/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ export { metrics, withStreamedSpan } from '@sentry/core';
export * as logger from './logs/exports';

export { childProcessIntegration } from './integrations/childProcess';
export { workerIntegration } from './integrations/workerIntegration';
Comment thread
cursor[bot] marked this conversation as resolved.
export { consoleIntegration } from './integrations/console';
export { nodeContextIntegration } from './integrations/context';
export { contextLinesIntegration } from './integrations/contextlines';
Expand Down
44 changes: 5 additions & 39 deletions packages/node/src/integrations/childProcess.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { ChildProcess } from 'node:child_process';
import * as diagnosticsChannel from 'node:diagnostics_channel';
import type { Worker } from 'node:worker_threads';
import { addBreadcrumb, captureException, defineIntegration, isObjectLike } from '@sentry/core';
import { addBreadcrumb, defineIntegration, isObjectLike } from '@sentry/core';

interface Options {
/**
Expand All @@ -10,19 +9,14 @@ interface Options {
* @default false
*/
includeChildProcessArgs?: boolean;

/**
* Whether to capture errors from worker threads.
*
Comment thread
cursor[bot] marked this conversation as resolved.
* @default true
*/
captureWorkerErrors?: boolean;
}

const INTEGRATION_NAME = 'ChildProcess' as const;
Comment thread
sentry[bot] marked this conversation as resolved.

/**
* Capture breadcrumbs and events for child processes and worker threads.
Comment thread
cursor[bot] marked this conversation as resolved.
* Capture breadcrumbs and events for child processes.
*
* For worker thread events, use `workerIntegration()` instead.
*/
export const childProcessIntegration = defineIntegration((options: Options = {}) => {
return {
Expand All @@ -33,12 +27,6 @@ export const childProcessIntegration = defineIntegration((options: Options = {})
captureChildProcessEvents(event.process as ChildProcess, options);
}
});

diagnosticsChannel.channel('worker_threads').subscribe((event: unknown) => {
if (isObjectLike(event) && 'worker' in event) {
captureWorkerThreadEvents(event.worker as Worker, options);
}
});
},
};
});
Expand Down Expand Up @@ -69,7 +57,7 @@ function captureChildProcessEvents(child: ChildProcess, options: Options): void
addBreadcrumb({
category: 'child_process',
message: `Child process exited with code '${code}'`,
level: code === 0 ? 'info' : 'warning',
level: 'warning',
data,
});
}
Expand All @@ -89,25 +77,3 @@ function captureChildProcessEvents(child: ChildProcess, options: Options): void
});
}

function captureWorkerThreadEvents(worker: Worker, options: Options): void {
let threadId: number | undefined;

worker
.on('online', () => {
threadId = worker.threadId;
})
.on('error', error => {
if (options.captureWorkerErrors !== false) {
captureException(error, {
mechanism: { type: 'auto.child_process.worker_thread', handled: false, data: { threadId: String(threadId) } },
});
} else {
addBreadcrumb({
category: 'worker_thread',
message: `Worker thread errored with '${error.message}'`,
level: 'error',
data: { threadId },
});
}
});
}
53 changes: 53 additions & 0 deletions packages/node/src/integrations/workerIntegration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import type { Worker } from 'node:worker_threads';
import * as diagnosticsChannel from 'node:diagnostics_channel';
import { addBreadcrumb, captureException, defineIntegration, isObjectLike } from '@sentry/core';

interface Options {
/**
* Whether to capture errors from worker threads.
*
* @default true
*/
Comment thread
atharv-sys32 marked this conversation as resolved.
captureWorkerErrors?: boolean;
}

const INTEGRATION_NAME = 'Worker' as const;

/**
* Capture breadcrumbs and events for worker threads.
*/
export const workerIntegration = defineIntegration((options: Options = {}) => {
return {
name: INTEGRATION_NAME,
setup() {
diagnosticsChannel.channel('worker_threads').subscribe((event: unknown) => {
if (isObjectLike(event) && 'worker' in event) {
captureWorkerThreadEvents(event.worker as Worker, options);
}
});
},
};
});
Comment thread
cursor[bot] marked this conversation as resolved.

function captureWorkerThreadEvents(worker: Worker, options: Options): void {
let threadId: number | undefined;

worker
.on('online', () => {
threadId = worker.threadId;
})
.on('error', error => {
if (options.captureWorkerErrors !== false) {
captureException(error, {
mechanism: { type: 'auto.worker_thread', handled: false, data: { threadId: threadId !== undefined ? String(threadId) : undefined } },
});
Comment thread
cursor[bot] marked this conversation as resolved.
} else {
Comment thread
sentry[bot] marked this conversation as resolved.
addBreadcrumb({
category: 'worker_thread',
message: `Worker thread errored with '${error.message}'`,
level: 'error',
data: { threadId },
});
}
});
}
Comment thread
cursor[bot] marked this conversation as resolved.
2 changes: 2 additions & 0 deletions packages/node/src/sdk/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { detectOrchestrionSetup } from '@sentry/server-utils/orchestrion';
import { registerDiagnosticsChannelInjection } from '@sentry/server-utils/orchestrion/register';
import { DEBUG_BUILD } from '../debug-build';
import { childProcessIntegration } from '../integrations/childProcess';
import { workerIntegration } from '../integrations/workerIntegration';
import { consoleIntegration } from '../integrations/console';
import { nodeContextIntegration } from '../integrations/context';
import { contextLinesIntegration } from '../integrations/contextlines';
Expand Down Expand Up @@ -68,6 +69,7 @@ function getBaseDefaultIntegrations(): Integration[] {
localVariablesIntegration(),
nodeContextIntegration(),
childProcessIntegration(),
workerIntegration(),
processSessionIntegration(),
modulesIntegration(),
];
Expand Down