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

util.debuglog callback argument behavior and purpose appears to be documented incorrectly #56676

Open
GB609 opened this issue Jan 21, 2025 · 0 comments
Labels
doc Issues and PRs related to the documentations. util Issues and PRs related to the built-in util module.

Comments

@GB609
Copy link

GB609 commented Jan 21, 2025

Affected URL(s)

https://nodejs.org/docs/latest/api/util.html#utildebuglogsection-callback

Description of the problem

The usage example of the callback function for util.debuglog is not sufficiently documented imho.
Moreover, when looking at the code, it also seems to even work differently than described.

The example for the callback does the following:

const util = require('node:util');
let debuglog = util.debuglog('internals', (debug) => {
  // Replace with a logging function that optimizes out
  // testing if the section is enabled
  debuglog = debug;
});

What debuglog effectively does is:

function debuglog(set, cb){
  realLogFunction = (...args){
     init() //sets up the set name and an enabled boolean value

     // creates a noop function when enabled=false
     realLogFunction = debugLogImpl(enabled) 
     if(typeof cb == "function"){
       // this is the part where the documentation is lacking
       cb(realLogFunction) //code depends on side-effects of the callback?
     }
     // this line is only effective the very first time, when still in the factory
     // likely to not 'swallow' the first log line that lazily inits the real logger
     realLogFunction(...args)
  }

  //left out for brewity, but works on the same principle as realLogFunction
  let innerEnabledCheck ()=>{...}
  
  logDelegate = (...) => {
    //some switch on argument length, but effectively always results in the next line, with a varying
    //amount of arguments passed on.
    realLogFunction(args)
  }
  logDelegate.enabled = innerEnabledCheck() //left out for brewity
  return logDelegate;
}

The first time logDelegate is called, the enabled test is already optimized out and logDelegate will call the now-changed realLogFunction generated from debugLogImpl.
What actually happens when the callback is used as in the documentation's example, is that the outside variable, (debuglog in the example) which points to logDelegate, will be replaced by realLogFunction.

Thus, what is 'optimized out' is the switch in logDelegate when the callback is used as shown in the example, but at the price of also losing the enabled getter. 'Testing if the section is enabled' is always automatically and implicitly optimized out in the inner factory method.

@GB609 GB609 added the doc Issues and PRs related to the documentations. label Jan 21, 2025
@VoltrexKeyva VoltrexKeyva added the util Issues and PRs related to the built-in util module. label Jan 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
doc Issues and PRs related to the documentations. util Issues and PRs related to the built-in util module.
Projects
None yet
Development

No branches or pull requests

2 participants