Skip to content

Commit

Permalink
Upgrade sentry (#7145)
Browse files Browse the repository at this point in the history
Upgrave Sentry to v8 and add Sentry Cron monitoring

---------

Co-authored-by: Charles Bochet <[email protected]>
  • Loading branch information
FelixMalfait and charlesBochet authored Sep 19, 2024
1 parent b3ed6cb commit 3025ac3
Show file tree
Hide file tree
Showing 22 changed files with 883 additions and 214 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ storybook-static
.eslintcache
.nyc_output
test-results/

dump.rdb
7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,9 @@
"@ptc-org/nestjs-query-typeorm": "4.2.1-alpha.2",
"@react-email/components": "0.0.12",
"@react-email/render": "0.0.10",
"@sentry/node": "^7.99.0",
"@sentry/profiling-node": "^1.3.4",
"@sentry/react": "^7.88.0",
"@sentry/tracing": "^7.99.0",
"@sentry/node": "^8",
"@sentry/profiling-node": "^8",
"@sentry/react": "^8",
"@sniptt/guards": "^0.2.0",
"@stoplight/elements": "^8.0.5",
"@swc/jest": "^0.2.29",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SentryInitEffect } from '@/error-handler/components/SentryInitiEffect';
import { SentryInitEffect } from '@/error-handler/components/SentryInitEffect';

