Skip to content
This repository has been archived by the owner on Mar 4, 2022. It is now read-only.

feat(#64) added multiple aggregate levels #66

Merged

Conversation

mscottx88
Copy link
Contributor

@jasonwilson Here is the first go at this code. I need to add unit tests for the new work. If you get a moment, check it out and see what you think!

lib/dashboard.js Outdated
@@ -94,8 +100,8 @@ var VIEW_MAP = {
eventLoop: EventLoopView
};

Dashboard.prototype._showLayout = function (id) {
if (this.currentLayout === id) {
Dashboard.prototype._showLayout = function (id, forced) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there another way to update the aggregate view without having to force a layout refresh?

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 sure there is. I will work on it!

@@ -0,0 +1,37 @@
{
// Use IntelliSense to learn about possible Node.js debug attributes.
Copy link
Contributor

Choose a reason for hiding this comment

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

can we remove these comments?

Copy link
Member

Choose a reason for hiding this comment

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

i think this is a visual studio file - should add file/dir to .gitignore


screen.on("zoomAggregate", function zoomAggregate(zoom) {
// apply zoom delta and check for boundaries
this.currentAggregateZoom += zoom;
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we just use something like lodash.clamp (https://lodash.com/docs/4.17.4#clamp) to enforce bounds?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

var MetricsProvider = function MetricsProvider(screen) {
EventEmitter.call(this);
// time scaling factors
var timeScales = [
Copy link
Member

Choose a reason for hiding this comment

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

this could be in constants.js

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

@@ -0,0 +1,37 @@
{
// Use IntelliSense to learn about possible Node.js debug attributes.
Copy link
Member

Choose a reason for hiding this comment

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

i think this is a visual studio file - should add file/dir to .gitignore

mscottx88 and others added 3 commits July 20, 2017 14:45
Also, corrected the use of sinon-chai and fixed a cross-platform issue with mock-require.
Included gulp and gulpfile for unit test debugging.
New constants.js file for configuration.
Lots of performance improvements and code cleanup in MetricsProvider aggregation logic.
Lots of documentation for MetricsProvider.
gulpfile.js Outdated
@@ -0,0 +1,9 @@
"use strict";
Copy link
Member

Choose a reason for hiding this comment

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

Small nit here -- at least as a broad Formidable convention (and same for most of our clients), npm scripts have "won".

Gulp, while a great tool, has persistent problems of plugins being behind the "real" upstream projects and adding complexity / abstraction where it's not needed. Here, we just want to execute mocha. I vote we stick with mocha + package.json:scripts until we hit a use case we truly can't support.

Side note -- if we need concurrent execution of things, we've got great tools for that that work with package.json:scripts.

@jasonwilson -- Thoughts on ^^^ ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can npm run scripts allow you to debug your spec files? If so, that is great. Otherwise, the only purpose for the gulp is for debugging unit tests and I can keep it out of the main repo.

Although, excluding it would make portability an issue across dev machines.

Copy link
Member

Choose a reason for hiding this comment

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

First, you can always use mocha directly. Second npm scripts allow extra commands to punch to the command via --. So, for example,

$ npm run test-only -- --grep=foo --ANY_OTHER_MOCHA_CLI_FLAG

works just fine.

Also, we write our npm package scripts to be the portable subset of shell commands that is universally (mac, win, linux) compatible.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

By dev machine, I really meant for those folks that might use VS code as their debugger, these tagalong files are helpful to include

Copy link
Member

Choose a reason for hiding this comment

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

I'm not familiar with VS code's debugging, but I'd be surprised if generic gulp was supported and raw mocha wasn't. In any case, let's keep the main repo gulp-free to save on dependencies we don't strictly need 😉

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good. Also sounds like I might have another interested party in learning debugging and using VS code?

I think you'll find it to be a really amazing editor.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since it is an Electron app, it is built on Node too, so this editor is perfectly adapted to Node development.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Out of curiosity, since you're not using VS code, what editor are you using?

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 believe I have the solution I was looking for to remove the gulp and still get the debug ability.

https://gist.github.com/paambaati/54d33e409b4f7cf059cc

Up to date even!

Copy link
Member

Choose a reason for hiding this comment

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

I use many, currently vs code. What I meant is that I don't use the integrated debugger -- typically when I need a debugger I just do the normal node flags and open up chrome.

Nice to see you found what you need and your preferred debugging solution is still available to you!

expect(metrics.mem.heapTotal).to.be.above(0);
expect(metrics.mem.heapUsed).to.be.above(0);
expect(metrics.cpu.utilization).to.be.above(0);
expect(metrics.eventLoop.delay).to.be.a("number");
Copy link
Member

Choose a reason for hiding this comment

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

GLOBAL SUGGESTION: I know this is a refactor, but for things like:

expect(metrics.eventLoop.delay).to.be.a("number");

if for example, metrics.eventLoop is undefined, you're going to get a not-so-useful assertion failure. A better way to do this is to assert on the property and let chai tell you "that deep property doesn't exist". Aka

expect(metrics).to.have.deep.property("eventLoop.delay").that.is.a("number");

(Side note -- unique to .property assertions, the context changes from there on to the property asserted against (e.g. metrics.eventLoop.delay) and not the original target object (e.g. metrics))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Neat, I like it.

};

var stubProcess = sinon.stub(process, "memoryUsage", function () {
Copy link
Member

Choose a reason for hiding this comment

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

GLOBAL: Never use sinon.stub|spy on anything that requires a .restore(). Instead, use a sandbox which we declare at top scope for this test suite.

Here you've got a problem that if anything fails / errors in this test, you won't reach the .restore()s on L99-L100. That means you have real methods potentially left unrestored that could cause unrelated tests to fail. Thus, you must always try/catch synchronous stubs to restore or do it in a beforeEach|afterEach pair.

Since we already do this with a sandbox, you can just use that to sandbox.stub and never worry about the restore, since a global restore is done in the top-level afterEach

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 tried the sandbox but when the sandbox.restore() ran, the stub was still there. On other words, the sandbox did not work as expected.

Copy link
Member

Choose a reason for hiding this comment

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

We can work together on Monday. A sandbox restores anything created with it.

Copy link
Member

Choose a reason for hiding this comment

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

Also, @jasonwilson and @aisapatino can help with this as they've both got a ton of experience with mocha + sandboxes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Aha, I know what I did wrong, instead of sandbox.stub() I used sinon.stub() and that would explain why it didn't go in the sandbox.

I'll correct this one, thanks!

Copy link
Member

Choose a reason for hiding this comment

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

One thing I did notice was the sandbox create was in a before() (pre-existing code). This may be problematic, and as a general rule for unit tests, beforeEach() is almost always better than a before(). before() is typically reserved for super-expensive time-wise things, and I don't see that here. (Same for after())

@@ -149,6 +154,8 @@ describe("generate-layouts", function () {
]
}
]]);

done();
Copy link
Member

Choose a reason for hiding this comment

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

This looks unnecessary.

});
}

done();
Copy link
Member

Choose a reason for hiding this comment

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

Same here.

Copy link
Member

Choose a reason for hiding this comment

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

GLOBAL: done() should only be used for async callbacks. Everywhere that it's been added seems synchronous.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good. I've always done the done() as a consistency thing, but easily removed!

});

beforeEach(function () {
after(function (done) {
done();
Copy link
Member

Choose a reason for hiding this comment

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

What is this?

var sinon = require("sinon");
var sinonChai = require("sinon-chai");
var expect = chai.expect;
chai.use(sinonChai);
Copy link
Member

Choose a reason for hiding this comment

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

GLOBAL: This shouldn't be necessary -- this boilerplate is already taken care of in setup.js https://github.com/FormidableLabs/nodejs-dashboard/blob/master/test/setup.js

I think maybe the gulp switch isn't using setup? At any rate go with how we already ran mocha from package.json scripts and should work fine.

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 tried npm run scripts in addition to gulp and the problem was still there.

Copy link
Member

Choose a reason for hiding this comment

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

We can work through it on Monday. If we've got you Slack access, just hit me or @jasonwilson up and we'll work it out.

And generally, speaking, anytime you're doing a repeated, fundamental change to a bunch of files, feel free to bounce that off of us early so we can possibly help debug things up front and save you some time!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm I wonder, and this could be a red herring, but is it possibly related to the order of the parameters on the npm script? I see a difference between the coverage script and test-only script.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Scratch that, I see the commands aren't the same.

@mscottx88
Copy link
Contributor Author

@ryan-roemer @jasonwilson @aisapatino I believe this is at last ready for final review :)

@ryan-roemer
Copy link
Member

@mscottx88 -- Great! I'll review for formalities / test stuff and @jasonwilson @aisapatino can do the substantive stuff in addition to that.

Copy link
Member

@ryan-roemer ryan-roemer left a comment

Choose a reason for hiding this comment

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

Getting there!

CHANGELOG.md Outdated
@@ -1,5 +1,8 @@
# Change log

## [v0.5.1] - 2017-07-24
Copy link
Member

Choose a reason for hiding this comment

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

NIT: Typically we do Unreleased until we release. Here, it would seem our options should be MINOR (v0.4.2) or MAJOR (v0.5.0) in that v0.x.x semver parlance or whatever 😛

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yea i meant 5.0.0... sorry about that. Should I put Unreleased for now or leave CHANGLOG unchanged as part of this PR?

Copy link
Member

@ryan-roemer ryan-roemer Jul 24, 2017

Choose a reason for hiding this comment

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

Put Unreleased here. Leave package.json:version unchanged from current master.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cool, I will correct this one!

lib/constants.js Outdated

// these define the time levels that data will be aggregated into
// each number is in milliseconds

Copy link
Member

Choose a reason for hiding this comment

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

NIT: Do the empty newline // too, so that it reads as a contiguous "comment"

package.json Outdated
@@ -1,6 +1,6 @@
{
"name": "nodejs-dashboard",
"version": "0.4.1",
"version": "0.5.0",
Copy link
Member

Choose a reason for hiding this comment

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

Again, typically we don't bump versions in PRs. Also, this differs from changelog entry.

package.json Outdated
@@ -16,7 +16,7 @@
"test": "npm run lint && npm run test-only",
"test-only": "mocha -c --require test/setup.js --recursive ./test",
"test-app": "./bin/nodejs-dashboard.js node test/app/index.js",
Copy link
Member

Choose a reason for hiding this comment

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

Not part of this PR, but can you remove the prefix ./ in this command? ./ is unnecessary on mac/linux and breaks windows.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This one is weird. As is, with the ./, I get the following error:

./bin/nodejs-dashboard.js node test/app/index.js

'.' is not recognized as an internal or external command,
operable program or batch file.

When I change it to not have the ./ I get this error instead:

[email protected] test-app C:\Users\formidable\Documents\nodejs-dashboard
bin/nodejs-dashboard.js node test/app/index.js

'bin' is not recognized as an internal or external command,
operable program or batch file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe my npm settings are incorrect. When I put node in front, it works:

$ npm run test-app

[email protected] test-app C:\Users\formidable\Documents\nodejs-dashboard
node bin/nodejs-dashboard.js node test/app/index.js

Waiting for client connection on 9838...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ryan-roemer Should/Could it be done as:

"test-app": "node bin/nodejs-dashboard.js -- node test/app/index.js",

Copy link
Member

Choose a reason for hiding this comment

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

@jasonwilson -- Can you comment here? The problem is that bin/nodejs-dashboard.js isn't a recognizable Windows cmd script.

I'm guessing we want:

node bin/nodejs-dashboard.js node test/app/index.js

but not totally sure...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cool, that's what I ended up with too!

var mock = function (path, obj) {
return mockRequire(process.cwd() + "/" + path, obj);
return mockRequire(normalize(process.cwd() + "/" + path), obj);
Copy link
Member

Choose a reason for hiding this comment

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

The existing string concat with "/" feels wrong.

Wouldn't

return mockRequire(path.resolve(path), obj);

solve all the problems we have here?

@mscottx88
Copy link
Contributor Author

@ryan-roemer I reverted the version bump and changed from normalize to resolve.

@mscottx88
Copy link
Contributor Author

Woohoo! I figured out how to get the screen to update without the forced option in showLayouts. All I needed was a lil bit of inversion of control. Turns out the BaseLineGraph needs to request the data, so when changing the zoom level, the higher classes provide a mapper function.

@jasonwilson
Copy link
Contributor

The units seem to be offset from whole intervals. Can we make these fixed?
screen shot 2017-07-25 at 4 39 43 pm

@mscottx88
Copy link
Contributor Author

Do you mean, keep them as seconds until everything is evenly divisible by minutes, and so on?

@mscottx88
Copy link
Contributor Author

It turns out that 7.3m = 438s, both of which take up the same space on the screen 🤣

@jasonwilson
Copy link
Contributor

I mean so the units are fixed, whole number increments. For example: 1m 5m 10m 15m 20m 25m

Time labels now appear like digital clocks.
@mscottx88
Copy link
Contributor Author

image

@mscottx88
Copy link
Contributor Author

I've got the new #67 ready to go, in a separate branch, but it relies on this one.

The memory guage view was not getting its "metrics" events and appears frozen.
Since it is not a historical graph, the "metrics" event needed to be emitted every time.
@mscottx88
Copy link
Contributor Author

@jasonwilson @aisapatino Hi there, I was just following up on this PR. I have a few more branches/features I'd like to merge after this one.

Copy link
Contributor

@jasonwilson jasonwilson left a comment

Choose a reason for hiding this comment

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

A couple small changes then we're good to go!

@@ -1,5 +1,8 @@
# Change log

## [Unreleased] - 2017-07-24
- **Added:** Longer history for graphs [\#64]
Copy link
Contributor

Choose a reason for hiding this comment

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

Need to include the PR reference at the bottom of the file.

@@ -1,25 +1,500 @@
"use strict";

/**
* This module provides metric data for various data points.
Copy link
Contributor

Choose a reason for hiding this comment

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

Lets put this writeup in a separate markdown file and abbreviate the explanation here.

@@ -71,6 +77,38 @@ BaseLineGraph.prototype.update = function (values) {
this.node.setData(_.values(this.series));
};

BaseLineGraph.prototype.changeMetricData = function (mapper) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Anyway to have blessed fix the increments?

};

sandbox.stub(process, "memoryUsage", function () {
return {
systemTotal: 20,
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

@mscottx88
Copy link
Contributor Author

@jasonwilson Corrected those, thanks for the recommendation on the separate MD. I was able to include some visuals which I really wanted to do anyway 👍

Copy link
Member

@ryan-roemer ryan-roemer left a comment

Choose a reason for hiding this comment

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

Nice work!

@jasonwilson
Copy link
Contributor

🚀

@jasonwilson jasonwilson merged commit 4ad9351 into FormidableLabs:master Aug 8, 2017
@mscottx88 mscottx88 deleted the features/graph-units-of-time branch August 8, 2017 18:16
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants