Skip to content

Conversation

rwalle61
Copy link
Contributor

@rwalle61 rwalle61 commented May 24, 2019

(These changes break Node 6. See below)

Fix for Node 12:

General information about the V8 API changes between Node 10 and 12

These fixes frequently involve the following:

Specific error fixes and my specific sources of information

Specific deprecation warning fixes and my specific sources of information

Notes

  • other forms of 'X->Set' will soon be deprecated - we should update our code

These changes break Node 6:

Problem:

Error output from `npm i` on Node 6
/Users/richard.waller@ibm.com/.node-gyp/6.17.1/include/node/v8.h:21:10: fatal error: 'utility' file not found
#include <utility>
         ^~~~~~~~~
1 warning and 1 error generated.
make: *** [Release/obj.target/appmetrics/geni/appmetrics.o] Error 1

This can be resolved simply following nodejs/node-gyp#1564 and nodejs/node-gyp#1574. However, that reveals that my upgrade to Node 12 is incompatible with Node 6:

Error output from `CXXFLAGS="-mmacosx-version-min=10.9" LDFLAGS="-mmacosx-version-min=10.9" npm i` on Node 6
In file included from ../src/plugins/node/prof/watchdog.h:21:
../src/plugins/node/prof/compat-inl.h:308:38: error: no member named 'New' in 'v8::CpuProfiler'
    cpu_profiler_ = v8::CpuProfiler::New(isolate);
                    ~~~~~~~~~~~~~~~~~^
Release/obj.target/appmetrics/geni/appmetrics.cpp:467:29: warning: 'Call' is deprecated [-Wdeprecated-declarations]
        listener->callback->Call(argc, argv);
                            ^
../node_modules/nan/nan.h:1673:3: note: 'Call' has been explicitly marked deprecated here
  NAN_DEPRECATED inline v8::Local<v8::Value>
  ^
../node_modules/nan/nan.h:103:40: note: expanded from macro 'NAN_DEPRECATED'
# define NAN_DEPRECATED __attribute__((deprecated))
                                       ^
Release/obj.target/appmetrics/geni/appmetrics.cpp:530:27: error: no matching constructor for initialization of
      'String::Utf8Value'
        String::Utf8Value str(isolate, Nan::To<String>(info[0]).ToLocalChecked());
                          ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/richard.waller@ibm.com/.node-gyp/6.17.1/include/node/v8.h:2428:14: note: candidate constructor not viable:
      requires single argument 'obj', but 2 arguments were provided
    explicit Utf8Value(Local<v8::Value> obj);
             ^
/Users/richard.waller@ibm.com/.node-gyp/6.17.1/include/node/v8.h:2438:5: note: candidate constructor not viable:
      requires 1 argument, but 2 were provided
    Utf8Value(const Utf8Value&);
    ^
Release/obj.target/appmetrics/geni/appmetrics.cpp:542:27: error: no matching constructor for initialization of
      'String::Utf8Value'
        String::Utf8Value str(isolate, Nan::To<String>(info[1]).ToLocalChecked());
                          ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/richard.waller@ibm.com/.node-gyp/6.17.1/include/node/v8.h:2428:14: note: candidate constructor not viable:
      requires single argument 'obj', but 2 arguments were provided
    explicit Utf8Value(Local<v8::Value> obj);
             ^
/Users/richard.waller@ibm.com/.node-gyp/6.17.1/include/node/v8.h:2438:5: note: candidate constructor not viable:
      requires 1 argument, but 2 were provided
    Utf8Value(const Utf8Value&);
    ^
Release/obj.target/appmetrics/geni/appmetrics.cpp:570:27: error: no matching constructor for initialization of
      'String::Utf8Value'
        String::Utf8Value topicArg(isolate, Nan::To<String>(info[0]).ToLocalChecked());
                          ^        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/richard.waller@ibm.com/.node-gyp/6.17.1/include/node/v8.h:2428:14: note: candidate constructor not viable:
      requires single argument 'obj', but 2 arguments were provided
    explicit Utf8Value(Local<v8::Value> obj);
             ^
