DEV Community

François-Emmanuel CORTES
François-Emmanuel CORTES

Posted on

[At Run Time] Adaptative Log Function

When debugging some buge coding project, you want sometimes to drop a console.log() calls to track some varaible and errors, to figure out what is happening during program execution, especially nearby potential tricky sections of it; something like:

function danger (a: number, b: number) {
    console.log ('### (title "h3") the dangerous function is here...')

    try {
        return a / b
    } catch (err) {
        console.log ('posssible divisoion by zero !')
        console.log ({a, b })

        throw new Error ('#DIVIDE_BY_ZERO')
    }
}
Enter fullscreen mode Exit fullscreen mode

This approach gives you the ability to see the error at its location.

But the more code grows and the more logging calls occurrences grows together... and when comes And that produces time-consuming task to remove these calls (manually or not): lot of work in perpsective, and risks to waste time introducing some garbage (characters typos) and need to fix it again.

Logger class (first idea)

The idea for now is to add a Logger/Debugger class to filter console.log calls and shutdown its messages when the production phase comes.

function danger (a: number, b: number) {
    const debug = Debug.getInstance ()

    debug.level (3).title ('the dangerous function is here...')

    try {
        return a / b
    } catch (err) {
        debug.level (2).title ('posssible divisoion by zero !')
        debug.level (3).dump ({a, b })

        throw new Error ('#DIVIDE_BY_ZERO')
    }
}    
Enter fullscreen mode Exit fullscreen mode

Note: the singelton instance exposes a level method that returns a fluent interface, backed by some closure and bounding pattern, and wrap console.log calls:

// Debug class
protected verbosity = 0

protected log (effective: number, something) {
    if (this.verbosity < effective ) {
        // here we effectively log in the browser
        console.log (something)
    }
}

protected title (level: number, text: string) {
   const message = '#'.repat (level) + ' ' + text
   this.log (level, message)
}

protected dump (level: number,something) {
   this.log (level, something)
}

public level (wandered: number) {
    return {
        title: this.title.bind (this, this.verbosiry),
        dump: this.dump.bind (this, this.verbosiry),            
    }
}
Enter fullscreen mode Exit fullscreen mode

No it's OK logginh process is filterd properly. Adapt it now ?

Adaptative ? OK for now !

Declare a setter for thos.verbosity value:

// default behaviour:  shutdown all logs (silent)
public adapt (wantered: number = 0) {
    this.verbosity = wandered
}
Enter fullscreen mode Exit fullscreen mode

USE CASE: dangerous functions

  • Phase of self-tests of program: log enough stuff;
  • Phase Production: log normally and minimally (0: silently, when possible);
  • Increase drastrically verbosity just before throwing errors:
  • if error is catched properly at a higher level in call stack , adapt level to 0, to turn it off again !
    function danger (a: number, b: number) {
        const debug = Debug.getInstance ()

        debug.level (3).title ('the dangerous function is here...')

        try {
            return a / b
        } catch (err) {
            // now we have all errors log:
            debug.adapt (10)
            debug.level (2).title ('posssible divisoion by zero !')
            debug.level (3).dump ({a, b })

            throw new Error ('#DIVIDE_BY_ZERO')
        }
    }    

    function process (iterations: number) {
        const debug = Debug.getInstance ()

        for (let a = 0; a < iterations; a++) {
            for (let b = 0; b < iterations; b++) {}        
                // print all results
                // debug.level (0).dump (danger (a,b ))

                // or log anyway, print, do whatever with results...
                console.log (danger (an b))
            }
    }

    // *** caller code (main routine) ***
    const debug = Debug.getInstance ()       

    // self tests
    debug.adapt (1)
    process (1)    

    // produiuction phase: NO MPGS
    debug.adapt (0)
    process (1000 * 1000)    

Enter fullscreen mode Exit fullscreen mode

Doing like this, we adapt the logging mechanism to see clearly what is happening diring tests phase and after dangerous runtime error occurrence, the rest of (normal) run time we don't pollute the briwser's console anymore, neither altering performances anymore.

Happy coding !

Billboard image

Use Playwright to test. Use Playwright to monitor.

Join Vercel, CrowdStrike, and thousands of other teams that run end-to-end monitors on Checkly's programmable monitoring platform.

Get started now!

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Engage with a sea of insights in this enlightening article, highly esteemed within the encouraging DEV Community. Programmers of every skill level are invited to participate and enrich our shared knowledge.

A simple "thank you" can uplift someone's spirits. Express your appreciation in the comments section!

On DEV, sharing knowledge smooths our journey and strengthens our community bonds. Found this useful? A brief thank you to the author can mean a lot.

Okay