सही लाइन नंबर के साथ कंसोल.लॉग के लिए एक उचित आवरण?


132

अब मैं एक एप्लिकेशन विकसित कर रहा हूं, और एक वैश्विक isDebugस्विच रखूंगा। मैं console.logअधिक सुविधाजनक उपयोग के लिए रैप करना चाहूंगा ।

//isDebug controls the entire site.
var isDebug = true;

//debug.js
function debug(msg, level){
    var Global = this;
    if(!(Global.isDebug && Global.console && Global.console.log)){
        return;
    }
    level = level||'info';
    Global.console.log(level + ': '+ msg);
}

//main.js
debug('Here is a msg.');

फिर मुझे यह परिणाम फ़ायरफ़ॉक्स कंसोल में मिलता है।

info: Here is a msg.                       debug.js (line 8)

क्या होगा यदि मैं लाइन नंबर के साथ लॉग इन करना चाहता हूं debug(), जहां कॉल किया जाता है, जैसे info: Here is a msg. main.js (line 2)?


आप एक आवरण समारोह के माध्यम से कुछ जोड़ने के बजाय console.log, जानकारी के लिए, console.warnचेतावनी के लिए और console.errorत्रुटि के लिए उपयोग कर सकते हैं console.log
एल्विन वोंग

2
@AlvinWong हाँ मुझे पता है कि, लेकिन समस्या यह है कि मुझे एक वैश्विक डिबग स्विच की आवश्यकता है, जो नियंत्रित करता है कि क्या consoleउपयोग करने की आवश्यकता है। ऐसे लक्ष्य को प्राप्त करने के लिए, एक आवरण ही एकमात्र तरीका लगता है?
रुफस

Google Chrome के लिए देखें stackoverflow.com/a/25729203/1429301 आपके मामले में पैटर्न डिबग होगा। js
अलेक्जेंडर

जवाबों:


117

यह एक पुराना प्रश्न है और प्रदान किए गए सभी उत्तर अत्यधिक हैकी हैं, MAJOR पार ब्राउज़र समस्याएँ हैं, और कुछ भी उपयोगी नहीं प्रदान करते हैं। यह समाधान हर ब्राउज़र में काम करता है और सभी कंसोल डेटा को ठीक उसी तरह रिपोर्ट करता है जैसे यह होना चाहिए। कोई हैक की आवश्यकता नहीं है और कोड की एक पंक्ति कोडपेन की जाँच करें

var debug = console.log.bind(window.console)

स्विच इस तरह बनाएँ:

isDebug = true // toggle this to turn on / off for global controll

if (isDebug) var debug = console.log.bind(window.console)
else var debug = function(){}

तो बस कॉल इस प्रकार है:

debug('This is happening.')

तुम भी इस तरह से एक स्विच के साथ कंसोल ले सकते हैं।

if (!isDebug) console.log = function(){}

यदि आप इसके साथ कुछ उपयोगी करना चाहते हैं .. आप सभी कंसोल विधियों को जोड़ सकते हैं और इसे पुन: प्रयोज्य फ़ंक्शन में लपेट सकते हैं जो न केवल वैश्विक नियंत्रण देता है, बल्कि वर्ग स्तर भी:

var Debugger = function(gState, klass) {

  this.debug = {}

  if (gState && klass.isDebug) {
    for (var m in console)
      if (typeof console[m] == 'function')
        this.debug[m] = console[m].bind(window.console, klass.toString()+": ")
  }else{
    for (var m in console)
      if (typeof console[m] == 'function')
        this.debug[m] = function(){}
  }
  return this.debug
}

isDebug = true //global debug state

debug = Debugger(isDebug, this)

debug.log('Hello log!')
debug.trace('Hello trace!')

अब आप इसे अपनी कक्षाओं में जोड़ सकते हैं:

var MyClass = function() {
  this.isDebug = true //local state
  this.debug = Debugger(isDebug, this)
  this.debug.warn('It works in classses')
}

16
अगर मैं गलत हूं तो मुझे सुधारें, लेकिन यह आपको किसी भी अतिरिक्त कार्यक्षमता को जोड़ने की अनुमति नहीं देता है, सही है? आप अनिवार्य रूप से केवल कंसोल ऑब्जेक्ट को अलियास कर रहे हैं? एक क्रूड उदाहरण - कंसोल के लिए कोई रास्ता नहीं है। () हर डीबग के लिए दो बार घटना ()?
एबी कैरोल

3
@ABCarroll दो कॉल वाले console.logकस्टम log()फ़ंक्शन को बाइंड करके आप दो बार कर सकते हैं console.log, हालांकि लाइन नंबर उस रेखा को प्रतिबिंबित करेंगे जो console.logवास्तव में रहता है, जहां नहीं debug.logकहा जाता है। हालाँकि, आप डायनामिक उपसर्ग / प्रत्यय इत्यादि जोड़ने जैसी बातें कर सकते थे .. लाइन नंबर के मुद्दे की भरपाई करने के भी तरीके हैं, लेकिन एक और सवाल मुझे लगता है। इस परियोजना को एक उदाहरण के लिए देखें: github.com/arctelix/iDebugConsole/blob/master/README.md
arctelix

2
यह विधि फ़ायरफ़ॉक्स संस्करण 47 से 49 तक समावेशी में काम नहीं करती है। और केवल 50.0a2 संस्करण में तय किया गया था। वैसे FF50 को 2 सप्ताह में रिलीज़ किया जाएगा, लेकिन मुझे यह महसूस करने में कई घंटे लगते हैं कि यह काम क्यों नहीं कर रहा है। इसलिए मुझे लगता है कि यह जानकारी किसी के लिए मददगार हो सकती है। संपर्क
व्लादिमीर Liubimov

