Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Debug API #3957

Merged
merged 8 commits into from
Dec 5, 2019
Merged

Debug API #3957

merged 8 commits into from
Dec 5, 2019

Conversation

Pessimistress
Copy link
Collaborator

An alternative approach of #3949

Change List

  • Pull all logging into a central location
  • Do not bundle the default logging functions in production mode
  • Allow logging functions to be loaded at runtime

@coveralls
Copy link

coveralls commented Dec 3, 2019

Coverage Status

Coverage decreased (-0.04%) to 83.708% when pulling 40d4c0e on x/debug-api into 9225d45 on master.

Copy link
Contributor

@tsherif tsherif left a comment

Choose a reason for hiding this comment

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

I really like the idea of a centralized "debug" object, and I'm wondering if this approach can be combined with the other one, i.e. remove any references to the debug object completely in production code. This could allow us to use it for more than removing logs, e.g.:

// Run an expensive assertion
deck.debug.run(() => {
    assert(gl.getError() === gl.OK, "No errors");
});
// Instrument a method.
deck.debug.run(() => {
    const oldDrawLayer = Layer.protototype.drawLayer;
    Layer.protototype.drawLayer = function (...args) {
		// Logging, profiling, etc.
        oldDrawLayer.apply(this, args);
        // More logging profiling, etc.
    };
});

@@ -36,6 +36,13 @@
- `PerspectiveView` class - use `FirstPersonView`
- `ThirdPersonView` class - use `MapView` (geospatial) or `OrbitView` (info-vis)

##### Debugging

Type `deck.debug(true)` in the console together with `deck.log.priority=<number>` to enable debug mode.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm thinking deck.debug(true) should set a minimum log priority to get logging so this can be done in one step (with the user having the option to set the priority higher). And maybe the log priority could be an optional second argument to deck.debug.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm thinking deck.debug(true) should set a minimum log priority to get logging

Agree that we should make this easy for user. This logging system has always had a discovery problem - how many deck.gl users are aware of it and able to leverage it?

For reference, the probe.gl Log.enable() etc returns this for chaining. deck.log.enable().setPriority(3) etc. It is a reasonable design, but the user needs to know that those methods exist.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

An easy solution to this is to set the default priority of deck.log to a non-zero number.

If we want to address this usability issue in probe.gl, I would set the priority default to 1. When log is disabled only priority=0 messages will pass through. Since enabled is default to false, the logging behavior will remain the same for most users who haven't messed with it.

Copy link
Collaborator

Choose a reason for hiding this comment

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

An easy solution to this is to set the default priority of deck.log to a non-zero number.

Yes. The system is probably not optimal. I would not be opposed to changes. They could be small as you suggest but here is some additional grist for the mill:

  • We have both enable and priority, maybe we don't need both? Initial probe.gl users (a long time ago) had concerns about perf impact when not in use, and the idea was that enable(false) would replace all methods with empty functions, not a bad idea though that feature generated surprising amounts of errors during probe.gl maintenance, not sure it was worth it.

Another question is whether enable/disable should affect log.warn and log.error as we now rely on those for non-debugging cases. If disable does not defeat those, it does not really so what it sounds like, and if it does, enable should probably be true by default as I assume we do want such messages...

Another criticism on the probe.gl API that was often raised: The term priority was considered very confusing since higher values are less likely to be logged. Most logging framework calls this value "log level", and it would make perfect sense to align with that convention.

@ibgreen
Copy link
Collaborator

ibgreen commented Dec 4, 2019

I really like the idea of a centralized "debug" object, and I'm wondering if this approach can be combined with the other one, i.e. remove any references to the debug object completely in production code. This could allow us to use it for more than removing logs, e.g.:

Yes it is a nice idea. In fact the pre-cursor version of probe.gl Log class (non-open-source) had exactly this method (used the same priority system as the log statements). It wasn't used much so it doesn't seem to have made it into the open source version, but certainly easy to add on either level.

modules/core/src/lib/attribute/attribute-manager.js Outdated Show resolved Hide resolved
modules/core/src/debug/index.js Outdated Show resolved Hide resolved
modules/core/src/lib/index.js Show resolved Hide resolved
@@ -363,13 +368,8 @@ export default class Layer extends Component {
}

