googleapis/cloud-profiler-nodejs

Unable to use on electron app

VikramTiwari opened this issue · 13 comments

Environment details

  • OS: mac os 10.15.2
  • Node.js version: 12.13.1
  • npm version: 6.12.1
  • @google-cloud/profiler version: 3.0.1
  • electron: 7.1.3

Steps to reproduce:

  • As soon as I start the app, it breaks with following error log:
Error: Cannot find module '/Users/vikram/Documents/code/omni/my-project/node_modules/pprof/build/electron-v7.1-darwin-x64-unknown/pprof.node'
Require stack:
- /Users/vikram/Documents/code/omni/my-project/node_modules/pprof/out/src/heap-profiler-bindings.js
- /Users/vikram/Documents/code/omni/my-project/node_modules/pprof/out/src/heap-profiler.js
- /Users/vikram/Documents/code/omni/my-project/node_modules/pprof/out/src/index.js
- /Users/vikram/Documents/code/omni/my-project/node_modules/@google-cloud/profiler/out/src/index.js
- /Users/vikram/Documents/code/omni/my-project/dist/app.js
- /Users/vikram/Documents/code/omni/my-project/node_modules/electron/dist/Electron.app/Contents/Resources/default_app.asar/main.js
- 
    at Module._resolveFilename (internal/modules/cjs/loader.js:717:15)
    at Function../lib/common/reset-search-paths.ts.Module._resolveFilename (electron/js2c/browser_init.js:7609:16)
    at Module._load (internal/modules/cjs/loader.js:622:27)
    at Module._load (electron/js2c/asar.js:717:26)
    at Function.Module._load (electron/js2c/asar.js:717:26)
    at Module.require (internal/modules/cjs/loader.js:775:19)
    at require (internal/modules/cjs/helpers.js:68:18)
    at Object.<anonymous> (/Users/vikram/Documents/code/omni/my-project/node_modules/pprof/out/src/heap-profiler-bindings.js:21:18)
    at Module._compile (internal/modules/cjs/loader.js:880:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:892:10)
    at Module.load (internal/modules/cjs/loader.js:735:32)
    at Module._load (internal/modules/cjs/loader.js:648:12)
    at Module._load (electron/js2c/asar.js:717:26)
    at Function.Module._load (electron/js2c/asar.js:717:26)
    at Module.require (internal/modules/cjs/loader.js:775:19)
    at require (internal/modules/cjs/helpers.js:68:18)
Error: Cannot find module '/Users/vikram/Documents/code/omni/my-project/node_modules/pprof/build/electron-v7.1-darwin-x64-unknown/pprof.node'
Require stack:
- /Users/vikram/Documents/code/omni/my-project/node_modules/pprof/out/src/heap-profiler-bindings.js
- /Users/vikram/Documents/code/omni/my-project/node_modules/pprof/out/src/heap-profiler.js
- /Users/vikram/Documents/code/omni/my-project/node_modules/pprof/out/src/index.js
- /Users/vikram/Documents/code/omni/my-project/node_modules/@google-cloud/profiler/out/src/index.js
- /Users/vikram/Documents/code/omni/my-project/dist/app.js
- /Users/vikram/Documents/code/omni/my-project/node_modules/electron/dist/Electron.app/Contents/Resources/default_app.asar/main.js
- 
    at Module._resolveFilename (internal/modules/cjs/loader.js:717:15)
    at Function../lib/common/reset-search-paths.ts.Module._resolveFilename (electron/js2c/browser_init.js:7609:16)
    at Module._load (internal/modules/cjs/loader.js:622:27)
    at Module._load (electron/js2c/asar.js:717:26)
    at Function.Module._load (electron/js2c/asar.js:717:26)
    at Module.require (internal/modules/cjs/loader.js:775:19)
    at require (internal/modules/cjs/helpers.js:68:18)
    at Object.<anonymous> (/Users/vikram/Documents/code/omni/my-project/node_modules/pprof/out/src/heap-profiler-bindings.js:21:18)
    at Module._compile (internal/modules/cjs/loader.js:880:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:892:10)
    at Module.load (internal/modules/cjs/loader.js:735:32)
    at Module._load (internal/modules/cjs/loader.js:648:12)
    at Module._load (electron/js2c/asar.js:717:26)
    at Function.Module._load (electron/js2c/asar.js:717:26)
    at Module.require (internal/modules/cjs/loader.js:775:19)
    at require (internal/modules/cjs/helpers.js:68:18) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/Users/vikram/Documents/code/omni/my-project/node_modules/pprof/out/src/heap-profiler-bindings.js',
    '/Users/vikram/Documents/code/omni/my-project/node_modules/pprof/out/src/heap-profiler.js',
    '/Users/vikram/Documents/code/omni/my-project/node_modules/pprof/out/src/index.js',
    '/Users/vikram/Documents/code/omni/my-project/node_modules/@google-cloud/profiler/out/src/index.js',
    '/Users/vikram/Documents/code/omni/my-project/dist/app.js',
    '/Users/vikram/Documents/code/omni/my-project/node_modules/electron/dist/Electron.app/Contents/Resources/default_app.asar/main.js',
    undefined
  ]
} uncaughtException

@VikramTiwari -- Could you provide a bit more information about how @google-cloud/profiler was installed?

@google-cloud/profiler depends on a module, pprof, that has a native component. pprof has some pre-built binaries available (just for Linux and Alpine when using Node.js 8, 10, or 12). When pprof is installed, the binary corresponding for the version (of Node, or electron) and platform is either fetched (if a pre-build binary is available) or built (it uses [node-gyp](https://github.com/nodejs/node-gyp to build when needed).

From the output, I might guess that the system installed pprof assuming that it would be used with Node.js and not electron, and so build the version of the binary needed for whatever version of Node.js (errors like this also happen if I install the @google-cloud/profiler with one version of node, and then switch the version of node, or if I copy my node_modules directory from my non-Alpine linux machine onto an Alpine docker image and try to use the agent).

I haven't used electron, but it looks like you should be able to use a command like npm install --runtime=electron --target=7.1.2 @google-cloud/profiler (see node-gyp's documentation for details) to let npm know to build for whatever version of electron you're using.

We haven't tested the agent with electron. I'd be interested to know if specifying a runtime and target when installing might allow @google-cloud/profiler to work for you (or what errors then occur when building the agent).

Hey @nolanmar511 Thanks for the detailed response.

I tried with specifying the target during install and got following error. It didn't find the lib and tried to compile it's own.

$ npm install --runtime=electron --target=7.1.2 @google-cloud/profiler

> pprof@1.2.0 install /Users/vikram/Documents/code/omni/my-project/node_modules/pprof
> node-pre-gyp install --fallback-to-build

node-pre-gyp WARN Using request for node-pre-gyp https download 
node-pre-gyp WARN Tried to download(404): https://storage.googleapis.com/cloud-profiler/pprof-nodejs/release/v1.2.0/electron-v7.1-darwin-x64-unknown.tar.gz 
node-pre-gyp WARN Pre-built binaries not found for pprof@1.2.0 and electron@7.1.2 (electron-v7.1 ABI, unknown) (falling back to source compile with node-gyp) 
gyp WARN install got an error, rolling back install
gyp ERR! configure error 
gyp ERR! stack Error: 404 response downloading https://nodejs.org/dist/v7.1.2/node-v7.1.2-headers.tar.gz
gyp ERR! stack     at Request.<anonymous> (/Users/vikram/.nvm/versions/node/v12.13.1/lib/node_modules/npm/node_modules/node-gyp/lib/install.js:187:14)
gyp ERR! stack     at Request.emit (events.js:215:7)
gyp ERR! stack     at Request.onRequestResponse (/Users/vikram/.nvm/versions/node/v12.13.1/lib/node_modules/npm/node_modules/request/request.js:1066:10)
gyp ERR! stack     at ClientRequest.emit (events.js:210:5)
gyp ERR! stack     at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:583:27)
gyp ERR! stack     at HTTPParser.parserOnHeadersComplete (_http_common.js:115:17)
gyp ERR! stack     at TLSSocket.socketOnData (_http_client.js:456:22)
gyp ERR! stack     at TLSSocket.emit (events.js:210:5)
gyp ERR! stack     at addChunk (_stream_readable.js:309:12)
gyp ERR! stack     at readableAddChunk (_stream_readable.js:290:11)
gyp ERR! System Darwin 19.0.0
gyp ERR! command "/Users/vikram/.nvm/versions/node/v12.13.1/bin/node" "/Users/vikram/.nvm/versions/node/v12.13.1/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "configure" "--fallback-to-build" "--module=/Users/vikram/Documents/code/omni/my-project/node_modules/pprof/build/electron-v7.1-darwin-x64-unknown/pprof.node" "--module_name=pprof" "--module_path=/Users/vikram/Documents/code/omni/my-project/node_modules/pprof/build/electron-v7.1-darwin-x64-unknown" "--napi_version=5" "--node_abi_napi=napi" "--napi_build_version=0" "--node_napi_label=electron-v7.1"
gyp ERR! cwd /Users/vikram/Documents/code/omni/my-project/node_modules/pprof
gyp ERR! node -v v12.13.1
gyp ERR! node-gyp -v v5.0.5
gyp ERR! not ok 
node-pre-gyp ERR! build error 
node-pre-gyp ERR! stack Error: Failed to execute '/Users/vikram/.nvm/versions/node/v12.13.1/bin/node /Users/vikram/.nvm/versions/node/v12.13.1/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js configure --fallback-to-build --module=/Users/vikram/Documents/code/omni/my-project/node_modules/pprof/build/electron-v7.1-darwin-x64-unknown/pprof.node --module_name=pprof --module_path=/Users/vikram/Documents/code/omni/my-project/node_modules/pprof/build/electron-v7.1-darwin-x64-unknown --napi_version=5 --node_abi_napi=napi --napi_build_version=0 --node_napi_label=electron-v7.1' (1)
node-pre-gyp ERR! stack     at ChildProcess.<anonymous> (/Users/vikram/Documents/code/omni/my-project/node_modules/node-pre-gyp/lib/util/compile.js:83:29)
node-pre-gyp ERR! stack     at ChildProcess.emit (events.js:210:5)
node-pre-gyp ERR! stack     at maybeClose (internal/child_process.js:1021:16)
node-pre-gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:283:5)
node-pre-gyp ERR! System Darwin 19.0.0
node-pre-gyp ERR! command "/Users/vikram/.nvm/versions/node/v12.13.1/bin/node" "/Users/vikram/Documents/code/omni/my-project/node_modules/.bin/node-pre-gyp" "install" "--fallback-to-build"
node-pre-gyp ERR! cwd /Users/vikram/Documents/code/omni/my-project/node_modules/pprof
node-pre-gyp ERR! node -v v12.13.1
node-pre-gyp ERR! node-pre-gyp -v v0.13.0
node-pre-gyp ERR! not ok 
Failed to execute '/Users/vikram/.nvm/versions/node/v12.13.1/bin/node /Users/vikram/.nvm/versions/node/v12.13.1/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js configure --fallback-to-build --module=/Users/vikram/Documents/code/omni/my-project/node_modules/pprof/build/electron-v7.1-darwin-x64-unknown/pprof.node --module_name=pprof --module_path=/Users/vikram/Documents/code/omni/my-project/node_modules/pprof/build/electron-v7.1-darwin-x64-unknown --napi_version=5 --node_abi_napi=napi --napi_build_version=0 --node_napi_label=electron-v7.1' (1)

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! pprof@1.2.0 install: `node-pre-gyp install --fallback-to-build`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the pprof@1.2.0 install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/vikram/.npm/_logs/2019-12-11T22_39_35_627Z-debug.log

