Skip to content

Next.js auto instrumentation hides properties of wrapped api routes #6931

Closed
@dhmacs

Description

@dhmacs

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which package are you using?

@sentry/nextjs

SDK Version

7.33.0

Framework Version

Next.js 12.2.3

Link to Sentry event

No response

SDK Setup

Sentry.init({
   dsn: SENTRY_DSN,
   integrations: [new BrowserTracing()],
   sampleRate: 1.0,
   normalizeDepth: 5,
   tracesSampleRate: 0.05,
   // ...
   // Note: if you want to override the automatic release value, do not set a
   // `release` value here - use the environment variable `SENTRY_RELEASE`, so
   // that it will also get attached to your source maps
   initialScope: {
      tags: {
         'next.runtime': 'client',
      },
   },
   ignoreErrors: [
      'TypeError: NetworkError when attempting to fetch resource.',
      'TypeError: Network request failed',
      // Algolia error when network requests fail.
      // Only happens on iOS devices (across all browsers)
      'RetryError: Unreachable hosts - your application id may be incorrect',
      // Can't reproduce, promise rejection with an instance of a CustomEvent
      // is unhandled.
      // Only happens on Macs, mostly Chrome, but some on safari
      'CustomEvent: Non-Error promise rejection captured with keys: currentTarget, detail, isTrusted, target',
   ],
   beforeSend: (event, hint) => {
      const ex = hint.originalException;
      if (ex && typeof ex == 'object' && ex.message) {
         // Sample hydration errors.
         if (hydrationErrors.some((msg) => ex.message.match(msg))) {
            return Math.random() < 0.05 ? event : null;
         }
      }
      return event;
   },
});

Steps to Reproduce

Context

We use our api endpoint to export a method to call the api within getServerSideProps without a network call.

Example:

const withFoo = (fn) => {
  const handler = async (req, res) => res.json(fn());
  handler.get = () => { return fn(); }
  return handler;
}

We then declare an endpoint:

// /api/hello-world.js
export default withFoo(() => "hello world!");

and we use it like this in out getServerSideProps method:

import HelloWorld from "@pages/api/hello-world";

export const getServerSideProps = async () => {
      const greeting = await HelloWorld.get();
      return {
         props: { greeting },
      };
   });

This is just a dummy example, if you want to check what we're using this for, here's the reference: https://github.com/iFixit/react-commerce/blob/add-product-caching/frontend/pages/api/nextjs/cache/product.ts (TLDR: An SWR server side caching mechanism with Redis)

Problem

With the introduction of autoInstrumentServerFunctions we are unable to access the .get static method that we export from our api endpoint because Sentry wraps the function without re-exporting any attached static prop.
To avoid breaking this use cases Sentry wrappers needs to copy over any static method (Just for reference this is similar to the problem of writing higher order component in React https://reactjs.org/docs/higher-order-components.html#static-methods-must-be-copied-over)

Expected Result

Sentry wrapper should re-export any static method to avoid breaking this advanced use cases

Actual Result

Webpack throws an error because it can't find HelloWorld.get method exported from the module

Metadata

Metadata

Assignees

Labels

Package: nextjsIssues related to the Sentry Nextjs SDK

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions