grafana / faro-web-sdk

The Grafana Faro Web SDK, part of the Grafana Faro project, is a highly configurable web SDK for real user monitoring (RUM) that instruments browser frontend applications to capture observability signals. Frontend telemetry can then be correlated with backend and infrastructure data for full-stack observability.
https://grafana.com/oss/faro/
Apache License 2.0
765 stars 66 forks source link

TracingInstrumentation is breaking NextJS application #219

Open therealmanny opened 1 year ago

therealmanny commented 1 year ago

Description

I get the following errors when I add TracingInstrumentation to my NextJS application.

Unhandled Promise rejection: Cannot find module for page: /en ; Zone: <root> ; Task: Promise.then ; Value: PageNotFoundError: Cannot find module for page: /en
    at getPagePath (C:\Users\e\s\r\A\ui.app\node_modules\next\dist\server\require.js:145:15)
    at requirePage (C:\Users\e\s\r\A\ui.app\node_modules\next\dist\server\require.js:150:22)
    at C:\Users\e\s\r\A\ui.app\node_modules\next\dist\server\load-components.js:68:84
    at ZoneDelegate.invoke (C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:400:30)
    at Zone.run (C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:160:47)
    at C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:1318:38
    at ZoneDelegate.invokeTask (C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:434:35)
    at Zone.runTask (C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:205:51)
    at drainMicroTaskQueue (C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:620:39) {
  code: 'ENOENT'
} PageNotFoundError: Cannot find module for page: /en
    at getPagePath (C:\Users\e\s\r\A\ui.app\node_modules\next\dist\server\require.js:145:15)
    at requirePage (C:\Users\e\s\r\A\ui.app\node_modules\next\dist\server\require.js:150:22)
    at C:\Users\e\s\r\A\ui.app\node_modules\next\dist\server\load-components.js:68:84
    at ZoneDelegate.invoke (C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:400:30)
    at Zone.run (C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:160:47)
    at C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:1318:38
    at ZoneDelegate.invokeTask (C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:434:35)
    at Zone.runTask (C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:205:51)
    at drainMicroTaskQueue (C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:620:39)

I have tried a couple of things to fix it, including deleting the node_modules folder and reinstalling the packages. I also upgraded the NextJS and other packages. But I still got the same errors. Thanks, for taking a look at this issue.

Steps to reproduce

  1. Add Faro web SDK, web tracing, and react to NextJS project
  2. Run app
  3. Observe console for errors

Expected behavior

There should be no errors when the app starts up.

Actual behavior

The following errors are created when the app starts up.

Unhandled Promise rejection: Cannot find module for page: /en ; Zone: <root> ; Task: Promise.then ; Value: PageNotFoundError: Cannot find module for page: /en
    at getPagePath (C:\Users\e\s\r\A\ui.app\node_modules\next\dist\server\require.js:145:15)
    at requirePage (C:\Users\e\s\r\A\ui.app\node_modules\next\dist\server\require.js:150:22)
    at C:\Users\e\s\r\A\ui.app\node_modules\next\dist\server\load-components.js:68:84
    at ZoneDelegate.invoke (C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:400:30)
    at Zone.run (C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:160:47)
    at C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:1318:38
    at ZoneDelegate.invokeTask (C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:434:35)
    at Zone.runTask (C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:205:51)
    at drainMicroTaskQueue (C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:620:39) {
  code: 'ENOENT'
} PageNotFoundError: Cannot find module for page: /en
    at getPagePath (C:\Users\e\s\r\A\ui.app\node_modules\next\dist\server\require.js:145:15)
    at requirePage (C:\Users\e\s\r\A\ui.app\node_modules\next\dist\server\require.js:150:22)
    at C:\Users\e\s\r\A\ui.app\node_modules\next\dist\server\load-components.js:68:84
    at ZoneDelegate.invoke (C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:400:30)
    at Zone.run (C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:160:47)
    at C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:1318:38
    at ZoneDelegate.invokeTask (C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:434:35)
    at Zone.runTask (C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:205:51)
    at drainMicroTaskQueue (C:\Users\e\s\r\A\ui.app\node_modules\zone.js\bundles\zone.umd.js:620:39)

Environment

Demo

Context