मेरा मानना ​​है कि @ABCarroll का मतलब है कि उदाहरण के अंदर सब कुछ रनटाइम में उपयोग नहीं किया जा सकता है। एक और उदाहरण के लिए, वैश्विक राज्य को केवल तात्कालिकता में परिभाषित किया जा सकता है, इसलिए यदि आप बाद में बदलते this.isDebugहैंfalse , तो इससे कोई फर्क नहीं पड़ेगा। मुझे नहीं पता कि इसके आसपास कोई रास्ता है, शायद यह डिज़ाइन द्वारा है। इस अर्थ में, isDebugएक बहुत भ्रामक है varऔर constइसके बजाय होना चाहिए ।
Cregox

2
यह प्रश्न का उत्तर नहीं देता है "क्या होगा यदि मैं लाइन नंबर के साथ लॉग इन करना चाहता हूं जहां डिबग () कहा जाता है?"
technomage

24

मुझे @ fredrik का उत्तर पसंद आया , इसलिए मैंने इसे एक और उत्तर के साथ रोल किया, जो वेबकिट स्टैकट्रेस को विभाजित करता है , और इसे @ PaulIrish के सुरक्षित कंसोल.लॉग रैपर के साथ विलय कर दिया । "मानकीकृत"filename:line एक "विशेष वस्तु" के लिए तो यह बाहर खड़ा है और ज्यादातर एफएफ और क्रोम में समान दिखता है।

परीक्षण में परीक्षण: http://jsfiddle.net/drzaus/pWe6W/

_log = (function (undefined) {
    var Log = Error; // does this do anything?  proper inheritance...?
    Log.prototype.write = function (args) {
        /// <summary>
        /// Paulirish-like console.log wrapper.  Includes stack trace via @fredrik SO suggestion (see remarks for sources).
        /// </summary>
        /// <param name="args" type="Array">list of details to log, as provided by `arguments`</param>
        /// <remarks>Includes line numbers by calling Error object -- see
        /// * http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
        /// * /programming/13815640/a-proper-wrapper-for-console-log-with-correct-line-number
        /// * https://stackoverflow.com/a/3806596/1037948
        /// </remarks>

        // via @fredrik SO trace suggestion; wrapping in special construct so it stands out
        var suffix = {
            "@": (this.lineNumber
                    ? this.fileName + ':' + this.lineNumber + ":1" // add arbitrary column value for chrome linking
                    : extractLineNumberFromStack(this.stack)
            )
        };

        args = args.concat([suffix]);
        // via @paulirish console wrapper
        if (console && console.log) {
            if (console.log.apply) { console.log.apply(console, args); } else { console.log(args); } // nicer display in some browsers
        }
    };
    var extractLineNumberFromStack = function (stack) {
        /// <summary>
        /// Get the line/filename detail from a Webkit stack trace.  See https://stackoverflow.com/a/3806596/1037948
        /// </summary>
        /// <param name="stack" type="String">the stack string</param>

        if(!stack) return '?'; // fix undefined issue reported by @sigod

        // correct line number according to how Log().write implemented
        var line = stack.split('\n')[2];
        // fix for various display text
        line = (line.indexOf(' (') >= 0
            ? line.split(' (')[1].substring(0, line.length - 1)
            : line.split('at ')[1]
            );
        return line;
    };

    return function (params) {
        /// <summary>
        /// Paulirish-like console.log wrapper
        /// </summary>
        /// <param name="params" type="[...]">list your logging parameters</param>

        // only if explicitly true somewhere
        if (typeof DEBUGMODE === typeof undefined || !DEBUGMODE) return;

        // call handler extension which provides stack trace
        Log().write(Array.prototype.slice.call(arguments, 0)); // turn into proper array
    };//--  fn  returned

})();//--- _log

यह भी नोड में काम करता है, और आप इसके साथ परीक्षण कर सकते हैं:

// no debug mode
_log('this should not appear');

// turn it on
DEBUGMODE = true;

_log('you should', 'see this', {a:1, b:2, c:3});
console.log('--- regular log ---');
_log('you should', 'also see this', {a:4, b:8, c:16});

// turn it off
DEBUGMODE = false;

_log('disabled, should not appear');
console.log('--- regular log2 ---');

अतिरिक्त consoleतरीकों जैसे आदि warn, के लिए खाते के लिए थोड़ा और अधिक उन्नत उत्तर error- stackoverflow.com/a/14842659/1037948
drzaus

1
var line = stack.split('\n')[2];-'undefined' is not an object
sigod

@ सिगोड - शायद या तो ब्राउज़र पर निर्भर करता है, या कि मैंने इसे 2 साल पहले लिखा था और ब्राउज़र बदल गया है। आपका परिदृश्य क्या है?
ढोलकिया

1
मेरे एक सहकर्मी ने आपके कोड को हमारे प्रोजेक्ट में कॉपी-पेस्ट कर दिया। यह IE11 और सफारी 5 में साइट को तोड़ दिया। इस ब्राउज़र के अन्य संस्करणों के बारे में निश्चित नहीं है। शायद आप भविष्य के कॉपी-पास्टर्स के लिए एक चेक जोड़ देंगे?
सिगोड

1
@ सिगोड अब क्या है? if(!stack) return '?'उस विधि में जोड़ा गया जो विफल हो जाती है, बजाय इसके कि इसे कहाँ बुलाया जाता है (इसलिए यदि कोई इस पद्धति का उपयोग स्वयं करता है तो वे "संरक्षित" भी हैं)
drzaus

18

आप लाइन नंबरों को बनाए रख सकते हैं और लॉग स्तर को कुछ चतुर उपयोग के साथ आउटपुट कर सकते हैं Function.prototype.bind:

function setDebug(isDebug) {
  if (window.isDebug) {
    window.debug = window.console.log.bind(window.console, '%s: %s');
  } else {
    window.debug = function() {};
  }
}