export const ExceptionHandlerProvider: React.FC<React.PropsWithChildren> = ({
children,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useEffect, useState } from 'react';
import * as Sentry from '@sentry/react';
import { isNonEmptyString } from '@sniptt/guards';
import { useEffect, useState } from 'react';
import { useRecoilValue } from 'recoil';

import { currentUserState } from '@/auth/states/currentUserState';
Expand All @@ -26,14 +26,10 @@ export const SentryInitEffect = () => {
release: sentryConfig?.release ?? undefined,
dsn: sentryConfig?.dsn,
integrations: [
new Sentry.BrowserTracing({
tracePropagationTargets: [
'localhost:3001',
REACT_APP_SERVER_BASE_URL,
],
}),
new Sentry.Replay(),
Sentry.browserTracingIntegration({}),
Sentry.replayIntegration(),
],
tracePropagationTargets: ['localhost:3001', REACT_APP_SERVER_BASE_URL],
tracesSampleRate: 1.0,
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import * as Sentry from '@sentry/node';

export function SentryCronMonitor(monitorSlug: string, schedule: string) {
return function (
target: any,
propertyKey: string,
descriptor: PropertyDescriptor,
) {
if (!Sentry.isInitialized()) {
return descriptor;
}

const originalMethod = descriptor.value;

descriptor.value = async function (...args: any[]) {
try {
Sentry.captureCheckIn(
{
monitorSlug,
status: 'in_progress',
},
{
schedule: {
type: 'crontab',
value: schedule,
},
checkinMargin: 1,
maxRuntime: 1,
timezone: 'UTC',
},
);
const result = await originalMethod.apply(this, args);

Sentry.captureCheckIn({
monitorSlug,
status: 'ok',
});

return result;
} catch (error) {
Sentry.captureCheckIn({
monitorSlug,
status: 'error',
});
throw error;
}
};

return descriptor;
};
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import * as Sentry from '@sentry/node';
import { ProfilingIntegration } from '@sentry/profiling-node';
import { nodeProfilingIntegration } from '@sentry/profiling-node';

import { ExceptionHandlerUser } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-user.interface';
import { ExceptionHandlerOptions } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-options.interface';
import { ExceptionHandlerUser } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-user.interface';

import {
ExceptionHandlerDriverInterface,
ExceptionHandlerSentryDriverFactoryOptions,
} from 'src/engine/core-modules/exception-handler/interfaces';
import { WorkspaceCacheKeys } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';

export class ExceptionHandlerSentryDriver
implements ExceptionHandlerDriverInterface
Expand All @@ -18,11 +19,17 @@ export class ExceptionHandlerSentryDriver
release: options.release,
dsn: options.dsn,
integrations: [
new Sentry.Integrations.Http({ tracing: true }),
new Sentry.Integrations.Express({ app: options.serverInstance }),
new Sentry.Integrations.GraphQL(),
new Sentry.Integrations.Postgres(),
new ProfilingIntegration(),
// TODO: Redis integration doesn't seem to work - investigate why
Sentry.redisIntegration({
cachePrefixes: Object.values(WorkspaceCacheKeys).map(
(key) => `engine:${key}:`,
),
}),
Sentry.httpIntegration(),
Sentry.expressIntegration(),
Sentry.graphqlIntegration(),
Sentry.postgresIntegration(),
nodeProfilingIntegration(),
],
tracesSampleRate: 0.1,
profilesSampleRate: 0.3,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ export class CacheManager<T> {
const [workspaceId] = cacheKey.split('-');

if (this.cache.has(cacheKey)) {
console.log('Cache hit for key:', cacheKey);

return this.cache.get(cacheKey)!;
}

Expand All @@ -25,7 +23,6 @@ export class CacheManager<T> {
}
}

console.log('Cache miss for key:', cacheKey);
const value = await factory();

if (!value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { CacheStorageService } from 'src/engine/core-modules/cache-storage/servi
import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum';
import { ObjectMetadataMap } from 'src/engine/metadata-modules/utils/generate-object-metadata-map.util';

enum WorkspaceCacheKeys {
export enum WorkspaceCacheKeys {
GraphQLTypeDefs = 'graphql:type-defs',
GraphQLUsedScalarNames = 'graphql:used-scalar-names',
GraphQLOperations = 'graphql:operations',
Expand Down
6 changes: 2 additions & 4 deletions packages/twenty-server/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';

import * as Sentry from '@sentry/node';
import '@sentry/tracing';
import bytes from 'bytes';
import { useContainer } from 'class-validator';
import { graphqlUploadExpress } from 'graphql-upload';

import { ApplyCorsToExceptions } from 'src/utils/apply-cors-to-exceptions';
import { LoggerService } from 'src/engine/core-modules/logger/logger.service';
import { ApplyCorsToExceptions } from 'src/utils/apply-cors-to-exceptions';

import { AppModule } from './app.module';

Expand All @@ -36,8 +35,7 @@ const bootstrap = async () => {
app.useLogger(logger);

if (Sentry.isInitialized()) {
app.use(Sentry.Handlers.requestHandler());
app.use(Sentry.Handlers.tracingHandler());
Sentry.setupExpressErrorHandler(app);
}

app.useGlobalFilters(new ApplyCorsToExceptions());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { Command, CommandRunner } from 'nest-commander';
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
import { CalendarEventListFetchCronJob } from 'src/modules/calendar/calendar-event-import-manager/crons/jobs/calendar-event-list-fetch.cron.job';

const CALENDAR_EVENTS_IMPORT_CRON_PATTERN = '*/5 * * * *';
import {
CALENDAR_EVENTS_IMPORT_CRON_PATTERN,
CalendarEventListFetchCronJob,
} from 'src/modules/calendar/calendar-event-import-manager/crons/jobs/calendar-event-list-fetch.cron.job';

@Command({
name: 'cron:calendar:calendar-event-list-fetch',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { Command, CommandRunner } from 'nest-commander';
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
import { CalendarOngoingStaleCronJob } from 'src/modules/calendar/calendar-event-import-manager/crons/jobs/calendar-ongoing-stale.cron.job';

const CALENDAR_ONGOING_STALE_CRON_PATTERN = '0 * * * *';
import {
CALENDAR_ONGOING_STALE_CRON_PATTERN,
CalendarOngoingStaleCronJob,
} from 'src/modules/calendar/calendar-event-import-manager/crons/jobs/calendar-ongoing-stale.cron.job';

@Command({
name: 'cron:calendar:ongoing-stale',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,26 @@ import { InjectRepository } from '@nestjs/typeorm';

import { Any, Repository } from 'typeorm';

import {
Workspace,
WorkspaceActivationStatus,
} from 'src/engine/core-modules/workspace/workspace.entity';
import { SentryCronMonitor } from 'src/engine/core-modules/cron/sentry-cron-monitor.decorator';
import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service';
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator';
import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator';
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
import {
Workspace,
WorkspaceActivationStatus,
} from 'src/engine/core-modules/workspace/workspace.entity';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import {
CalendarEventListFetchJob,
CalendarEventsImportJobData,
} from 'src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job';
import { CalendarChannelSyncStage } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';

export const CALENDAR_EVENTS_IMPORT_CRON_PATTERN = '*/5 * * * *';

@Processor({
queueName: MessageQueue.cronQueue,
})
Expand All @@ -33,6 +36,10 @@ export class CalendarEventListFetchCronJob {
) {}

@Process(CalendarEventListFetchCronJob.name)
@SentryCronMonitor(
CalendarEventListFetchCronJob.name,
CALENDAR_EVENTS_IMPORT_CRON_PATTERN,
)
async handle(): Promise<void> {
console.time('CalendarEventListFetchCronJob time');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,24 @@ import { InjectRepository } from '@nestjs/typeorm';

import { Repository } from 'typeorm';

import {
Workspace,
WorkspaceActivationStatus,
} from 'src/engine/core-modules/workspace/workspace.entity';
import { SentryCronMonitor } from 'src/engine/core-modules/cron/sentry-cron-monitor.decorator';
import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service';
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator';
import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator';
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
import {
Workspace,
WorkspaceActivationStatus,
} from 'src/engine/core-modules/workspace/workspace.entity';
import {
CalendarOngoingStaleJob,
CalendarOngoingStaleJobData,
} from 'src/modules/calendar/calendar-event-import-manager/jobs/calendar-ongoing-stale.job';

export const CALENDAR_ONGOING_STALE_CRON_PATTERN = '0 * * * *';

@Processor(MessageQueue.cronQueue)
export class CalendarOngoingStaleCronJob {
constructor(
Expand All @@ -28,6 +31,10 @@ export class CalendarOngoingStaleCronJob {
) {}

@Process(CalendarOngoingStaleCronJob.name)
@SentryCronMonitor(
CalendarOngoingStaleCronJob.name,
CALENDAR_ONGOING_STALE_CRON_PATTERN,
)
async handle(): Promise<void> {
const activeWorkspaces = await this.workspaceRepository.find({
where: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { Command, CommandRunner } from 'nest-commander';
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
import { MessagingMessageListFetchCronJob } from 'src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job';

const MESSAGING_MESSAGE_LIST_FETCH_CRON_PATTERN = '*/5 * * * *';
import {
MESSAGING_MESSAGE_LIST_FETCH_CRON_PATTERN,
MessagingMessageListFetchCronJob,
} from 'src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job';

@Command({
name: 'cron:messaging:message-list-fetch',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { Command, CommandRunner } from 'nest-commander';
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
import { MessagingMessagesImportCronJob } from 'src/modules/messaging/message-import-manager/crons/jobs/messaging-messages-import.cron.job';

const MESSAGING_MESSAGES_IMPORT_CRON_PATTERN = '*/1 * * * *';
import {
MESSAGING_MESSAGES_IMPORT_CRON_PATTERN,
MessagingMessagesImportCronJob,
} from 'src/modules/messaging/message-import-manager/crons/jobs/messaging-messages-import.cron.job';

@Command({
name: 'cron:messaging:messages-import',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { Command, CommandRunner } from 'nest-commander';
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
import { MessagingOngoingStaleCronJob } from 'src/modules/messaging/message-import-manager/crons/jobs/messaging-ongoing-stale.cron.job';

const MESSAGING_ONGOING_STALE_CRON_PATTERN = '0 * * * *';
import {
MESSAGING_ONGOING_STALE_CRON_PATTERN,
MessagingOngoingStaleCronJob,
} from 'src/modules/messaging/message-import-manager/crons/jobs/messaging-ongoing-stale.cron.job';

@Command({
name: 'cron:messaging:ongoing-stale',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ import { InjectRepository } from '@nestjs/typeorm';

import { In, Repository } from 'typeorm';

import {
Workspace,
WorkspaceActivationStatus,
} from 'src/engine/core-modules/workspace/workspace.entity';
import { SentryCronMonitor } from 'src/engine/core-modules/cron/sentry-cron-monitor.decorator';
import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service';
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator';
import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator';
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
import {
Workspace,
WorkspaceActivationStatus,
} from 'src/engine/core-modules/workspace/workspace.entity';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import {
MessageChannelSyncStage,
Expand All @@ -22,6 +23,8 @@ import {
MessagingMessageListFetchJobData,
} from 'src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job';

export const MESSAGING_MESSAGE_LIST_FETCH_CRON_PATTERN = '*/5 * * * *';

@Processor(MessageQueue.cronQueue)
export class MessagingMessageListFetchCronJob {
constructor(
Expand All @@ -34,6 +37,10 @@ export class MessagingMessageListFetchCronJob {
) {}

@Process(MessagingMessageListFetchCronJob.name)
@SentryCronMonitor(
MessagingMessageListFetchCronJob.name,
MESSAGING_MESSAGE_LIST_FETCH_CRON_PATTERN,
)
async handle(): Promise<void> {
console.time('MessagingMessageListFetchCronJob time');

Expand Down
Loading

0 comments on commit 3025ac3

Please sign in to comment.