Package.json dependencies

{
  "dependencies": {
    "@grafana/faro-react": "^1.1.0",
    "@grafana/faro-web-sdk": "^1.1.0",
    "@grafana/faro-web-tracing": "^1.1.0",
    "algoliasearch": "^4.14.0",
    "and": "^0.0.3",
    "autolinker": "^4.0.0",
    "build": "^0.1.4",
    "classnames": "^2.3.1",
    "is_js": "^0.9.0",
    "jest-junit": "^15.0.0",
    "js-cookie": "^3.0.1",
    "lodash": "^4.17.21",
    "moment": "^2.29.4",
    "next": "^13.4.6",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-focus-lock": "^2.9.1",
    "react-instantsearch-dom": "^6.32.0",
    "react-json-pretty": "^2.2.0",
    "react-qr-code": "^2.0.8",
    "sass": "^1.54.5"
  }
}

Faro initialization (initialize.ts)

import {
  FetchTransport,
  initializeFaro as coreInit,
  getWebInstrumentations
} from "@grafana/faro-web-sdk";
import { TracingInstrumentation } from "@grafana/faro-web-tracing";
import getConfig from "next/config";
const { publicRuntimeConfig } = getConfig() || { publicRuntimeConfig: {} }

export const initializeFaro = () => {
  const faro = coreInit({
    app: {
      name: publicRuntimeConfig.NAME,
      version: publicRuntimeConfig.VERSION,
      environment: publicRuntimeConfig.ENVIRONMENT,
      release: publicRuntimeConfig.RELEASE
    },
    instrumentations: [
      ...getWebInstrumentations(),
      new TracingInstrumentation({
        instrumentationOptions: {
          propagateTraceHeaderCorsUrls: [
            new RegExp("https://jsonplaceholder.typicode.com/*"),
          ]
        },
        resourceAttributes: {
          namespace: publicRuntimeConfig.NAMESPACE,
          node_name: publicRuntimeConfig.NODE_NAME,
          pod: publicRuntimeConfig.POD_NAME
        }
      })
    ],
    transports: [
      new FetchTransport({
        url: publicRuntimeConfig.COLLECTOR_URL,
        apiKey: publicRuntimeConfig.COLLECTOR_API_KEY
      })
    ]
  });

  faro?.api.pushLog(["Faro was initialized"]);
  return faro;
}

_app.tsx

import type { AppContext, AppProps } from 'next/app'
import dynamic from 'next/dynamic'
import App from 'next/app'
import Head from 'next/head'
import SearchWrapper from 'searchContext/useSearchContext'
import MetadataContextWrapper from 'searchContext/useMetadataContext'
import getConfig from 'next/config'
import { FaroErrorBoundary, withFaroProfiler } from '@grafana/faro-react'
import { initializeFaro } from 'faro/initialize'
import { useEffect } from 'react'

const AppWrapper = dynamic(() => import('context/useAppContext'), { ssr: false })
const LocalizeWrapper = dynamic(() => import('localize/useLocalizeContext'), { ssr: false })
const { publicRuntimeConfig } = getConfig() || { publicRuntimeConfig: {} }

function MyApp({ Component, pageProps }: AppProps) {

  useEffect(() => {
    if ( publicRuntimeConfig.COLLECTOR_URL && publicRuntimeConfig.COLLECTOR_API_KEY ) {
      initializeFaro()
    }
  }, [])

  return (
    <FaroErrorBoundary>
      <AppWrapper>
        <LocalizeWrapper>
          <MetadataContextWrapper>
            <SearchWrapper>
              <Head>
                <title>UI app</title>
              </Head>
              <Component {...pageProps} />
            </SearchWrapper>
          </MetadataContextWrapper>
        </LocalizeWrapper>
      </AppWrapper>
    </FaroErrorBoundary>
  )
}

MyApp.getInitialProps = async (appContext: AppContext) => {
  const appProps = await App.getInitialProps(appContext)

  return { ...appProps }
}

export default withFaroProfiler(MyApp)
valleywood commented 1 year ago

Got the exact same problem using next version 13.5.5 and @grafana/faro-web-sdkversion 1.2.2 If I add new TracingInstrumentation(), to my instrumentations I get the exact same error.