setDebug(true);

// ...

debug('level', 'This is my message.'); // --> level: This is my message. (line X)

इसे एक कदम आगे बढ़ाते हुए, आप console's त्रुटि / चेतावनी / सूचना के अंतर का उपयोग कर सकते हैं और अभी भी कस्टम स्तर हैं। कोशिश करो!

function setDebug(isDebug) {
  if (isDebug) {
    window.debug = {
      log: window.console.log.bind(window.console, '%s: %s'),
      error: window.console.error.bind(window.console, 'error: %s'),
      info: window.console.info.bind(window.console, 'info: %s'),
      warn: window.console.warn.bind(window.console, 'warn: %s')
    };
  } else {
    var __no_op = function() {};

    window.debug = {
      log: __no_op,
      error: __no_op,
      warn: __no_op,
      info: __no_op
    }
  }
}

setDebug(true);

// ...

debug.log('wat', 'Yay custom levels.'); // -> wat: Yay custom levels.    (line X)
debug.info('This is info.');            // -> info: This is info.        (line Y)
debug.error('Bad stuff happened.');     // -> error: Bad stuff happened. (line Z)

1
मैं अपने आप से उत्पादन उपसर्ग के लिए थोड़ी देर के लिए कोशिश कर रहा है अब console.debug(...)के साथ function nameऔर argumentsहै कि कैसे करना है पर कोई विचार -
डैनियल सोकोलोस्की

3
मैं कंसोल रैपर / शिमेस / आदि की भीड़ को देख रहा हूं। और यह पहली बार है जो मैंने पार किया है जो आउटपुट को कस्टमाइज़ करने के साथ लाइन नंबरों को संरक्षित करता है। यह इस तथ्य का एक चतुर उपयोग है कि .bind आपके लिए कुछ करी भी करता है, आप संदर्भ के अलावा एक या अधिक तर्क बाँध सकते हैं । आप इसे एक कदम आगे ले जा सकते हैं और इसे एक .opString विधि के साथ एक noop फ़ंक्शन पास कर सकते हैं जो लॉग विधि कहे जाने पर कोड चला सकता है! देखें इस jsfiddle
सैम Hasler

2
हो सकता है कि सभी ब्राउज़रों में नहीं (इसे देखा नहीं गया), लेकिन क्रोम के %sसाथ की जगह %oमापदंडों को प्रिंट करेगा जिस तरह से आप उम्मीद करेंगे (ऑब्जेक्ट विस्तार योग्य हैं, संख्या और तार रंगीन हैं, आदि)।
अनसन

इस समाधान को प्यार करो। मैंने कुछ बदलाव किए, जो मेरे आवेदन के लिए बेहतर काम करते हैं, लेकिन अभी भी यह बरकरार है और खूबसूरती से चल रहा है। साभार
वार्ड

9

से: जावास्क्रिप्ट कॉलर फ़ंक्शन लाइन नंबर कैसे प्राप्त करें? जावास्क्रिप्ट कॉलर स्रोत URL कैसे प्राप्त करें? Errorवस्तु एक लाइन नंबर संपत्ति (एफएफ में) है। तो कुछ इस तरह काम करना चाहिए:

var err = new Error();
Global.console.log(level + ': '+ msg + 'file: ' + err.fileName + ' line:' + err.lineNumber);

वेबकिट ब्राउज़र में आपके पास err.stackवह तार है जो वर्तमान कॉल स्टैक का प्रतिनिधित्व करता है। यह वर्तमान लाइन नंबर और अधिक जानकारी प्रदर्शित करेगा।

अपडेट करें

सही लिनेनंबर प्राप्त करने के लिए आपको उस लाइन पर त्रुटि को आमंत्रित करना होगा। कुछ इस तरह:

var Log = Error;
Log.prototype.write = function () {
    var args = Array.prototype.slice.call(arguments, 0),
        suffix = this.lineNumber ? 'line: '  + this.lineNumber : 'stack: ' + this.stack;

    console.log.apply(console, args.concat([suffix]));
};

var a = Log().write('monkey' + 1, 'test: ' + 2);

var b = Log().write('hello' + 3, 'test: ' + 4);

1
new Error();मुझे वह संदर्भ देता है, जहां वह क्रियान्वित होता है, अगर मैं इसे लागू करता हूं debug.js, तो मुझे मिलेगा info: Here is a msg. file: http://localhost/js/debug.js line:7
रुफस

1
किस बात का Log = Error? आप अभी भी त्रुटि वर्ग को संशोधित कर रहे हैं, है ना?
drzaus

अपने उत्तर को कुछ और लोगों के साथ
मिलाएं

8

लाइन नंबर रखने के लिए एक तरह से यहाँ है: https://gist.github.com/bgrins/5108712 । यह कम या ज्यादा उबालता है:

if (Function.prototype.bind) {
    window.log = Function.prototype.bind.call(console.log, console);
}
else {
    window.log = function() { 
        Function.prototype.apply.call(console.log, console, arguments);
    };
}

यदि आप डिबगिंग नहीं कर रहे हैं, तो आप इसे लपेट सकते हैं isDebugऔर सेट window.logकर function() { }सकते हैं।


7

आप अपनी डिबग विधि के लिए लाइन नंबर पास कर सकते हैं, जैसे:

//main.js
debug('Here is a msg.', (new Error).lineNumber);

यहां, (new Error).lineNumberआपको अपने javascriptकोड में वर्तमान लाइन नंबर देना होगा ।


2
एक छोटी सी क्रिया, है ना?
रुफस

2
मुझे लगता है कि यह आपके प्रश्न का उत्तर देने के लिए पर्याप्त है। :)
सुबोध

1
लाइननंबर प्रॉपर्टी गैर-मानक है, और अभी फायरफॉक्स पर काम करती है, यहाँ
Matthias

