getsentry / sentry-javascript

Official Sentry SDKs for JavaScript
https://sentry.io
MIT License
8.01k stars 1.58k forks source link

Unable to instrument Nestjs app when the Fastify Adapter is used #13388

Open samuelgoldenbaum opened 3 months ago

samuelgoldenbaum commented 3 months ago

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/nestjs

SDK Version

8.26.0

Framework Version

@nestjs/platform-fastify ^10.4.1

Link to Sentry event

No response

Reproduction Example/SDK Setup

The following will not instrument...

const initSentry = (): Promise<void> => {
  return new Promise((resolve) => {
    Sentry.init({
      dsn: 'DSN,
      integrations: [nodeProfilingIntegration()],
      tracesSampleRate: 1.0,
      profilesSampleRate: 1.0
    });
    return resolve();
  });
};

async function bootstrap() {
  const app = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter()
  );

  await app.listen(3000);
}

initSentry().then(() => bootstrap());

But using Express will

const initSentry = (): Promise<void> => {
  return new Promise((resolve) => {
    Sentry.init({
      dsn: 'DSN',
      integrations: [nodeProfilingIntegration()],
      tracesSampleRate: 1.0,
      profilesSampleRate: 1.0
    });
    return resolve();
  });
};

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  await app.listen(3000);
}

initSentry().then(() => bootstrap());

Steps to Reproduce

Swap to the Fastify adapter:

  const app = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter()
  );

  await app.listen(3000);

Expected Result

Should instrument and show data in Performance tab

Actual Result

No instrumentation

AbhiPrasad commented 3 months ago

@samuelgoldenbaum thanks for writing in.

Could you add debug: true to your Sentry.init and share the sentry logs for the fastify setup?

samuelgoldenbaum commented 3 months ago

@samuelgoldenbaum thanks for writing in.

Could you add debug: true to your Sentry.init and share the sentry logs for the fastify setup?

Logs:

Sentry Logger [log]: Initializing Sentry: process: 40771, thread: main.
Sentry Logger [log]: Integration installed: InboundFilters
Sentry Logger [log]: Integration installed: FunctionToString
Sentry Logger [log]: Integration installed: LinkedErrors
Sentry Logger [log]: Integration installed: RequestData
Sentry Logger [log]: Integration installed: Console
Sentry Logger [log]: Integration installed: Http
Sentry Logger [log]: Integration installed: NodeFetch
Sentry Logger [log]: Integration installed: OnUncaughtException
Sentry Logger [log]: Integration installed: OnUnhandledRejection
Sentry Logger [log]: Integration installed: ContextLines
Sentry Logger [log]: Integration installed: LocalVariablesAsync
Sentry Logger [log]: Integration installed: Context
Sentry Logger [log]: Integration installed: Modules
Sentry Logger [log]: Integration installed: Express
Sentry Logger [log]: Integration installed: Fastify
Sentry Logger [log]: Integration installed: Graphql
Sentry Logger [log]: Integration installed: Mongo
Sentry Logger [log]: Integration installed: Mongoose
Sentry Logger [log]: Integration installed: Mysql
Sentry Logger [log]: Integration installed: Mysql2
Sentry Logger [log]: Integration installed: Redis
Sentry Logger [log]: Integration installed: Postgres
Sentry Logger [log]: Integration installed: Nest
Sentry Logger [log]: Integration installed: Hapi
Sentry Logger [log]: Integration installed: Koa
Sentry Logger [log]: Integration installed: Connect
Sentry Logger [log]: [Profiling] Profiling integration setup.
Sentry Logger [log]: [Profiling] Span profiler mode enabled.
Sentry Logger [log]: Integration installed: ProfilingIntegration
Sentry Logger [log]: Running in CommonJS mode.
Sentry Logger [debug]: @opentelemetry/api: Registered a global for diag v1.9.0.
Sentry Logger [debug]: @opentelemetry/api: Registered a global for trace v1.9.0.
Sentry Logger [debug]: @opentelemetry/api: Registered a global for context v1.9.0.
Sentry Logger [debug]: @opentelemetry/api: Registered a global for propagation v1.9.0.
[Nest] 40771  - 08/18/2024, 12:05:51 PM     LOG [NestFactory] Starting Nest application...
[Nest] 40771  - 08/18/2024, 12:05:51 PM     LOG [InstanceLoader] SentryModule dependencies initialized +6ms
[Nest] 40771  - 08/18/2024, 12:05:51 PM     LOG [InstanceLoader] AppModule dependencies initialized +1ms
[Nest] 40771  - 08/18/2024, 12:05:51 PM     LOG [RoutesResolver] AppController {/}: +1ms
[Nest] 40771  - 08/18/2024, 12:05:51 PM     LOG [RouterExplorer] Mapped {/, GET} route +2ms
[Nest] 40771  - 08/18/2024, 12:05:51 PM     LOG [RouterExplorer] Mapped {/debug-sentry, GET} route +0ms
[Nest] 40771  - 08/18/2024, 12:05:51 PM     LOG [NestApplication] Nest application successfully started +1ms
Sentry Logger [log]: Flushing client reports based on interval.
Sentry Logger [log]: Flushing outcomes...
Sentry Logger [log]: No outcomes to send
Sentry Logger [log]: Flushing client reports based on interval.
Sentry Logger [log]: Flushing outcomes...
Sentry Logger [log]: No outcomes to send

Implementation:

import 'dotenv/config'; // needed as we init Sentry before bootstrapping Nest
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

import * as Sentry from '@sentry/nestjs';
import { nodeProfilingIntegration } from '@sentry/profiling-node';
import {
  FastifyAdapter,
  NestFastifyApplication
} from '@nestjs/platform-fastify';

const initSentry = (): Promise<void> => {
  return new Promise((resolve) => {
    Sentry.init({
      dsn: process.env.SENTRY_DSN,
      integrations: [nodeProfilingIntegration()],
      tracesSampleRate: 1.0,
      profilesSampleRate: 1.0,
      debug: true
    });
    return resolve();
  });
};

async function bootstrap() {
  const app = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter()
  );

  await app.listen(3000);
}

initSentry().then(() => bootstrap());

package.json:

  "dependencies": {
    "@nestjs/common": "^10.0.0",
    "@nestjs/config": "^3.2.3",
    "@nestjs/core": "^10.0.0",
    "@nestjs/microservices": "^10.4.1",
    "@nestjs/platform-express": "^10.0.0",
    "@nestjs/platform-fastify": "^10.4.1",
    "@sentry/cli": "^2.33.1",
    "@sentry/nestjs": "^8.26.0",
    "@sentry/profiling-node": "^8.26.0",
    "reflect-metadata": "^0.2.0",
    "rxjs": "^7.8.1"
  }
Lms24 commented 3 months ago

Hey @samuelgoldenbaum thanks for writing in!

We'll look into your issue next week as this week is Hackweek at Sentry (see #13421).

lforst commented 2 months ago

@samuelgoldenbaum can you try set up the SDK like it is recommended here: https://docs.sentry.io/platforms/javascript/guides/fastify/#configure

It might be the case that Sentry.init() is running too late and isn't able to patch the fastify imports. Thanks!

ctjhoa commented 1 month ago

Looks like I manage to make it work like this

  import * as Sentry from '@sentry/node';

  async function bootstrap() {
    const fastifyAdapter = new FastifyAdapter();
    Sentry.setupFastifyErrorHandler(fastifyAdapter.getInstance());
    const app = await NestFactory.create<NestFastifyApplication>(AppModule, fastifyAdapter);
  }