/Users/richard.waller@ibm.com/.node-gyp/6.17.1/include/node/v8.h:2438:5: note: candidate constructor not viable:
      requires 1 argument, but 2 were provided
    Utf8Value(const Utf8Value&);
    ^
Release/obj.target/appmetrics/geni/appmetrics.cpp:572:27: error: no matching constructor for initialization of
      'String::Utf8Value'
        String::Utf8Value commandArg(isolate, Nan::To<String>(info[1]).ToLocalChecked());
                          ^          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/richard.waller@ibm.com/.node-gyp/6.17.1/include/node/v8.h:2428:14: note: candidate constructor not viable:
      requires single argument 'obj', but 2 arguments were provided
    explicit Utf8Value(Local<v8::Value> obj);
             ^
/Users/richard.waller@ibm.com/.node-gyp/6.17.1/include/node/v8.h:2438:5: note: candidate constructor not viable:
      requires 1 argument, but 2 were provided
    Utf8Value(const Utf8Value&);
    ^
1 warning and 5 errors generated.
make: *** [Release/obj.target/appmetrics/geni/appmetrics.o] Error 1

Solution 1

Drop Node 6. This PR achieves this.

Solution 2

Support Node 6 alongside 8, 10, and 12. We would need to spend considerable time converting probably ~60% of the fixes in this PR to use NAN and if blocks.

Ideal long-term solution

Rewrite much of appmetrics using N-API, but that is beyond the scope of this issue.

@rwalle61 rwalle61 requested a review from hhellyer May 24, 2019 13:45
Copy link
Contributor Author

@rwalle61 rwalle61 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented to explain a couple of lines

