revert: Sentry #20064 + @sentry 10.27 (prod bisect) (#20221)

## Summary

Reverts **#20064** (`feat(sentry): propagate workspace context to all
spans`) and downgrades **@sentry** packages from **10.51** back to
**10.27** (reversing **#20149**), to validate in production whether
recent Sentry/instrumentation changes correlate with OTLP/metrics
issues.

## Changes

1. **Revert #20064** — removes `beforeSendSpan` from `instrument.ts`,
restores `WorkspaceAuthContextMiddleware` / `BullMQDriver` behavior, and
deletes the three `apply-workspace-sentry-*` utils added in that PR.
2. **Sentry versions** — `packages/twenty-server` (`@sentry/nestjs`,
`@sentry/node`, `@sentry/profiling-node`) and `packages/twenty-front`
(`@sentry/react`) set to `^10.27.0`; `yarn.lock` regenerated via `yarn
install`.

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Charles Bochet
2026-05-04 11:09:48 +02:00
committed by GitHub
parent 74cc2b4c87
commit ff22988caf
9 changed files with 29 additions and 138 deletions
@@ -13,7 +13,6 @@ import { buildApiKeyAuthContext } from 'src/engine/core-modules/auth/utils/build
import { buildApplicationAuthContext } from 'src/engine/core-modules/auth/utils/build-application-auth-context.util';
import { buildPendingActivationUserAuthContext } from 'src/engine/core-modules/auth/utils/build-pending-activation-user-auth-context.util';
import { buildUserAuthContext } from 'src/engine/core-modules/auth/utils/build-user-auth-context.util';
import { applyWorkspaceSentryContext } from 'src/engine/core-modules/sentry/utils/apply-workspace-sentry-context.util';
@Injectable()
export class WorkspaceAuthContextMiddleware implements NestMiddleware {
@@ -26,8 +25,6 @@ export class WorkspaceAuthContextMiddleware implements NestMiddleware {
const authContext = this.buildAuthContext(req);
applyWorkspaceSentryContext(authContext);
withWorkspaceAuthContext(authContext, () => {
next();
});
@@ -4,7 +4,6 @@ import {
type OnModuleInit,
} from '@nestjs/common';
import * as Sentry from '@sentry/node';
import {
type JobsOptions,
MetricsTime,
@@ -29,7 +28,6 @@ import { type MessageQueue } from 'src/engine/core-modules/message-queue/message
import { getJobKey } from 'src/engine/core-modules/message-queue/utils/get-job-key.util';
import { type MetricsService } from 'src/engine/core-modules/metrics/metrics.service';
import { MetricsKeys } from 'src/engine/core-modules/metrics/types/metrics-keys.type';
import { applyWorkspaceSentryContextFromJobData } from 'src/engine/core-modules/sentry/utils/apply-workspace-sentry-context-from-job-data.util';
export type BullMQDriverOptions = QueueOptions;
@@ -110,28 +108,25 @@ export class BullMQDriver
this.workerMap[queueName] = new Worker(
queueName,
async (job) =>
Sentry.withIsolationScope(async () => {
applyWorkspaceSentryContextFromJobData(job.data);
async (job) => {
// TODO: Correctly support for job.id
const timeStart = performance.now();
const workspaceId = job.data?.workspaceId;
const workspaceSuffix = workspaceId
? ` [workspace=${workspaceId}]`
: '';
// TODO: Correctly support for job.id
const timeStart = performance.now();
const workspaceId = job.data?.workspaceId;
const workspaceSuffix = workspaceId
? ` [workspace=${workspaceId}]`
: '';
this.logger.log(
`Processing job ${job.id} with name ${job.name} on queue ${queueName}${workspaceSuffix}`,
);
await handler({ data: job.data, id: job.id ?? '', name: job.name });
const timeEnd = performance.now();
const executionTime = timeEnd - timeStart;
this.logger.log(
`Processing job ${job.id} with name ${job.name} on queue ${queueName}${workspaceSuffix}`,
);
await handler({ data: job.data, id: job.id ?? '', name: job.name });
const timeEnd = performance.now();
const executionTime = timeEnd - timeStart;
this.logger.log(
`Job ${job.id} with name ${job.name} processed on queue ${queueName} in ${executionTime.toFixed(2)}ms${workspaceSuffix}`,
);
}),
this.logger.log(
`Job ${job.id} with name ${job.name} processed on queue ${queueName} in ${executionTime.toFixed(2)}ms${workspaceSuffix}`,
);
},
workerOptions,
);
@@ -1,25 +0,0 @@
import { applyWorkspaceSentryFields } from 'src/engine/core-modules/sentry/utils/apply-workspace-sentry-fields.util';
export const applyWorkspaceSentryContextFromJobData = (
jobData: unknown,
): void => {
if (typeof jobData !== 'object' || jobData === null) {
return;
}
const workspaceId = (jobData as { workspaceId?: unknown }).workspaceId;
const userWorkspaceId = (jobData as { userWorkspaceId?: unknown })
.userWorkspaceId;
if (typeof workspaceId !== 'string' || workspaceId.length === 0) {
return;
}
applyWorkspaceSentryFields({
workspaceId,
userWorkspaceId:
typeof userWorkspaceId === 'string' && userWorkspaceId.length > 0
? userWorkspaceId
: undefined,
});
};
@@ -1,27 +0,0 @@
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
import { applyWorkspaceSentryFields } from 'src/engine/core-modules/sentry/utils/apply-workspace-sentry-fields.util';
export const applyWorkspaceSentryContext = (
authContext: WorkspaceAuthContext,
): void => {
const workspaceId = authContext.workspace?.id;
if (!workspaceId) {
return;
}
switch (authContext.type) {
case 'user':
case 'pendingActivationUser':
applyWorkspaceSentryFields({
workspaceId,
userWorkspaceId: authContext.userWorkspaceId,
});
return;
case 'apiKey':
case 'application':
case 'system':
applyWorkspaceSentryFields({ workspaceId });
return;
}
};
@@ -1,26 +0,0 @@
import * as Sentry from '@sentry/node';
type WorkspaceSentryFields = {
workspaceId: string;
userWorkspaceId?: string;
};
export const applyWorkspaceSentryFields = (
fields: WorkspaceSentryFields,
): void => {
Sentry.setUser({
id: fields.userWorkspaceId ?? fields.workspaceId,
});
Sentry.setTag('twenty.workspace.id', fields.workspaceId);
if (fields.userWorkspaceId) {
Sentry.setTag('twenty.user_workspace.id', fields.userWorkspaceId);
}
Sentry.setContext('twenty', {
workspace_id: fields.workspaceId,
...(fields.userWorkspaceId && {
user_workspace_id: fields.userWorkspaceId,
}),
});
};