Sorry! It looks like I had missed a necessary flag.

VikramTiwari@, could you try adding the flag --dist-url=https://electronjs.org/headers; so like npm install --runtime=electron --target=7.1 @google-cloud/profiler --dist-url=https://electronjs.org/headers. This worked for us to build the agent.

I'd found more information about using native modules with electron at https://github.com/electron/electron/blob/master/docs/tutorial/using-native-node-modules.md.

Hey @nolanmar511 Sorry about the delayed response but seems like the issue with identifying a build version now.

$ npm install --runtime=electron --target=7.1 @google-cloud/profiler --dist-url=https://electronjs.org/headers 

> pprof@1.2.0 install /Users/vikram/Documents/code/my-project/node_modules/pprof
> node-pre-gyp install --fallback-to-build

node-pre-gyp WARN Using request for node-pre-gyp https download 
node-pre-gyp ERR! install error 
node-pre-gyp ERR! stack TypeError: Cannot read property 'major' of null
node-pre-gyp ERR! stack     at get_electron_abi (/Users/vikram/Documents/code/my-project/node_modules/node-pre-gyp/lib/util/versioning.js:40:37)
node-pre-gyp ERR! stack     at get_runtime_abi (/Users/vikram/Documents/code/my-project/node_modules/node-pre-gyp/lib/util/versioning.js:83:16)
node-pre-gyp ERR! stack     at Object.module.exports.evaluate (/Users/vikram/Documents/code/my-project/node_modules/node-pre-gyp/lib/util/versioning.js:295:19)
node-pre-gyp ERR! stack     at install (/Users/vikram/Documents/code/my-project/node_modules/node-pre-gyp/lib/install.js:216:31)
node-pre-gyp ERR! stack     at Object.self.commands.<computed> [as install] (/Users/vikram/Documents/code/my-project/node_modules/node-pre-gyp/lib/node-pre-gyp.js:52:37)
node-pre-gyp ERR! stack     at run (/Users/vikram/Documents/code/my-project/node_modules/node-pre-gyp/bin/node-pre-gyp:82:30)
node-pre-gyp ERR! stack     at Object.<anonymous> (/Users/vikram/Documents/code/my-project/node_modules/node-pre-gyp/bin/node-pre-gyp:134:1)
node-pre-gyp ERR! stack     at Module._compile (internal/modules/cjs/loader.js:959:30)
node-pre-gyp ERR! stack     at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10)
node-pre-gyp ERR! stack     at Module.load (internal/modules/cjs/loader.js:815:32)
node-pre-gyp ERR! System Darwin 19.2.0
node-pre-gyp ERR! command "/Users/vikram/.nvm/versions/node/v12.13.1/bin/node" "/Users/vikram/Documents/code/my-project/node_modules/.bin/node-pre-gyp" "install" "--fallback-to-build"
node-pre-gyp ERR! cwd /Users/vikram/Documents/code/my-project/node_modules/pprof
node-pre-gyp ERR! node -v v12.13.1
node-pre-gyp ERR! node-pre-gyp -v v0.13.0
node-pre-gyp ERR! not ok 
Cannot read property 'major' of null

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! pprof@1.2.0 install: `node-pre-gyp install --fallback-to-build`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the pprof@1.2.0 install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/vikram/.npm/_logs/2020-01-03T17_18_24_947Z-debug.log

I'm so sorry about that! I have the same issue when I try to run the command I gave locally, so I copied over the command incorrectly here.

It looks like a full semver version needs to be specified for the target (so --target=7.1.2 instead of --target=7.1). So something like the following works for me:

npm install --runtime=electron --target=7.1.2 @google-cloud/profiler --dist-url=https://electronjs.org/headers 

For my own reference, mapbox/node-pre-gyp#307 showed this error and explained the issue.

@VikramTiwari
Were you able to try the suggestions from @nolanmar511 ?

Hey @kalyanac and @nolanmar511 I am still seeing the same issue. I have created a proof-of-concept here: https://gist.github.com/VikramTiwari/d7325e0ce4543966a1d522b9fa215b42

It contains sample electron app, along with readme on the process that I followed and error that I got. Let me know if I can help debug this.

@VikramTiwari I was able to reproduce your issue. I noticed that now you are trying to use electron 8.0.3, while the previous attempt was 7.1.2

The way I was able to resolve this is by removing existing pprof installation from node_modules, remove profiler, and install again with the electron version. I believe it's not rebuilding the pprof binary with the electron version if one already exists even though its not built with the same electron version.

For example, if pprof/build/ already has electron-v8.0-darwin-x64-unknown/, and 8.0.3 is uninstalled and electron 7.1.2 is installed, pprof will not be built for this version of electron as long as pprof/build/electron* already exists.

Without a preexisting pprof binary, I was able to run with both 7.1.2 and 8.0.3

Node.js 12.13.0, Electron 8.0.3,

`kchadalavada-macbookpro:electron-quick-start kchadalavada$ npm start

$> electron-quick-start@1.0.0 start /node/electron-quick-start
$> electron .

@google-cloud/profiler Error: Service must be specified in the configuration
(electron) The default value of app.allowRendererProcessReuse is deprecated, it is currently "false". It will change to be "true" in Electron 9. For more information please check electron/electron#18397
`

@nolanmar511
Can you check if the pprof build behavior can be corrected?

Thanks for confirming @kalyanac! Will wait for more details on this from @nolanmar511.

@VikramTiwari

There is no need to wait.

Start with a clean environment. Remove existing electron, and profiler. Check to make sure pprof directory is also removed from your modules location. Install the version of electron you want to use, and reinstall profiler so it builds with the correct electron version.

You can check modules directory/pprof/build to see if there correct version of electron binary is built or not.

I think the issue is that when one runs npm install and a package is already installed, the package won't be re-installed (unless a new version of the package must be installed). I don't think we can change this behavior.

To work around this, one can specifically install pprof (the native module used by @google-cloud/profiler) when changing versions:
So, if I run the following when pprof (the native module used by @google-cloud/profiler) has already been installed, the native module will be re-built if needed.

npm install pprof --runtime=electron --target=8.0.0 @google-cloud/profiler --dist-url=https://electronjs.org/headers

@nolanmar511

The command works but its important to note that it replaces the existing pprof/build/electron-v* with the new version. Both cant seem to co-exist.

@VikramTiwari

I think we resolved this issue. Please reopen if you have any trouble.