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

Add optional dynamic debug instances (react on enable() and disable() once created) #209

Closed
wants to merge 1 commit into from

Conversation

ibc
Copy link
Contributor

@ibc ibc commented Jul 2, 2015

First of all: this PR is 100% compliant with the current design and adds zero overhead to it. This is, no changes must be done in apps and libraries already using the debug module, and the performance is the same as before.

This PR adds "dynamic debug instances" which are created by passing true as the second parameter to the module exported function:

var debug = require('debug');
var applog = debug('myApp', true);

Those instances do properly react if debug.enable(xxxx) or debug.disable() is called after they are created.

An usage example is provided in the example/ folder.

The PR also resets exports.names and exports.skips when enable() or disable() is called (rationale here).

Related issues:

@ibc ibc changed the title Add optional dynamic debug instances which react on enable() and disable() Add optional dynamic debug instances (react on enable() and disable() one created) Jul 2, 2015
@ibc ibc changed the title Add optional dynamic debug instances (react on enable() and disable() one created) Add optional dynamic debug instances (react on enable() and disable() once created) Jul 2, 2015
@leftieFriele
Copy link

+1 on this PR, turning on / off on the fly would be great for browser applications

@ibc
Copy link
Contributor Author

ibc commented Aug 28, 2015

@TooTallNate any comment about this?

@bragma
Copy link

bragma commented Dec 9, 2015

+1 please merge this!

@wision
Copy link

wision commented Jan 6, 2016

@TooTallNate any chance of merging this feature?

@techjeffharris
Copy link

👍 Yes, please!