6

Chrome Devtools आपको ब्लैकबॉक्सिंग के साथ इसे प्राप्त करने देता है । आप कंसोल.लॉग रैपर बना सकते हैं जिसके साइड इफेक्ट्स हो सकते हैं, अन्य कार्यों को बुला सकते हैं, आदि, और फिर भी रैपर फ़ंक्शन नामक लाइन संख्या को बनाए रख सकते हैं।

बस एक अलग फ़ाइल में एक छोटा सा कंसोल.लॉपर डालें, जैसे

(function() {
    var consolelog = console.log
    console.log = function() {
        // you may do something with side effects here.
        // log to a remote server, whatever you want. here
        // for example we append the log message to the DOM
        var p = document.createElement('p')
        var args = Array.prototype.slice.apply(arguments)
        p.innerText = JSON.stringify(args)
        document.body.appendChild(p)

        // call the original console.log function
        consolelog.apply(console,arguments)
    }
})()

इसे लॉग-ब्लैकबॉक्स.जेएस की तरह नाम दें

फिर क्रोम देवटूल सेटिंग्स पर जाएं और "ब्लैकबॉक्सिंग" अनुभाग ढूंढें, उस फ़ाइलनाम के लिए एक पैटर्न जोड़ें, जिसे आप ब्लैकबॉक्स करना चाहते हैं, इस मामले में लॉग-ब्लैकबॉक्स। js


नोट: सुनिश्चित करें कि आपके पास कोई कोड नहीं है जिसे आप उसी फ़ाइल में स्टैक ट्रेस में दिखाना चाहेंगे , क्योंकि यह ट्रेस से भी हटा दिया जाएगा।
जैमथॉवेलेल

6

मुझे वास्तव में लॉग इन करने के लिए कुछ बाहरी तर्क के साथ स्वीकार किए गए उत्तर (कंसोल के लिए बाध्यकारी / त्रुटि / आदि) को संयोजित करने के लिए एक सरल समाधान मिला।

// or window.log = {...}
var log = {
  ASSERT: 1, ERROR: 2, WARN: 3, INFO: 4, DEBUG: 5, VERBOSE: 6,
  set level(level) {
    if (level >= this.ASSERT) this.a = console.assert.bind(window.console);
    else this.a = function() {};
    if (level >= this.ERROR) this.e = console.error.bind(window.console);
    else this.e = function() {};
    if (level >= this.WARN) this.w = console.warn.bind(window.console);
    else this.w = function() {};
    if (level >= this.INFO) this.i = console.info.bind(window.console);
    else this.i = function() {};
    if (level >= this.DEBUG) this.d = console.debug.bind(window.console);
    else this.d = function() {};
    if (level >= this.VERBOSE) this.v = console.log.bind(window.console);
    else this.v = function() {};
    this.loggingLevel = level;
  },
  get level() { return this.loggingLevel; }
};
log.level = log.DEBUG;

उपयोग:

log.e('Error doing the thing!', e); // console.error
log.w('Bonus feature failed to load.'); // console.warn
log.i('Signed in.'); // console.info
log.d('Is this working as expected?'); // console.debug
log.v('Old debug messages, output dominating messages'); // console.log; ignored because `log.level` is set to `DEBUG`
log.a(someVar == 2) // console.assert
  • ध्यान दें कि console.assertसशर्त लॉगिंग का उपयोग करता है।
  • सुनिश्चित करें कि आपके ब्राउज़र के देव उपकरण सभी संदेश स्तरों को दिखाते हैं!

क्योंकि यह लॉग स्तर दिखाने वाले किसी भी लाइन नंबर और न ही काम करने वाले उदाहरण नहीं देता है।
'14:00

लाइन नंबर वैसा ही होगा जैसे कि कंसोल को सीधे इस्तेमाल करते हैं। मैंने उपयोग उदाहरणों के साथ उत्तर को अपडेट किया। इसके पास कई वोट नहीं हैं क्योंकि मैंने दो साल बाद इसका जवाब दिया :)
जैकब फिलिप्स

4

यदि आप केवल यह नियंत्रित करना चाहते हैं कि क्या डिबग का उपयोग किया गया है और सही लाइन नंबर है, तो आप इसके बजाय ऐसा कर सकते हैं:

if(isDebug && window.console && console.log && console.warn && console.error){
    window.debug = {
        'log': window.console.log,
        'warn': window.console.warn,
        'error': window.console.error
    };
}else{
    window.debug = {
        'log': function(){},
        'warn': function(){},
        'error': function(){}
    };
}

जब आपको डीबग करने की आवश्यकता होती है, तो आप यह कर सकते हैं:

debug.log("log");
debug.warn("warn");
debug.error("error");

यदि isDebug == true, कंसोल में दिखाए गए लाइन नंबर और फ़ाइल नाम सही होंगे, क्योंकि debug.logआदि वास्तव में एक उपनाम हैconsole.log

यदि isDebug == false, कोई डिबग संदेश नहीं दिखाया गया है, क्योंकि debug.logआदि केवल कुछ नहीं करता है (एक खाली फ़ंक्शन)।

जैसा कि आप पहले से ही जानते हैं, एक रैपर फ़ंक्शन लाइन नंबर और फ़ाइल नाम को गड़बड़ कर देगा, इसलिए यह रैपर फ़ंक्शन का उपयोग करने से रोकने के लिए एक अच्छा विचार है।


महान, मुझे isDebug = trueऔर के आदेश के बारे में सावधान रहने की जरूरत है debug.js, लेकिन यह जवाब काम करता है!
रुफस

3
window.debug = window.consoleथोड़ा क्लीनर होगा।
फ्रेड्रिक

