-
Notifications
You must be signed in to change notification settings - Fork 45
Fix version reporting in NodeReport section #30
Conversation
fprintf(fp, " %s: %s\n", *name, *version); | ||
} | ||
} | ||
fprintf(fp, "}\n"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How sure are you that it's safe to call into the VM at this point?
Also, spaces around operators a few lines up?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spaces fixed, thanks.
Other bits of the report later on (e.g. GC statistics, JavaScript stack) are generated via VM calls, so I guess as safe as they are? For this PR an alternative to avoid VM calls here is perhaps capturing process.versions
into a static buffer on module initialization and then outputting the captured buffer when the report is written.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would capture it at the earliest opportunity, that will let you deal with errors more gracefully. For example, if user JS code (however unwise) did the below, your code would assert and abort.
Object.defineProperty(process, 'versions', {get() { throw 'boom' }});
This particular example is a little farfetched but buggy code clobbering process
is not unheard of.
I was trying to avoid going into JavaScript-land if at all possible. As Ben says, things may be damaged, especially JS objects on the heap. For v8 there is a nice C++ API - Yes we should capture the versions at module load time and stash them rather than access the process object at dump time. Incidently, using SetAbortOnUncaughtExceptionCallback() to intercept exceptions is not working very well, so I may need to switch that to use process.on('uncaughtException'). Longer term I think we'll need better APIs in v8 and Node, but that's a long haul. One other design thing was to make NodeReport easily readable by non-programmers, admins etc. So I prefer something that headlines the Node version like rather than 'programmer-style' output |
Updated to capture versions at module load time. Changed the output to be slightly more human readable, currently:
Comments on formatting? I could pull out I think I also need to change |
Yes, suggest have node and v8 top of the list as they are of most interest to people I think. I had the less interesting components on a single line, to keep the intro section short - you don't have to scroll down far to see the stack traces, but it's not a big deal. Anything to make the code resilient - so we carry on - is good, with some 'version information not available' indication maybe. Thanks! |
Ah, scratch that last comment, I'm sorry. I liked the original format, but all the process.versions keys should
As an aside, |
My issue with including all the components on one line is that the line is quite long. Should we filter out |
No, patching over oddities in node just makes things odder, we'd have two special snowflakes, not one. The line is not longer than lots of other lines, so I don't think its a big issue, but I see your point. I think repeating the word "version" in every line is ugly and repetitive. Perhaps:
|
I think people understand what
is. Would it make sense to stick to that format even if we don't go back to javascript to generate it ? |
@sam-github I agree that modules: is not a great name, but thinking we want to be consistent with process.versions. |
Updated so the output is now similar to what it was before. I've enclosed the components (i.e. everything in
I left the tests so that they only check the information is there (and at the moment ignore formatting). I'll squash later on. While I'm editing in this area, as per #29 I'll add a line to this section of the report that reports the version of nodereport used and which version of Node.js it was compiled against, e.g. |
Oh I also attempted to make the code resilient, with a default |
Possibly stupid question, should it be
or
? |
|
It should be Node.js, not so sure about nodereport versus NodeReport but I'm leaning to NodeReport. |
@@ -70,6 +68,7 @@ const char* v8_states[] = {"JS", "GC", "COMPILER", "OTHER", "EXTERNAL", "IDLE"}; | |||
static bool report_active = false; // recursion protection | |||
static char report_filename[NR_MAXNAME + 1] = ""; | |||
static char report_directory[NR_MAXPATH + 1] = ""; // defaults to current working directory | |||
static std::string versionString = "Unable to determine Node.js version\n"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use snake_case for consistency? (Here and elsewhere, e.g., also please update processProp, versionProp, and so on.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
isolate->GetCurrentContext()->Global(), | ||
processProp.ToLocalChecked()); | ||
if (process.IsEmpty() || process.ToLocalChecked()->IsUndefined() | ||
|| trycatch.HasCaught()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know how much core style is supposed to be followed but assuming it's the same style:
- the operator should go on the previous line
- line continuations in the Nan::Get() call should be indented with four spaces
The call to IsUndefined() looks like it should be !process.ToLocalChecked()->IsObject()
?
Nan::TryCatch trycatch; | ||
Nan::MaybeLocal<String> processProp = Nan::New<String>("process"); | ||
if (processProp.IsEmpty() || trycatch.HasCaught()) { | ||
trycatch.Reset(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.Reset() is the default behaviour unless .ReThrow() is called, you don't need to call it explicitly. You also don't really need to check for .HasCaught() because .IsEmpty() is always true in case of exception.
A more succinct way of writing it:
Local<String> process_prop;
if (!Nan::New<String>("process").ToLocal(&process_prop)) return;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I've redone SetVersionString()
in the suggested more succinct style and it's much easier to read now.
size_t lineLength = 1; | ||
versionString.append("("); | ||
std::sort(compVersions.begin(), compVersions.end()); | ||
for (std::vector<std::string>::iterator it = compVersions.begin(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
auto it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
Fixed suggestions from @bnoordhuis. Added reporting of NodeReport version and test.
|
Made the code even more resilient -- It will now get the Node.js version from
Squashed commits. |
LGTM, new tests all ran ok (on Linux) @bnoordhuis - are your review comments all resolved now? thanks |
@bnoordhuis is this good to merge because this is blocking us from adding nodereport to citgm? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with two final comments and a suggestion, otherwise looks nice!
v8::Local<v8::Object> global_obj = isolate->GetCurrentContext()->Global(); | ||
v8::Local<v8::Value> process_value; | ||
if (!Nan::Get(global_obj, process_prop).ToLocal(&process_value)) return; | ||
v8::Local<v8::Object> process_obj = process_value.As<v8::Object>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the sake of robustness, you should if (!process_value->IsObject()) return;
first.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
if (!Nan::Get(versions_obj, name_value).ToLocal(&version_value)) continue; | ||
|
||
Nan::Utf8String component_name(name_value); | ||
Nan::Utf8String component_version(version_value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Robustness: if (*component_name == nullptr || *component_version == nullptr) continue;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
} | ||
nodeComponents.forEach((c) => { | ||
if (c !== 'node') { | ||
if (expectedVersions.indexOf(c) === -1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might as well use .includes() here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NodeReport claims to be Node.js v4.x compatible ("node": ">=4.0.0"
) and the version of V8 in v4.x doesn't have Array.prototype.includes()
.
Report the versions of Node.js and its components based on the runtime and not compile time constants. Report NodeReport version and the version of Node.js it was built against. Extend the tests to validate the versions reported in the report. Fixes: nodejs#29
Updated to address Ben's robustness comments. Haven't implemented the suggested use of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Report the versions of Node.js and its components based on the runtime and not compile time constants. Report NodeReport version and the version of Node.js it was built against. Extend the tests to validate the versions reported in the report. Fixes: #29 PR-URL: #30 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Sam Roberts <vieuxtech@gmail.com> Reviewed-By: George Adams <george.adams@uk.ibm.com>
Landed as 368f253 |
Fixes: #29
Replaces compile time constants with the contents of
process.versions
. As a bonusares.h
andzlib.h
are no longer required, which should unblock nodejs/citgm#226.Report content before changes:
after changes:
Tests have been extended to validate the versions contained in the report.