index--;
// Return a dynamic debug instance.
else {
function dynamic() {
Copy link
Contributor

Choose a reason for hiding this comment

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

-1 for all this copypasta

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What do you mean??

Copy link
Contributor

Choose a reason for hiding this comment

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

the dynamic function is nearly identical to the enabled function

Copy link
Contributor Author

@ibc ibc Mar 1, 2016

Choose a reason for hiding this comment

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

Right. We can talk about code optimization if the PR is at least considered by the author, which said nothing yet about it.

@roccomuso
Copy link

roccomuso commented May 17, 2016

Wouldn't it also be referred to #275 ?

@thebigredgeek
Copy link
Contributor

@TooTallNate thoughts here? Not sure if we want to go this direction with the API

@thebigredgeek thebigredgeek added discussion This issue is requesting comments and discussion change-major This proposes or provides a change that requires a major release feature This proposes or provides a feature or enhancement labels Nov 14, 2016
@thebigredgeek
Copy link
Contributor

#156

@thebigredgeek
Copy link
Contributor

thebigredgeek commented Nov 14, 2016

Referenced issue #326

@thebigredgeek thebigredgeek added this to the 3.0 milestone Nov 14, 2016
@thebigredgeek thebigredgeek changed the base branch from master to v3 November 15, 2016 16:37
@TooTallNate
Copy link
Contributor

A few comments:

  • I'm not a fan of the new API surface area. Why not all of them just be dynamic? And forget the ugly , true second argument to debug (boolean trap waiting to happen).
  • My PR in Node: configurable util.inspect() options #327 (specifically this commit f0e8a97) makes individual debug instances "hot-enableable" (that is, if you toggle the enabled flag on a debug instance it works as expected). Perhaps use that as a base instead of the "copy pasta".
  • You have to explicitly release dynamic debug instances otherwise exports.dynamics is a memory leak (plus it's an API, not change, but addition).

@TooTallNate
Copy link
Contributor

Honestly that last point is the main reason a feature like this is not in debug right now. I don't want to have to maintain a list of all the debug instances in memory, which just grows and grows as more modules are required.

@thebigredgeek
Copy link
Contributor

@TooTallNate agreed. Closing this for now.

@tehsenaus
Copy link

I don't see how this would cause a leak - the number of modules which can be require()'d is bounded, is it not?

@ibc
Copy link
Contributor Author

ibc commented Dec 20, 2016

I don't see how this would cause a leak - the number of modules which can be require()'d is bounded, is it not?

If you want to dynamicall enable/disable a debug instance you must store it somewhere. If you create tons of debug instances and never destroy them, they will in fact leak. Easy.

That's why in my PR I added a debug.release() method.

But, the current implementation of this module is too not handle debug instances. Instead they just exist while they are in the scope, and they are garbage collected if not like any variable.

@tehsenaus
Copy link

If you're creating debug instances on the fly and not releasing them, then sure. But is the library being used in that way? I'd bet 99.99% of cases users just require('debug')('blah:blah') at the top of their module. Then by the same logic, require() leaks memory!

This would be sooo useful for debugging in production, it seems a real shame to pass on for such an esoteric use case. If I were to wrap the library in userland, i'd only get the functionality for my application (not submodules like express).

@ibc
Copy link
Contributor Author

ibc commented Dec 20, 2016

If you're creating debug instances on the fly and not releasing them, then sure. But is the library being used in that way? I'd bet 99.99% of cases users just require('debug')('blah:blah') at the top of their module.

Sure. However sometimes I create dynamic debug instances in class constructors so their label include the id or whatever.

@tehsenaus
Copy link

That doesn't seem too efficient, it would be running lots of regex checks on your class instantiation?

Why not just log('%s: ...', this.id)?

@thebigredgeek
Copy link
Contributor

The reason this leaks is because internal state within the debug lib is required. If you call debug over and over in it's current state it simply returns a function. This PR requires it to keep an ever growing amount of bookkeeping. A lot of people create debug instances in class constructors as mentioned before. This would be a breaking change that would manifest itself as a server crash once ram filled up. I get that it's useful, but that doesn't necessarily mean it's doable. There are always tradeoffs

@ibc
Copy link
Contributor Author

ibc commented Dec 21, 2016

That doesn't seem too efficient, it would be running lots of regex checks on your class instantiation?

I agree, but that's up to the app developer.

This PR requires it to keep an ever growing amount of bookkeeping.

Not true. This PR does NOT change the current/default behavior. If the user wants manageable debug instances it must create them by passing true as second parameter:

var dyndebug = require('debug')('myApp', true);

I understand that such an API (passing just true as second argument) is not too cool, but you got the idea.

@tehsenaus
Copy link

require()s are synchronous, right? So if one were to enable bookkeeping initially on startup, then disable bookkeeping in a process.nextTick() (so dynamic debug instances would not be tracked), this would achieve the desired effect with no leaks.

Food for thought...?

@Othreumaru
Copy link

I would argue with the API for enabling that feature, but I would definitely love to see it in next major release, enabled by default.

@thebigredgeek
Copy link
Contributor

Check out the 3.0 conversation issue. It's something that will be added. However, I don't think we want to resort to hackery to make it work. We should probably just save enables/disabled state on a boolean within the factory closure as that won't leak

@tehsenaus
Copy link

I need this feature, so I created a module which enables it with no API changes:
https://github.com/tehsenaus/hot-debug

It patches the debug module, so any sub-dependencies of your project (e.g. express) will get the enable/disable functionality.

It'd be great to see this feature natively in debug v3!

@Yalhu
Copy link

Yalhu commented Apr 13, 2018

There are some questions that I use debug on Browser.

  1. Does debug.disable('debug:debug1') disable all the debug? On my test ,it was.
  2. Does debug.enable() must have a argument. If there is no argument, it will disable debug.
  3. If I disable debug on the script start up, on console debug.enable('debug:debug2') doesn't work. It will works again if I use debug.enable('debug:*'). (I use these API on chrome console).

steps

localStorage.setItem('debug','debug:*');
var d1=debug('debug:debug1');
var d2=debug('debug:debug2');
var d3=debug('debug:debug3');
debug.disable('debug:debug2'); // only debug2,but d1 not work
debug.enable('debug:debug1'); // debug1 not work
debug.enable('debug:debug3'); // only debug3 work
d1('test d1 ....');
d2('test d2 ...');
d3('test d3 ... ');

on chrome console:

  1. only d3 workde, d1 didn't work.
  2. do debug.enable('debug:debug1') d1('can work') worked.
  3. do debug.enable('debug:debug2') d2('can work') did not work.
  4. do debug.enable('debug:*') d2('can work') worked.
  5. do debug.enable() d1('can work') d2('can work') no debug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
change-major This proposes or provides a change that requires a major release discussion This issue is requesting comments and discussion feature This proposes or provides a feature or enhancement
Development

Successfully merging this pull request may close these issues.