getsentry / profiling-node

The code for this repo now lives in https://github.com/getsentry/sentry-javascript/tree/develop/packages/profiling-node
MIT License
29 stars 10 forks source link

TypeError: profiling_node_1.ProfilingIntegration is not a constructor #199

Closed DominicGBauer closed 8 months ago

DominicGBauer commented 1 year ago

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

SDK Version

1.2.1

Link to Sentry event

No response

What environment is your node script running in?

Koa node backend Node 16.20

How is your code deployed and bundled?

Webpack 5 webpackfile.js:

const path = require('path');
const webpack = require('webpack');
const CopyPlugin = require('copy-webpack-plugin');
const { sentryWebpackPlugin } = require("@sentry/webpack-plugin");

module.exports = {
  context: __dirname,
  entry: ['./js/app.js'],
  output: {
    path: path.join(__dirname, './', 'build'),
    filename: 'app.js',
    libraryTarget: 'commonjs2',
  },
  target: 'node',
  externals: {
    vertx: 'vertx',
    consolidate: 'commonjs consolidate',
    'aws-sdk': 'aws-sdk',
    '@sparticuz/chromium': '@sparticuz/chromium',
  },
  mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
  optimization: {
    minimize: false,
  },
  node: {
    __dirname: false,
  },
  module: {
    rules: [
      {
        test: /\.node$/,
        loader: "node-loader",
      },
    ],
  },
  plugins: [
    new webpack.DefinePlugin({ 'global.GENTLY': false }),
    new webpack.ProvidePlugin({
      saslprep: 'saslprep',
    }),
    new CopyPlugin({
      patterns: [
        {
          from: 'src/**/*.hbs',
          to: './',
        },
      ],
    }),
    sentryWebpackPlugin({
      authToken: process.env.SENTRY_AUTH_TOKEN,
      org: "layup",
      project: "api"
    })
  ],
  devtool: "source-map"
};

Steps to Reproduce

webpack-cli -c webpackfile.js && node -r dotenv/config build/app.js

Expected Result

No error

Actual Result

TypeError: profiling_node_1.ProfilingIntegration is not a constructor

Webpack out for profiling:

var ProfilingIntegration = class {
  constructor() {
    this.name = "ProfilingIntegration";
    this.getCurrentHub = void 0;
  }
  setupOnce(addGlobalEventProcessor, getCurrentHub2) {
    this.getCurrentHub = getCurrentHub2;
    const client = this.getCurrentHub().getClient();
    if (client && typeof client.on === "function") {
      client.on("startTransaction", (transaction) => {
        const profile_id = maybeProfileTransaction(client, transaction, void 0);
        if (profile_id) {
          const options = client.getOptions();
          const maxProfileDurationMs = options._experiments && options._experiments["maxProfileDurationMs"] || MAX_PROFILE_DURATION_MS;
          if (PROFILE_TIMEOUTS[profile_id]) {
            global.clearTimeout(PROFILE_TIMEOUTS[profile_id]);
            delete PROFILE_TIMEOUTS[profile_id];
          }
          PROFILE_TIMEOUTS[profile_id] = global.setTimeout(() => {
            if (isDebugBuild()) {
              import_utils5.logger.log("[Profiling] max profile duration elapsed, stopping profiling for:", transaction.name);
            }
            const profile = stopTransactionProfile(transaction, profile_id);
            if (profile) {
              addToProfileQueue(profile);
            }
          }, maxProfileDurationMs);
          transaction.setContext("profile", { profile_id });
          transaction.setMetadata({ profile_id });
        }
      });
      client.on("finishTransaction", (transaction) => {
        const profile_id = transaction && transaction.metadata && transaction.metadata.profile_id;
        if (profile_id) {
          if (PROFILE_TIMEOUTS[profile_id]) {
            global.clearTimeout(PROFILE_TIMEOUTS[profile_id]);
            delete PROFILE_TIMEOUTS[profile_id];
          }
          const profile = stopTransactionProfile(transaction, profile_id);
          if (profile) {
            addToProfileQueue(profile);
          }
        }
      });
      client.on("beforeEnvelope", (envelope) => {
        var _a, _b, _c;
        if (!PROFILE_QUEUE.length) {
          return;
        }
        const profiledTransactionEvents = findProfiledTransactionsFromEnvelope(envelope);
        if (!profiledTransactionEvents.length) {
          return;
        }
        const profilesToAddToEnvelope = [];
        for (let i = 0; i < profiledTransactionEvents.length; i++) {
          const profiledTransaction = profiledTransactionEvents[i];
          const profile_id = (_b = (_a = profiledTransaction == null ? void 0 : profiledTransaction.contexts) == null ? void 0 : _a["profile"]) == null ? void 0 : _b["profile_id"];
          if (!profile_id) {
            throw new TypeError("[Profiling] cannot find profile for a transaction without a profile context");
          }
          if ((_c = profiledTransaction == null ? void 0 : profiledTransaction.contexts) == null ? void 0 : _c[".profile"]) {
            delete profiledTransaction.contexts["profile"];
          }
          const profileIndex = PROFILE_QUEUE.findIndex((p) => p.profile_id === profile_id);
          if (profileIndex === -1) {
            if (isDebugBuild()) {
              import_utils5.logger.log(`[Profiling] Could not retrieve profile for transaction: ${profile_id}`);
            }
            continue;
          }
          const cpuProfile = PROFILE_QUEUE[profileIndex];
          if (!cpuProfile) {
            if (isDebugBuild()) {
              import_utils5.logger.log(`[Profiling] Could not retrieve profile for transaction: ${profile_id}`);
            }
            continue;
          }
          PROFILE_QUEUE.splice(profileIndex, 1);
          const profile = createProfilingEvent(cpuProfile, profiledTransaction);
          if (profile) {
            profilesToAddToEnvelope.push(profile);
          }
        }
        addProfilesToEnvelope(envelope, profilesToAddToEnvelope);
      });
    } else {
      addProfilingExtensionMethods();
      addGlobalEventProcessor(this.handleGlobalEvent.bind(this));
    }
  }
  handleGlobalEvent(event) {
    if (this.getCurrentHub === void 0) {
      return maybeRemoveProfileFromSdkMetadata(event);
    }
    if (isProfiledTransactionEvent(event)) {
      const hub = this.getCurrentHub();
      const client = hub.getClient();
      if (!client) {
        if (isDebugBuild()) {
          import_utils5.logger.log(
            "[Profiling] getClient did not return a Client, removing profile from event and forwarding to next event processors."
          );
        }
        return maybeRemoveProfileFromSdkMetadata(event);
      }
      const dsn = client.getDsn();
      if (!dsn) {
        if (isDebugBuild()) {
          import_utils5.logger.log(
            "[Profiling] getDsn did not return a Dsn, removing profile from event and forwarding to next event processors."
          );
        }
        return maybeRemoveProfileFromSdkMetadata(event);
      }
      const transport = client.getTransport();
      if (!transport) {
        if (isDebugBuild()) {
          import_utils5.logger.log(
            "[Profiling] getTransport did not return a Transport, removing profile from event and forwarding to next event processors."
          );
        }
        return maybeRemoveProfileFromSdkMetadata(event);
      }
      if (isDebugBuild()) {
        import_utils5.logger.log("[Profiling] Preparing envelope and sending a profiling event");
      }
      const envelope = createProfilingEventEnvelope(event, dsn);
      if (envelope) {
        transport.send(envelope);
      }
    }
    return maybeRemoveProfileFromSdkMetadata(event);
  }
};
drobati commented 10 months ago

I'm getting a similar error

TypeError: ProfilingIntegration is not a function

I'm using node 20, with no source map.

Following the default example on sentry.io just didn't work. Going to roll the profiling-node package back to an earlier version and see if I can get it to work.

JonasBa commented 10 months ago

@drobat how are you importing the module? Mind logging what the value of the module?

drobati commented 10 months ago

@JonasBa https://github.com/drobati/alia-bot On this project I ran the onboarding guide at sentry.io

npm install --save @sentry/node @sentry/profiling-node

Because they use mjs imports I had to convert it to cjs.

const Sentry = require("@sentry/node");
const { ProfilingIntegration } = "@sentry/profiling-node";

Sentry.init({
    dsn: 'https://cfe2a99241ba7519ae7809b58053c173@o4506257044340736.ingest.sentry.io/4506257052401664',
    integrations: [
        new ProfilingIntegration(),
    ],
    // Performance Monitoring
    tracesSampleRate: 1.0,
    // Set sampling rate for profiling - this is relative to tracesSampleRate
    profilesSampleRate: 1.0,
});

const transaction = Sentry.startTransaction({
    op: "test",
    name: "My First Test Transaction",
});

setTimeout(() => {
    try {
        foo();
    } catch (e) {
        Sentry.captureException(e);
    } finally {
        transaction.finish();
    }
}, 99);

I did this at the top of the index.js, so it happens immediately.

drobati commented 10 months ago

I have tried not destructing. Removing the new and using it like a function. Neither worked. I also weirdly can not cmd + click the library which in webstorm takes you to the packages types.d.js

I was able to find the package installed, and saw lib/index.js and found the module.exports, so it looks like it should be possible to destruct this and use the constructor on the class.

Not really sure what to do here.

drobati commented 10 months ago

Wow must be tired. I clearly dropped the require. My appologies. Fixed it.