@fredrik तो मुझे सभी सदस्य कार्यों को "कार्यान्वित" करना होगा isDebug == false। : {
एल्विन वोंग

@AlvinWong मैं सिर्फ अगर के लिए menat isDebug===true। या इसके लिए घटना: jsfiddle.net/fredrik/x6Jw5
fredrik

4

स्टैक ट्रेस समाधान लाइन नंबर प्रदर्शित करते हैं लेकिन स्रोत पर जाने के लिए क्लिक करने की अनुमति नहीं देते हैं, जो एक बड़ी समस्या है। इस व्यवहार को बनाए रखने का एकमात्र समाधान मूल कार्य से जुड़ना है।

बाइंडिंग मध्यवर्ती तर्क को शामिल करने से रोकता है, क्योंकि यह तर्क लाइन नंबरों के साथ गड़बड़ करेगा। हालांकि, बाध्य कार्यों को फिर से परिभाषित करके और कंसोल स्ट्रिंग प्रतिस्थापन के साथ खेलकर , कुछ अतिरिक्त व्यवहार अभी भी संभव है।

यह जस्ते एक न्यूनतम लॉजिंग रूपरेखा दिखाता है जो 34 लाइनों में मॉड्यूल, लॉग स्तर, स्वरूपण और उचित क्लिक करने योग्य लाइन नंबर प्रदान करता है। इसे अपनी आवश्यकताओं के लिए एक आधार या प्रेरणा के रूप में उपयोग करें।

var log = Logger.get("module").level(Logger.WARN);
log.error("An error has occured", errorObject);
log("Always show this.");

संपादित करें: नीचे दिए गए शामिल हैं

/*
 * Copyright 2016, Matthieu Dumas
 * This work is licensed under the Creative Commons Attribution 4.0 International License.
 * To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/
 */

/* Usage : 
 * var log = Logger.get("myModule") // .level(Logger.ALL) implicit
 * log.info("always a string as first argument", then, other, stuff)
 * log.level(Logger.WARN) // or ALL, DEBUG, INFO, WARN, ERROR, OFF
 * log.debug("does not show")
 * log("but this does because direct call on logger is not filtered by level")
 */
var Logger = (function() {
    var levels = {
        ALL:100,
        DEBUG:100,
        INFO:200,
        WARN:300,
        ERROR:400,
        OFF:500
    };
    var loggerCache = {};
    var cons = window.console;
    var noop = function() {};
    var level = function(level) {
        this.error = level<=levels.ERROR ? cons.error.bind(cons, "["+this.id+"] - ERROR - %s") : noop;
        this.warn = level<=levels.WARN ? cons.warn.bind(cons, "["+this.id+"] - WARN - %s") : noop;
        this.info = level<=levels.INFO ? cons.info.bind(cons, "["+this.id+"] - INFO - %s") : noop;
        this.debug = level<=levels.DEBUG ? cons.log.bind(cons, "["+this.id+"] - DEBUG - %s") : noop;
        this.log = cons.log.bind(cons, "["+this.id+"] %s");
        return this;
    };
    levels.get = function(id) {
        var res = loggerCache[id];
        if (!res) {
            var ctx = {id:id,level:level}; // create a context
            ctx.level(Logger.ALL); // apply level
            res = ctx.log; // extract the log function, copy context to it and returns it
            for (var prop in ctx)
                res[prop] = ctx[prop];
            loggerCache[id] = res;
        }
        return res;
    };
    return levels; // return levels augmented with "get"
})();


इस उत्तर में केवल 3 अपवोट हैं, लेकिन पेज में किसी भी अन्य की तुलना में अविश्वसनीय रूप से अधिक समृद्ध और साफ है
टॉम

हालाँकि, ऐसा लगता है कि सभी उपयोगी हिस्से बाहरी गिल्ट पर हैं।
रायन द लीच

3

बाइंड वाला विचार Function.prototype.bindशानदार है। आप npm लाइब्रेरी लाइन्स-लॉगर का भी उपयोग कर सकते हैं । यह मूल स्रोत फ़ाइलें दिखाता है:

अपनी परियोजना में एक बार किसी को भी लकड़हारा बनाएँ:

var LoggerFactory = require('lines-logger').LoggerFactory;
var loggerFactory = new LoggerFactory();
var logger = loggerFactory.getLoggerColor('global', '#753e01');

प्रिंट लॉग:

logger.log('Hello world!')();

यहाँ छवि विवरण दर्ज करें


2

consoleफ़ाइल का नाम और लाइन नंबर या आउटपुट पर अन्य स्टैक ट्रेस जानकारी जोड़ते समय अपने मौजूदा लॉगिंग स्टेटमेंट को रखने का एक तरीका है :

(function () {
  'use strict';
  var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
  var isChrome = !!window.chrome && !!window.chrome.webstore;
  var isIE = /*@cc_on!@*/false || !!document.documentMode;
  var isEdge = !isIE && !!window.StyleMedia;
  var isPhantom = (/PhantomJS/).test(navigator.userAgent);
  Object.defineProperties(console, ['log', 'info', 'warn', 'error'].reduce(function (props, method) {
    var _consoleMethod = console[method].bind(console);
    props[method] = {
      value: function MyError () {
        var stackPos = isOpera || isChrome ? 2 : 1;
        var err = new Error();
        if (isIE || isEdge || isPhantom) { // Untested in Edge
          try { // Stack not yet defined until thrown per https://docs.microsoft.com/en-us/scripting/javascript/reference/stack-property-error-javascript
            throw err;
          } catch (e) {
            err = e;
          }
          stackPos = isPhantom ? 1 : 2;
        }

        var a = arguments;
        if (err.stack) {
          var st = err.stack.split('\n')[stackPos]; // We could utilize the whole stack after the 0th index
          var argEnd = a.length - 1;
          [].slice.call(a).reverse().some(function(arg, i) {
            var pos = argEnd - i;
            if (typeof a[pos] !== 'string') {
              return false;
            }
            if (typeof a[0] === 'string' && a[0].indexOf('%') > -1) { pos = 0 } // If formatting
            a[pos] += ' \u00a0 (' + st.slice(0, st.lastIndexOf(':')) // Strip out character count
              .slice(st.lastIndexOf('/') + 1) + ')'; // Leave only path and line (which also avoids ":" changing Safari console formatting)
            return true;
          });
        }
        return _consoleMethod.apply(null, a);
      }
    };
    return props;
  }, {}));
}());

फिर इसे इस तरह उपयोग करें:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <script src="console-log.js"></script>
</head>
<body>
  <script>
  function a () {
    console.log('xyz'); // xyz   (console-log.html:10)
  }
  console.info('abc'); // abc   (console-log.html:12)
  console.log('%cdef', "color:red;"); // (IN RED:) // def   (console-log.html:13)
  a();
  console.warn('uuu'); // uuu   (console-log.html:15)
  console.error('yyy'); // yyy   (console-log.html:16)
  </script>
</body>
</html>

यह फ़ायरफ़ॉक्स, ओपेरा, सफारी, क्रोम और IE 10 में काम करता है (अभी तक IE11 या एज पर परीक्षण नहीं किया गया है)।


अच्छा काम है, लेकिन अभी भी 100% मुझे क्या चाहिए। मैं कंसोल-व्यू के दाईं ओर फ़ाइल-नाम और लाइन-नंबर जानकारी रखना चाहता हूं, जहां स्रोत को खोलने के लिए इसे क्लिक किया जा सकता है। यह समाधान संदेश के भाग (जैसे:) के रूप में सूचना को दिखाता है my test log message (myscript.js:42) VM167 mypage.html:15, जो पढ़ने में उतना अच्छा नहीं है जितना कि यह जुड़ा हुआ नहीं है। फिर भी अच्छा काम इस प्रकार एक उत्थान है।
फ्रेडरिक लीटनबर्गर

हाँ, जबकि वह आदर्श होगा, कोई रास्ता नहीं है, AFAIK, कंसोल में दिखाई देने वाले फ़ाइलनाम लिंक को खराब करने के लिए ...
ब्रेट ज़मीर

@BrettZamir ने इस कोड के बारे में एक सवाल यहां पोस्ट किया: stackoverflow.com/questions/52618368/…
Mahks

1
//isDebug controls the entire site.
var isDebug = true;

//debug.js
function debug(msg, level){
    var Global = this;
    if(!(Global.isDebug && Global.console && Global.console.log)){
        return;
    }
    level = level||'info';
    return 'console.log(\'' + level + ': '+ JSON.stringify(msg) + '\')';
}

//main.js
eval(debug('Here is a msg.'));

यह मुझे देगा info: "Here is a msg." main.js(line:2)

लेकिन अतिरिक्त evalकी जरूरत है, दया।


2
ईविल बुराई है! तो हर बुराई।
फ्रेड्रिक

1

Http://www.briangrinstead.com/blog/console-log-helper-function से कोड :

// Full version of `log` that:
//  * Prevents errors on console methods when no console present.
//  * Exposes a global 'log' function that preserves line numbering and formatting.
(function () {
  var method;
  var noop = function () { };
  var methods = [
      'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
      'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
      'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
      'timeStamp', 'trace', 'warn'
  ];
  var length = methods.length;
  var console = (window.console = window.console || {});

  while (length--) {
    method = methods[length];

    // Only stub undefined methods.
    if (!console[method]) {
        console[method] = noop;
    }
  }


  if (Function.prototype.bind) {
    window.log = Function.prototype.bind.call(console.log, console);
  }
  else {
    window.log = function() { 
      Function.prototype.apply.call(console.log, console, arguments);
    };
  }
})();

var a = {b:1};
var d = "test";
log(a, d);

यह मूल पंक्ति संख्या को दिखाने के लिए प्रकट नहीं होता है जहां logसे कहा जाता है
ragamufin

मुझे यकीन है कि जब मैंने परीक्षण किया तो यह काम कर रहा था, लेकिन मैंने उसी पृष्ठ से "पूर्ण" संस्करण के साथ कोड को बदल दिया। कम से कम क्रोम 45 में काम किया।
तिमो क्वाकोनन

समझ लिया। परिवर्तनों के साथ अब आपके पास अनिवार्य रूप से कुछ अन्य उत्तरों और कार्यों के समान है। मैं आपके पिछले कोड के बारे में उत्सुक था क्योंकि आपके पास अंत में एक ऐसा आवेदन था जिसने मेरे लिए और अधिक उपयोग करने के लिए दिलचस्प संभावनाएं खड़ी कीं, लेकिन चूंकि यह लाइन नंबर I को वर्ग एक में वापस नहीं दिखा था। हालांकि धन्यवाद!
रागमुफिन

1

मैं इस मुद्दे को हाल ही में देख रहा हूं। लॉगिंग को नियंत्रित करने के लिए बहुत सीधे कुछ की जरूरत है, लेकिन लाइन संख्या को बनाए रखने के लिए भी। मेरा समाधान कोड में उतना सुंदर नहीं लग रहा है, लेकिन यह प्रदान करता है कि मेरे लिए क्या आवश्यक है। यदि कोई बंद करने और बनाए रखने के साथ पर्याप्त सावधान है।

मैंने एप्लिकेशन की शुरुआत में एक छोटा आवरण जोड़ा है:

window.log = {
    log_level: 5,
    d: function (level, cb) {
        if (level < this.log_level) {
            cb();
        }
    }
};

ताकि बाद में मैं बस कर सकूं:

log.d(3, function(){console.log("file loaded: utils.js");});

मैंने इसे फ़ायरफ़ॉक्स और क्रोम का परीक्षण किया है, और दोनों ब्राउज़र्स कंसोल लॉग को उद्देश्य के रूप में दिखाते हैं। यदि आप ऐसा भरते हैं, तो आप हमेशा 'd' विधि का विस्तार कर सकते हैं और इसके लिए अन्य मापदंडों को पास कर सकते हैं, ताकि यह कुछ अतिरिक्त लॉगिंग कर सके।

लॉगिंग के लिए कोड में बदसूरत लाइन को छोड़कर, अभी तक मेरे दृष्टिकोण के लिए कोई गंभीर कमियां नहीं मिली हैं।


1

window.line = function () {
    var error = new Error(''),
        brower = {
            ie: !-[1,], // !!window.ActiveXObject || "ActiveXObject" in window
            opera: ~window.navigator.userAgent.indexOf("Opera"),
            firefox: ~window.navigator.userAgent.indexOf("Firefox"),
            chrome: ~window.navigator.userAgent.indexOf("Chrome"),
            safari: ~window.navigator.userAgent.indexOf("Safari"), // /^((?!chrome).)*safari/i.test(navigator.userAgent)?
        },
        todo = function () {
            // TODO: 
            console.error('a new island was found, please told the line()\'s author(roastwind)');        
        },
        line = (function(error, origin){
            // line, column, sourceURL
            if(error.stack){
                var line,
                    baseStr = '',
                    stacks = error.stack.split('\n');
                    stackLength = stacks.length,
                    isSupport = false;
                // mac版本chrome(55.0.2883.95 (64-bit))
                if(stackLength == 11 || brower.chrome){
                    line = stacks[3];
                    isSupport = true;
                // mac版本safari(10.0.1 (12602.2.14.0.7))
                }else if(brower.safari){
                    line = stacks[2];
                    isSupport = true;
                }else{
                    todo();
                }
                if(isSupport){
                    line = ~line.indexOf(origin) ? line.replace(origin, '') : line;
                    line = ~line.indexOf('/') ? line.substring(line.indexOf('/')+1, line.lastIndexOf(':')) : line;
                }
                return line;
            }else{
                todo();
            }
            return '😭';
        })(error, window.location.origin);
    return line;
}
window.log = function () {
    var _line = window.line.apply(arguments.callee.caller),
        args = Array.prototype.slice.call(arguments, 0).concat(['\t\t\t@'+_line]);
    window.console.log.apply(window.console, args);
}
log('hello');

यहाँ इस सवाल के बारे में मेरा समाधान था। जब आप विधि कहते हैं: लॉग करें, तो यह उस पंक्ति संख्या को प्रिंट करेगा जहां आप अपना लॉग प्रिंट करते हैं


1

डिबग करने के लिए थोड़ी भिन्नता एक फ़ंक्शन को वापस करना है, जिसे तब निष्पादित किया जाता है जहां आपको इसकी आवश्यकता होती है - डिबग (संदेश) (); और ठीक से कंसोल विंडो में सही लाइन नंबर और कॉलिंग स्क्रिप्ट दिखाता है, जबकि अलर्ट के रूप में रीडायरेक्ट करने, या फ़ाइल को सहेजने जैसे बदलावों की अनुमति देता है।

var debugmode='console';
var debugloglevel=3;

function debug(msg, type, level) {

  if(level && level>=debugloglevel) {
    return(function() {});
  }

  switch(debugmode) {
    case 'alert':
      return(alert.bind(window, type+": "+msg));
    break;
    case 'console':
      return(console.log.bind(window.console, type+": "+msg));
    break;
    default:
      return (function() {});
  }

}

चूंकि यह एक फ़ंक्शन देता है, उस फ़ंक्शन को डिबग लाइन पर () के साथ निष्पादित किया जाना चाहिए; दूसरे, संदेश को डिबग फ़ंक्शन में भेजा जाता है, बजाय लौटाए गए फ़ंक्शन के बजाय प्री-प्रोसेसिंग या जाँच की अनुमति देता है, जैसे कि आपको आवश्यकता हो सकती है, जैसे लॉग-लेवल स्टेट की जाँच करना, संदेश को अधिक पठनीय बनाना, विभिन्न प्रकारों को छोड़ देना, या केवल रिपोर्टिंग आइटम लॉग स्तर के मानदंडों को पूरा करना;

debug(message, "serious", 1)();
debug(message, "minor", 4)();

1

आप यहाँ तर्क को सरल बना सकते हैं। यह मानता है कि आपका वैश्विक डिबग ध्वज गतिशील नहीं है और ऐप लोड पर सेट है या कुछ कॉन्फिगर के रूप में पारित किया गया है। यह पर्यावरण फ़्लैगिंग के लिए उपयोग करने का इरादा है (उदाहरण के लिए केवल प्रिंट जब देव मोड में और उत्पादन नहीं)

वेनिला जेएस:

(function(window){ 
  var Logger = {},
      noop = function(){};

  ['log', 'debug', 'info', 'warn', 'error'].forEach(function(level){
    Logger[level] = window.isDebug ? window.console[level] : noop;
  });

  window.Logger = Logger;
})(this);

ES6:

((window) => {
  const Logger = {};
  const noop = function(){};

  ['log', 'debug', 'info', 'warn', 'error'].forEach((level) => {
    Logger[level] = window.isDebug ? window.console[level] : noop;
  });

  window.Logger = Logger;
})(this);

मापांक:

const Logger = {};
const noop = function(){};

['log', 'debug', 'info', 'warn', 'error'].forEach((level) => {
  Logger[level] = window.isDebug ? window.console[level] : noop;
});

export default Logger;

कोणीय 1.x:

angular
  .module('logger', [])
  .factory('Logger', ['$window',
    function Logger($window) {
      const noop = function(){};
      const logger = {};

      ['log', 'debug', 'info', 'warn', 'error'].forEach((level) => {
        logger[level] = $window.isDebug ? $window.console[level] : noop;
      });

      return logger;
    }
  ]);

अब आपको बस इतना करना होगा कि लॉगर के साथ सभी कंसोल रिफ को बदल दिया जाए


1

यह कार्यान्वयन चयनित उत्तर पर आधारित है और त्रुटि कंसोल में शोर की मात्रा को कम करने में मदद करता है: https://stackoverflow.com/a/32928812/516126

var Logging = Logging || {};

const LOG_LEVEL_ERROR = 0,
    LOG_LEVEL_WARNING = 1,
    LOG_LEVEL_INFO = 2,
    LOG_LEVEL_DEBUG = 3;

Logging.setLogLevel = function (level) {
    const NOOP = function () { }
    Logging.logLevel = level;
    Logging.debug = (Logging.logLevel >= LOG_LEVEL_DEBUG) ? console.log.bind(window.console) : NOOP;
    Logging.info = (Logging.logLevel >= LOG_LEVEL_INFO) ? console.log.bind(window.console) : NOOP;
    Logging.warning = (Logging.logLevel >= LOG_LEVEL_WARNING) ? console.log.bind(window.console) : NOOP;
    Logging.error = (Logging.logLevel >= LOG_LEVEL_ERROR) ? console.log.bind(window.console) : NOOP;

}

Logging.setLogLevel(LOG_LEVEL_INFO);

0

मुझे इस समस्या के कुछ उत्तर अपनी आवश्यकताओं के लिए थोड़े बहुत जटिल लगे। यहाँ एक सरल समाधान है, कॉफ़ीस्क्रिप्ट में प्रस्तुत किया गया है। यह ब्रायन ग्रिंस्टेड के संस्करण से अनुकूलित है

यह वैश्विक कंसोल ऑब्जेक्ट को मानता है।

# exposes a global 'log' function that preserves line numbering and formatting.
(() ->
    methods = [
      'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
      'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
      'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
      'timeStamp', 'trace', 'warn']
    noop = () ->
    # stub undefined methods.
    for m in methods  when  !console[m]
        console[m] = noop

    if Function.prototype.bind?
        window.log = Function.prototype.bind.call(console.log, console);
    else
        window.log = () ->
            Function.prototype.apply.call(console.log, console, arguments)
)()

0

जिस तरह से मैंने इसे हल किया वह एक ऑब्जेक्ट बनाने के लिए था, फिर Object.defineProperty () का उपयोग करके ऑब्जेक्ट पर एक नई प्रॉपर्टी बनाएं और कंसोल प्रॉपर्टी को वापस करें, जो तब सामान्य फ़ंक्शन के रूप में उपयोग किया जाता था, लेकिन अब विस्तारित एबिलिटी के साथ।

var c = {};
var debugMode = true;

var createConsoleFunction = function(property) {
    Object.defineProperty(c, property, {
        get: function() {
            if(debugMode)
                return console[property];
            else
                return function() {};
        }
    });
};

फिर, एक संपत्ति को परिभाषित करने के लिए जो आप अभी करते हैं ...

createConsoleFunction("warn");
createConsoleFunction("log");
createConsoleFunction("trace");
createConsoleFunction("clear");
createConsoleFunction("error");
createConsoleFunction("info");

और अब आप अपने फ़ंक्शन का उपयोग कर सकते हैं जैसे

c.error("Error!");

0

अन्य उत्तरों (मुख्य रूप से @arctelix one) के आधार पर मैंने इसे Node ES6 के लिए बनाया था, लेकिन एक त्वरित परीक्षण ने ब्राउज़र में भी अच्छे परिणाम दिखाए। मैं दूसरे फ़ंक्शन को एक संदर्भ के रूप में पारित कर रहा हूं।

let debug = () => {};
if (process.argv.includes('-v')) {
    debug = console.log;
    // debug = console; // For full object access
}

0

यहाँ मेरा लकड़हारा समारोह (कुछ उत्तरों के आधार पर) है। आशा है कि कोई इसका उपयोग कर सकता है:

const DEBUG = true;

let log = function ( lvl, msg, fun ) {};

if ( DEBUG === true ) {
    log = function ( lvl, msg, fun ) {
        const d = new Date();
        const timestamp = '[' + d.getHours() + ':' + d.getMinutes() + ':' +
            d.getSeconds() + '.' + d.getMilliseconds() + ']';
        let stackEntry = new Error().stack.split( '\n' )[2];
        if ( stackEntry === 'undefined' || stackEntry === null ) {
            stackEntry = new Error().stack.split( '\n' )[1];
        }
        if ( typeof fun === 'undefined' || fun === null ) {
            fun = stackEntry.substring( stackEntry.indexOf( 'at' ) + 3,
                stackEntry.lastIndexOf( ' ' ) );
            if ( fun === 'undefined' || fun === null || fun.length <= 1 ) {
                fun = 'anonymous';
            }
        }
        const idx = stackEntry.lastIndexOf( '/' );
        let file;
        if ( idx !== -1 ) {
            file = stackEntry.substring( idx + 1, stackEntry.length - 1 );
        } else {
            file = stackEntry.substring( stackEntry.lastIndexOf( '\\' ) + 1,
                stackEntry.length - 1 );
        }
        if ( file === 'undefined' || file === null ) {
            file = '<>';
        }

        const m = timestamp + ' ' + file + '::' + fun + '(): ' + msg;

        switch ( lvl ) {
        case 'log': console.log( m ); break;
        case 'debug': console.log( m ); break;
        case 'info': console.info( m ); break;
        case 'warn': console.warn( m ); break;
        case 'err': console.error( m ); break;
        default: console.log( m ); break;
        }
    };
}

उदाहरण:

log( 'warn', 'log message', 'my_function' );
log( 'info', 'log message' );
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.