if (name === 'all') {
log.log(LOG_PRIORITY_UPDATE, `updateTriggers invalidating all attributes: ${diffReason}`)();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Aren't these pretty important? Assuming they are covered somewhere else?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

They are covered in AttributeManager.

@@ -295,36 +291,3 @@ test('AttributeManager.invalidate', t => {

t.end();
});

test('AttributeManager.setDefaultLogFunctions', t => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Assume the new system should be nicely testable by injecting test assertions instead of log functions? Assume that can be improved especially if this becomes the foundation of a plugin system.

modules/core/src/debug/loggers.js Outdated Show resolved Hide resolved
@@ -36,6 +36,13 @@
- `PerspectiveView` class - use `FirstPersonView`
- `ThirdPersonView` class - use `MapView` (geospatial) or `OrbitView` (info-vis)

##### Debugging

Type `deck.debug(true)` in the console together with `deck.log.priority=<number>` to enable debug mode.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm thinking deck.debug(true) should set a minimum log priority to get logging

Agree that we should make this easy for user. This logging system has always had a discovery problem - how many deck.gl users are aware of it and able to leverage it?

For reference, the probe.gl Log.enable() etc returns this for chaining. deck.log.enable().setPriority(3) etc. It is a reasonable design, but the user needs to know that those methods exist.

Copy link
Collaborator

@ibgreen ibgreen left a comment

Choose a reason for hiding this comment

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

Absolutely delighted to see that you went ahead and did this exploration!

I was hoping (at best) that my running commentary on debug support would slightly alter the future trajectory of development, I did not expect that it could be implemented already in v8, this is much appreciated.

All comments are nits, no concerns:

I don't understand the require/import strategy here, but I am fine with any approach you choose. That said:

Some more comments especially around anyrequire statements would probably help as I consider use of require to be a slightly "hacky" and fragile part of the setup (e.g. I seem to recall mixing require and import caused pains for some bundlers and was to be avoided).

E.g. the comments say that logging is not bundled, but my sense is that require does not prevent bundling, it just prevents execution, which saves little. Maybe add a comment above this if statement explaining how the bundling config actually strips this file? - I don't seem to find it in this PR...

if (process.env.NODE_ENV !== 'production') {
  loggers = require('./loggers').getLoggers(log); // This does not stop webpack from bundling right?
}

And the below destructuring is pretty jarring to my eyes and raises questions every time I see it:

import debug from '../../debug';
const debugLog = debug.log;

FWIW, I was able to avoid such hacks in loaders.gl for conditionally bundled (node only) files using some techniques but they may not apply here.

modules/core/src/lib/composite-layer.js Outdated Show resolved Hide resolved
@Pessimistress
Copy link
Collaborator Author

Pessimistress commented Dec 4, 2019

my sense is that require does not prevent bundling, it just prevents execution

Correct, although it will be stripped during compression. This is the entry point of React:

if (process.env.NODE_ENV === 'production') {
  module.exports = require('./cjs/react.production.min.js');
} else {
  module.exports = require('./cjs/react.development.js');
}

I had some offline discussion with @tsherif. We will merge the debug utility into probe.gl's Log class:

  • It will allow us to get rid of the manual "syncing" of debug.enable and log.enable
  • In the core classes we'll call something like log.debug(eventType, ...) instead
  • It will allow us to optionally strip the debug calls using the babel plugin should we choose to do so

@ibgreen
Copy link
Collaborator

ibgreen commented Dec 4, 2019

Nice, moving this to probe.gl makes a lot sense if done in a generic and well-documented way.

Correct, although it will be stripped during compression. This is the entry point of React:

Got it. Long term perhaps it can be loaded dynamically when needed instead of always included and then stripped. (The loading just needs to survive page reloads to enable logging of startup code but that is just another reason to move the debug system to probe.gl which already manages that).

In the core classes we'll call something like log.debug(eventType, ...) instead

For my understanding log.warn and log.error will be unaffected right? This is not a wholesale unbundling of the log class in production, just the debug calls?

@Pessimistress Pessimistress merged commit 71e764d into master Dec 5, 2019
@Pessimistress Pessimistress deleted the x/debug-api branch December 5, 2019 20:59
@tgorkin tgorkin mentioned this pull request Dec 11, 2019
5 tasks
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.

4 participants