if (semver.gt(process.version, '10.0.0')) {

if (semver.gt(process.version, '12.0.0')) {
t.skip();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tobespc suggested skipping this for now

s->WriteUtf8(isolate, buf);
#else
s->WriteUtf8(buf);
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation is kind of off here. Typically the preprocessor lines (e.g. those beginning with #) would be in column 0 and the code blocks at the same indentation as if the preprocessor lines were not there.

e.g.

static std::string toStdString(Local<String> s) {
    char *buf = new char[s->Length() + 1];
#if NODE_VERSION_AT_LEAST(10, 0, 0)
    Isolate* isolate = v8::Isolate::GetCurrent();
    s->WriteUtf8(isolate, buf);
#else
    s->WriteUtf8(buf);
#endif

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/nodejs/nan/blob/master/doc/string_bytes.md#nandecodewrite perhaps? It shouldn't be necessary to have node version ifdefs, at least not for something as common as string conversions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how to implement that Nan function tbh, as I don't see how the function name and arguments are related. And Nan seems to implement writeUtf8 using 4 or 5 arguments? Happy to implement this if you show me how

@AndyRWatson
Copy link

I think option 1 is ok given that Node 6 is no longer in LTS. Agree that a longer term plan to support N-Api would be the right one to avoid issues in the future. We should document that Node 6 is no longer supported and the last known working appmetrics level

@sam-github
Copy link
Contributor

Dropping 6.x support sounds like a good idea to me, but it requires bumping the appmetrics major (because dropping 6 support is a breaking change for people using node 6). That's NBD, but don't forget to do the book keeping: it eans finding all the other runtimes packages (prometheus, etc) that depend on appmetrics, and publishing an updated major of them, that depends on the new appmetrics major.

s->WriteUtf8(isolate, buf);
#else
s->WriteUtf8(buf);
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/nodejs/nan/blob/master/doc/string_bytes.md#nandecodewrite perhaps? It shouldn't be necessary to have node version ifdefs, at least not for something as common as string conversions.

@@ -13,7 +13,7 @@
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#include "node.h" // Picks up BUILDING_NODE_EXTENSION on Windows, see #30.

#include "nan.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 Richard and I had discussed this, we just need to check we are able to take a new drop.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

opened a new issue #579

@@ -37,7 +37,7 @@ NAN_METHOD(getObjectHistogram) {

HeapProfiler *heapProfiler = isolate->GetHeapProfiler();

#if NODE_VERSION_AT_LEAST(4, 0, 0) // > v0.11+
#if NODE_VERSION_AT_LEAST(4, 0, 0) // > v4.00+
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated to this PR, but https://github.com/bnoordhuis/node-heapdump/blob/master/src/heapdump.cc#L69-L78 (which is copied into this repo) has a TakeHeapSnapshot(), maybe it can just be called from heapsnapshot/heapsnapshot.cc?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

opened a new issue #579

@@ -81,7 +81,13 @@ pushsource* createPushSource(uint32 srcid, const char* name) {

static std::string ToStdString(Local<String> s) {
char *buf = new char[s->Length() + 1];
s->WriteUtf8(buf);
#if NODE_VERSION_AT_LEAST(10, 0, 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see previous comment

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indenting again.

@tobespc
Copy link
Member

tobespc commented May 28, 2019

The issues raised in the comments will be dealt with as separate PR's

Copy link
Member

@tobespc tobespc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Member

@hhellyer hhellyer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • I'd like to be sure we need to drop Node 6 support, that feels wrong especially given we work on Node 6 until this goes in.
  • We need to see whether we can update the heapdump code with the latest from the heapdump npm.

@@ -13,7 +13,7 @@
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#include "node.h" // Picks up BUILDING_NODE_EXTENSION on Windows, see #30.

#include "nan.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 Richard and I had discussed this, we just need to check we are able to take a new drop.

@rwalle61
Copy link
Contributor Author

rwalle61 commented May 30, 2019

Travis problem

Build intermittently failing on Windows (various versions of Node) with seemingly the same error in a test in http-outbound-probe-test.js.

Error output:
[Thu May 30 09:47:02 2019] com.ibm.diagnostics.healthcenter.mqtt INFO: Connecting to broker localhost:1883
Error: connect ECONNREFUSED 127.0.0.1:49860
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1191:14)
{ name: 'TAP',
  autoend: true,
  errno: 'ECONNREFUSED',
  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 49860,
  tapCaught: 'uncaughtException',
  test: 'TAP' }
Error: socket hang up
    at createHangUpError (_http_client.js:342:15)
    at Socket.socketCloseListener (_http_client.js:377:23)
    at emitOne (events.js:121:20)
    at Socket.emit (events.js:211:7)
    at TCP._handle.close [as _onclose] (net.js:561:12)
{ name: 'TAP',
  autoend: true,
  code: 'ECONNRESET',
  tapCaught: 'uncaughtException',
  test: 'TAP' }
    # time=92.67ms
not ok 3 - tests/probes/http-outbound-probe-test.js # time=5743.445ms
  ---
  timeout: 120000
  file: tests/probes/http-outbound-probe-test.js
  childId: 2
  command: 'C:\ProgramData\nvs\node\8.16.0\x64\node.exe'
  args:
    - '-r'
    - 'C:\Users\travis\build\RuntimeTools\appmetrics\node_modules\esm\esm.js'
    - tests/probes/http-outbound-probe-test.js
  stdio:
    - 0
    - pipe
    - 2
  cwd: 'C:\Users\travis\build\RuntimeTools\appmetrics'
  exitCode: 1
  ...

Solution

  • On Travis, Appmetrics passes tests ~60% time on Windows with Node 8, 10, and 12.
  • We have manually verified that Appmetrics passes tests on Windows with Node 8, 10, and 12.
  • Travis says "Windows builds are in early access stage"
  • other people have reported Travis errors due to intermittent network issues https://travis-ci.community/t/nvs-add-6-download-error/3050

Therefore, we will keep running the Windows tests on Travis but flag them as allowed to fail.

  • That way we will at least be able to monitor whether the Windows tests pass more consistently when Windows builds are no longer just early access.
  • If the tests still fail intermittently at that point, then we should investigate these failures further

@rwalle61 rwalle61 requested a review from hhellyer May 30, 2019 16:01
@rwalle61
Copy link
Contributor Author

I've updated the docs, so this PR also resolves #571

Copy link
Member

@hhellyer hhellyer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, please use squash and merge to deliver this, there's 20 commits in here and we should add them to master as one logical change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants