hunk.code_window: }
   const otelSDK = initializeOtelSdk(packageJson.name);
   export async function bootstrap(): Promise<INestApplication> {
     await otelSDK.start();
     const app = await NestFactory.create(AppModule, { bufferLogs: true });
     app.useLogger(app.get(Logger));
     app.flushLogs();
  
hunk.labels: keep keep keep keep keep replace keep keep keep keep
hunk.after_edit:   if (process.env.ENABLE_OTEL_SDK === 'true') {
       await otelSDK.start();
     }
  
hunk.file_path: apps/webhook/src/bootstrap.ts
hunk.type: replace
file: import { CONTEXT_PATH } from './config';
  import 'newrelic';
  import '@sentry/tracing';
  
  import helmet from 'helmet';
  import { INestApplication, Logger, ValidationPipe } from '@nestjs/common';
  import * as passport from 'passport';
  import * as compression from 'compression';
  import { NestFactory, Reflector } from '@nestjs/core';
  import * as bodyParser from 'body-parser';
  import * as Sentry from '@sentry/node';
  import { BullMqService, getErrorInterceptor, Logger as PinoLogger, initializeOtelSdk } from '@novu/application-generic';
  import { ExpressAdapter } from '@nestjs/platform-express';
  
  import { AppModule } from './app.module';
  import { ResponseInterceptor } from './app/shared/framework/response.interceptor';
  import { RolesGuard } from './app/auth/framework/roles.guard';
  import { SubscriberRouteGuard } from './app/auth/framework/subscriber-route.guard';
  import { validateEnv } from './config/env-validator';
  
  import * as packageJson from '../package.json';
  import { setupSwagger } from './app/shared/framework/swagger/swagger.controller';
  import { HttpRequestHeaderKeysEnum } from './app/shared/framework/types';
  
  const extendedBodySizeRoutes = ['/v1/events', '/v1/notification-templates', '/v1/workflows', '/v1/layouts'];
  
  if (process.env.SENTRY_DSN) {
    Sentry.init({
      dsn: process.env.SENTRY_DSN,
      environment: process.env.NODE_ENV,
      release: `v${packageJson.version}`,
      ignoreErrors: ['Non-Error exception captured'],
      integrations: [
        // enable HTTP calls tracing
        new Sentry.Integrations.Http({ tracing: true }),
      ],
    });
  }
  
  // Validate the ENV variables after launching SENTRY, so missing variables will report to sentry
  validateEnv();
  const otelSDK = initializeOtelSdk(packageJson.name);
  
  export async function bootstrap(expressApp?): Promise<INestApplication> {
    BullMqService.haveProInstalled();
    await otelSDK.start();
  
    let app: INestApplication;
    if (expressApp) {
      app = await NestFactory.create(AppModule, new ExpressAdapter(expressApp));
    } else {
      app = await NestFactory.create(AppModule, { bufferLogs: true });
    }
  
    app.useLogger(app.get(PinoLogger));
    app.flushLogs();
  
    const server = app.getHttpServer();
    Logger.verbose(`Server timeout: ${server.timeout}`);
    server.keepAliveTimeout = 61 * 1000;
    Logger.verbose(`Server keepAliveTimeout: ${server.keepAliveTimeout / 1000}s `);
    server.headersTimeout = 65 * 1000;
    Logger.verbose(`Server headersTimeout: ${server.headersTimeout / 1000}s `);
  
    if (process.env.SENTRY_DSN) {
      app.use(Sentry.Handlers.requestHandler());
      app.use(Sentry.Handlers.tracingHandler());
    }
  
    app.use(helmet());
    app.enableCors(corsOptionsDelegate);
  
    app.setGlobalPrefix(CONTEXT_PATH + 'v1');
  
    app.use(passport.initialize());
  
    app.useGlobalPipes(
      new ValidationPipe({
        transform: true,
        forbidUnknownValues: false,
      })
    );
  
    app.useGlobalInterceptors(new ResponseInterceptor());
    app.useGlobalInterceptors(getErrorInterceptor());
  
    app.useGlobalGuards(new RolesGuard(app.get(Reflector)));
    app.useGlobalGuards(new SubscriberRouteGuard(app.get(Reflector)));
  
    app.use(extendedBodySizeRoutes, bodyParser.json({ limit: '20mb' }));
    app.use(extendedBodySizeRoutes, bodyParser.urlencoded({ limit: '20mb', extended: true }));
  
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));
  
    app.use(compression());
  
    setupSwagger(app);
  
    Logger.log('BOOTSTRAPPED SUCCESSFULLY');
  
    if (expressApp) {
      await app.init();
    } else {
      await app.listen(process.env.PORT);
    }
  
    app.enableShutdownHooks();
  
    Logger.log(`Started application in NODE_ENV=${process.env.NODE_ENV} on port ${process.env.PORT}`);
  
    return app;
  }
  
  const corsOptionsDelegate: Parameters<INestApplication['enableCors']>[0] = function (req, callback) {
    const corsOptions: Parameters<typeof callback>[1] = {
      origin: false as boolean | string | string[],
      preflightContinue: false,
      maxAge: 86400,
      allowedHeaders: Object.values(HttpRequestHeaderKeysEnum),
      methods: ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
    };
  
    if (['test', 'local'].includes(process.env.NODE_ENV) || isWidgetRoute(req.url) || isBlueprintRoute(req.url)) {
      corsOptions.origin = '*';
    } else {
      corsOptions.origin = [process.env.FRONT_BASE_URL];
      if (process.env.WIDGET_BASE_URL) {
        corsOptions.origin.push(process.env.WIDGET_BASE_URL);
      }
    }
    callback(null as unknown as Error, corsOptions);
  };
  
  function isWidgetRoute(url: string) {
    return url.startsWith('/v1/widgets');
  }
  
  function isBlueprintRoute(url: string) {
    return url.startsWith('/v1/blueprints');
  }
  
  process.on('SIGTERM', () => {
    otelSDK
      .shutdown()
      .then(
        () => console.log('SDK shut down successfully'),
        (err) => console.log('Error shutting down SDK', err)
      )
      .finally(() => process.exit(0));
  });
  