balbalcode commented 1 year ago

hi @therealmanny i've same problem with you but I'm runnings my web with nuxt. can you tell me the node version in your device? thank you.

haimprecise commented 11 months ago

Also running w/ Next.js, I noticed all my handled promise errors under then/catch gets an Unhandled Runtime Error on my screen.

It seems zone.js is breaking the show

soleo commented 3 months ago

Now in August 2024, I am running into similar issue with NextJs 14.2.5 (Node 20.9.0), and I have the latest package version for faro

    "@grafana/faro-react": "^1.9.0",
    "@grafana/faro-web-sdk": "^1.9.0",
    "@grafana/faro-web-tracing": "^1.9.0",

The error message I got when run next build.

Node.js v20.9.0
 ⨯ Static worker exited with code: 1 and signal: null
 ⨯ Static worker exited with code: 1 and signal: null
   Generating static pages (0/2)  [   =]node:internal/event_target:1083
  process.nextTick(() => { throw err; });
                           ^

Error [ERR_INTERNAL_ASSERTION]: Unknown worker message type message
This is caused by either a bug in Node.js or incorrect usage of Node.js internals.
Please open an issue with this stack trace at https://github.com/nodejs/node/issues

    at new NodeError (node:internal/errors:406:5)
    at Function.fail (node:internal/assert:20:9)
    at [kOnMessage] (node:internal/worker:354:12)
    at MessagePort.<anonymous> (node:internal/worker:232:57)
    at _ZoneDelegate.invokeTask (/Users/x/workspace/dotcom-next-gen-flume/node_modules/zone.js/bundles/zone.umd.js:443:35)
    at Zone.runTask (/Users/x/workspace/dotcom-next-gen-flume/node_modules/zone.js/bundles/zone.umd.js:214:51)
    at ZoneTask.invokeTask [as invoke] (/Users/xinjiang.shao/workspace/dotcom-next-gen-flume/node_modules/zone.js/bundles/zone.umd.js:525:38)
    at invokeTask (/Users/x/workspace/dotcom-next-gen-flume/node_modules/zone.js/bundles/zone.umd.js:1727:22)
    at globalCallback (/Users/x/workspace/dotcom-next-gen-flume/node_modules/zone.js/bundles/zone.umd.js:1758:31)
    at MessagePort.globalZoneAwareCallback (/Users/xx/workspace/dotcom-next-gen-flume/node_modules/zone.js/bundles/zone.umd.js:1794:20) {
  code: 'ERR_INTERNAL_ASSERTION'
}
codecapitano commented 3 months ago

Hi @soleo can you test one thing. I have a suspicion that a dependency may cause this error.

Would you mind trying to remove/not add the web-tracing package and see if the error is still there?

soleo commented 3 months ago

@codecapitano I did test with TracingInstrumentation() removed, and the build did pass.

The initialization for Faro is very similar to what @jpmcb did in https://github.com/open-sauced/app/pull/3139

export const initGrafanaFaro = () => {
    return initializeFaro({
        url: process.env.FARO_URL,

        app: {
            name: process.env.APP_NAME,
            version: version,
            environment: process.env.ENVIRONMENT_NAME,
        },

        instrumentations: [
            // load the mandatory web instrumentation
            ...getWebInstrumentations({
                captureConsole: true,
            }),

            // add tracing instrumentation which should include the React Profiler
                         // new TracingInstrumentation(),

            new ReactIntegration({
                // In the future, we may choose to integrate with React router instrumentation to
                // get deeper metrics on matched routes, navigation types, etc.
                // Next/router doesn't seem to be supported which won't give us route metrics.
                //
                // Reference: https://github.com/grafana/faro-web-sdk/tree/main/packages/react
                //
                // router: {}
            }),
        ],
    });
};

With that being said, we do wanna get the web tracing working in order to have better visibility. Is there a recommended path for nextjs apps?

codecapitano commented 3 months ago

Hi @soleo

I think you run Faro on the server as well? Faro is client only.

So you need to ensure that Faro is running in the client only. Afaik this can be configured in Next by the useClient pragma.

To instrument the server we recommend to use opentelemetry-node.

You can find an example in next docs: Manual OpenTelemetry configuration

cc @cedricziel