Doğru satır numarasına sahip console.log için uygun bir sarmalayıcı?


132

Şimdi bir uygulama geliştiriyorum ve küresel bir isDebuggeçiş yapıyorum . console.logDaha rahat kullanım için sarmak istiyorum .

//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.');

Sonra bu sonucu Firefox konsolunda alıyorum.

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

Ya aranacak yer numarası ile oturum açmak istersem debug(), mesela info: Here is a msg. main.js (line 2)?


Bir sarmalayıcı işlevi aracılığıyla bir şey eklemek yerine console.logbilgi console.warniçin, uyarı için ve console.errorhata için kullanabilirsiniz console.log.
Alvin Wong

2
@AlvinWong Evet Bunu biliyorum, ama sorun şu ki, consolekullanılması gerekip gerekmediğini kontrol eden global bir hata ayıklama anahtarına ihtiyacım var. Böyle bir hedefe ulaşmak için, bir paketleyici tek yol gibi görünüyor?
Rufus

Google Chrome için stackoverflow.com/a/25729203/1429301 adresine bakın . Sizin durumunuzda model debug.js
Alexander

Yanıtlar:


117

Bu eski bir sorudur ve verilen tüm cevaplar aşırı derecede hilekârdır, BÜYÜK tarayıcılar arası sorunları vardır ve süper yararlı hiçbir şey sağlamaz. Bu çözüm her tarayıcıda çalışır ve tüm konsol verilerini olması gerektiği gibi raporlar. Hack gerektirmez ve bir satır kod kodlayıcıya göz atın .

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

Anahtarı şu şekilde oluşturun:

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

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

Ardından aşağıdaki şekilde arayın:

debug('This is happening.')

Console.log dosyasını şöyle bir anahtarla bile devralabilirsiniz:

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

Bununla faydalı bir şey yapmak istiyorsanız .. Tüm konsol yöntemlerini ekleyebilir ve bunu yalnızca genel kontrol değil, aynı zamanda sınıf seviyesi de veren yeniden kullanılabilir bir işlevde toplayabilirsiniz:

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!')

Şimdi onu sınıflarınıza ekleyebilirsiniz:

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

16
Yanılıyorsam düzelt ama bu, herhangi bir ek işlev eklemene izin vermiyor, değil mi? Esasen yalnızca konsol nesnesinin takma adını mı kullanıyorsunuz? Kaba bir örnek - olayı her debug.log () için iki kez console.log () yapmanın bir yolu yoktur?
AB Carroll

3
@ABCarroll İki çağrı içeren console.logözel bir log()işlevi iki kez bağlayabilirsiniz console.log, ancak satır numaraları console.lognerede debug.logçağrıldığını değil , gerçekte bulunan hattı yansıtır . Bununla birlikte, dinamik ön ekler / son ekler vb. Eklemek gibi şeyler yapabilirsiniz. Satır numarası sorununu telafi etmenin yolları da var, ancak bu bence başka bir soru. Bir örnek için bu projeye göz atın: github.com/arctelix/iDebugConsole/blob/master/README.md
arctelix

2
Bu yöntem Firefox'ta 47'den 49'a kadar (dahil) çalışmaz. Ve yalnızca 50.0a2 sürümünde düzeltildi. FF50 2 hafta içinde piyasaya sürülecek, ancak neden işe yaramadığını anlamak için birkaç saat harcıyorum. Bu yüzden bu bilginin birisi için faydalı olabileceğini düşünüyorum. bağlantı
Vladimir Liubimov

@ABCarroll'un örnek içindeki her şeyin çalışma zamanında kullanılamayacağına inanıyorum. Başka örneğin küresel devlet sadece daha sonra değiştirirseniz, bu örnekleme tanımlanabilir this.isDebugiçin false, meselenin olmaz. Bunun bir yolu var mı bilmiyorum, belki tasarım gereğidir. Bu anlamda, isDebugoldukça yanıltıcıdır varve constonun yerine olmalıdır .
cregox

3
Bu, "debug () işlevinin çağrıldığı satır numarasıyla oturum açmak istersem ne olur?" Sorusunu yanıtlamaz.
technomage

24

@ Fredrik'in cevabını beğendim , bu yüzden Webkit yığın izini bölen başka bir cevapla yuvarladım ve @ PaulIrish'in güvenli console.log paketleyicisiyle birleştirdim . filename:lineFF ve Chrome'da öne çıkması ve çoğunlukla aynı görünmesi için "özel bir nesne" olarak "standartlaştırır" .

Kemanla test etme: 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

Bu aynı zamanda düğümde de çalışır ve aşağıdakilerle test edebilirsiniz:

// 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 ---');

Ekstra için hesaba biraz daha gelişmiş bir cevap consolegibi yöntemlerle warn, error- vb stackoverflow.com/a/14842659/1037948
drzaus

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

@sigod - muhtemelen ya tarayıcıya bağlıdır ya da bunu 2 yıl önce yazdığım ve tarayıcı (lar) değişti. senaryon nedir
drzaus

1
meslektaşlarımdan biri kodunuzu kopyalayıp projemize yapıştırdı. IE11 ve Safari 5'te siteyi bozdu. Bu tarayıcının diğer sürümlerinden emin değilim. Belki gelecekteki kopya-yapıştırıcılar için bir çek eklersiniz?
sigod

1
@sigod peki ya şimdi? if(!stack) return '?'nerede çağrıldığı yerine başarısız olan yönteme eklenir (bu nedenle, yöntemin kendisini kullanan biri de "korumalı" olur)
drzaus

18

Aşağıdakileri akıllıca kullanarak satır numaralarını koruyabilir ve günlük düzeyini çıktı olarak verebilirsiniz 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)

Bir adım daha ileri götürerek, console'nin hata / uyarı / bilgi ayrımlarını kullanabilir ve yine de özel seviyelere sahip olabilirsiniz. Dene!

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
Ben otomatik çıktı önek bir süredir çalışıyordum console.debug(...)ile function nameve argumentsbunu nasıl herhangi düşünceler -?
Daniel Sokolowski

3
Çok sayıda konsol sarmalayıcıya / şimlere / vb. Bakıyorum. ve bu, satır numaralarını korumayı çıktıyı özelleştirmeyle birleştiren ilk karşılaştığım şey. Bu, .bind'in sizin için biraz körelmesi, bağlama ek olarak bir veya daha fazla argüman bağlayabileceğiniz gerçeğinin akıllıca bir kullanımıdır . Bunu bir adım daha ileri götürebilir ve .toString yöntemiyle , günlük yöntemi çağrıldığında kodu çalıştırabilecek bir noop işlevi geçirebilirsiniz ! Bkz bu jsfiddle
Sam Hasler

2
Belki tüm tarayıcılarda olmayabilir (bakmadım), ancak Chrome'da %sile değiştirmek %o, parametreleri beklediğiniz şekilde yazdıracaktır (nesneler genişletilebilir, sayılar ve dizeler renklidir, vb.).
anson

bu çözümü seviyorum. Uygulamam için daha iyi sonuç veren birkaç değişiklik yaptım, ancak büyük kısmı hala sağlam ve güzel çalışıyor. Teşekkürler
Ward

9

Kimden: JavaScript arayan işlevi satır numarası nasıl alınır? JavaScript arayan kaynak URL'si nasıl alınır? ErrorNesne (FF) bir hat numarasıdır özelliğine sahiptir. Yani bunun gibi bir şey çalışmalı:

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

Webkit tarayıcısında err.stack mevcut çağrı yığınını temsil eden bir dizeye . Mevcut satır numarasını ve daha fazla bilgiyi gösterecektir.

GÜNCELLEME

Doğru çamaşır numarasını elde etmek için, o satırdaki hatayı çağırmanız gerekir. Gibi bir şey:

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();bana yürütüldüğü bağlamı verir, eğer onu koyarsam debug.js, o zaman alırım info: Here is a msg. file: http://localhost/js/debug.js line:7.
Rufus

1
Ne anlamı var Log = Error? Hala Error sınıfını değiştiriyorsunuz, değil mi?
drzaus

Cevabınızı birkaç kişiyle birleştirdik - aşağıya bakın stackoverflow.com/a/14841411/1037948
drzaus

8

Satır numarasını korumanın bir yolu burada: https://gist.github.com/bgrins/5108712 . Aşağı yukarı şuna indirgeniyor:

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);
    };
}

Sen bu sarabilirdiniz isDebugve set window.logiçin function() { }size ayıklama değilse.


7

Satır numarasını aşağıdaki gibi hata ayıklama yönteminize iletebilirsiniz:

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

Burada (new Error).lineNumbersize javascriptkodunuzdaki mevcut satır numarasını verecektir .


2
Biraz ayrıntılı, değil mi?
Rufus

2
Sanırım sorgunuzu cevaplamanız yeterli. :)
Subodh

1
lineNumber özelliği standart değil ve şu anda yalnızca firefox'ta çalışıyor, buraya
Matthias

6

Chrome Devtools, Blackboxing ile bunu başarmanıza olanak tanır . Yan etkilere sahip olabilen, diğer işlevleri çağırabilen, vb. Ve yine de sarmalayıcı işlevini çağıran satır numarasını koruyabilen console.log sarmalayıcısı oluşturabilirsiniz.

Küçük bir console.log sarmalayıcısını ayrı bir dosyaya koyun, örn.

(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)
    }
})()

Log-blackbox.js gibi bir ad verin

Ardından Chrome Devtools ayarlarına gidin ve "Kara kutu oluşturma" bölümünü bulun, kara kutuya eklemek istediğiniz dosya adı için bir desen ekleyin, bu durumda log-blackbox.js


Not: Marka emin herhangi bir kod yok olurdu o da iz kaldırılacaktır olarak, aynı dosyada yığın izleme gösterilmesini istiyoruz.
jamesthollowell

6

Gerçekte günlüğe kaydedileni filtrelemek için kabul edilen yanıtı (console.log / error / etc'ye bağlanmak) bazı dış mantıkla birleştirmek için basit bir çözüm buldum.

// 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;

Kullanımı:

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.assertKoşullu günlük kaydı kullandığını unutmayın .
  • Tarayıcınızın geliştirme araçlarının tüm mesaj seviyelerini gösterdiğinden emin olun!

Çünkü herhangi bir satır numarası ya da log seviyesini gösteren çalışma örnekleri vermez.
not2qubit

Satır numarası, konsolu doğrudan kullanıyormuş gibi aynı olacaktır. Cevabı kullanım örnekleri ile güncelledim. Çok oy almıyor çünkü iki yıl sonra cevapladım :)
Jacob Phillips

4

Sadece hata ayıklamanın kullanılıp kullanılmadığını kontrol etmek ve doğru satır numarasına sahip olmak istiyorsanız, bunun yerine bunu yapabilirsiniz:

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(){}
    };
}

Hata ayıklamaya erişmeniz gerektiğinde, bunu yapabilirsiniz:

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

Eğer isDebug == true, Konsolda gösterilen satır numaraları ve dosya adları doğru olacaktır, çünkü debug.logetc aslında console.logvs.'nin takma adıdır .

Eğer isDebug == falsehiçbir hata ayıklama mesajları gösterilir, çünküdebug.log vb basitçe hiçbir şey (boş bir fonksiyonu) yapar.

Bildiğiniz gibi, bir sarmalayıcı işlevi satır numaralarını ve dosya adlarını karıştıracaktır, bu nedenle sarmalayıcı işlevlerinin kullanılmasını önlemek iyi bir fikirdir.


Büyük, ben sırasına konusunda dikkatli olmak gerekir isDebug = trueve debug.jsancak bu cevap çalışır!
Rufus

3
window.debug = window.consolebiraz daha temiz olurdu.
fredrik

@fredrik daha sonra tüm üye işlevlerini "uygulamam" gerekecekse isDebug == false . : {
Alvin Wong

@AlvinWong I just menat for if eğer isDebug===true. Veya bunun için olay: jsfiddle.net/fredrik/x6Jw5
Fredrik

4

Yığın izleme çözümleri satır numarasını gösterir , ancak büyük bir sorun olan kaynağa gitmek için tıklamaya izin vermez. Bu davranışı korumak için tek çözüm , orijinal işleve bağlanmaktır .

Bağlama, ara mantığın dahil edilmesini engeller, çünkü bu mantık satır numaralarını karıştırır. Bununla birlikte, bağlı işlevleri yeniden tanımlayarak ve konsol dizesi değiştirmeyle oynayarak , bazı ek davranışlar hala mümkündür.

Bu özet modüller, günlük seviyeleri, biçimlendirme ve 34 satırda uygun tıklanabilir satır numaraları sunan minimalist bir günlükleme çerçevesini gösterir. Bunu kendi ihtiyaçlarınız için bir temel veya ilham kaynağı olarak kullanın.

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

DÜZENLEME: özet aşağıda yer almaktadır

/*
 * 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"
})();


Bu yanıtın yalnızca 3 olumlu oyu var ancak sayfadaki diğer tüm yanıtlardan inanılmaz derecede daha zengin ve temiz
Tom

ancak, görünen o ki, tüm yararlı parçalar harici bir özde yer alıyor.
Ryan The Leach

3

Bind ile fikir Function.prototype.bindmükemmel. Ayrıca npm kitaplığı satır günlükçüsünü de kullanabilirsiniz . Kaynak kaynak dosyalarını gösterir:

Projenizde herhangi birini bir kez kaydedici oluşturun:

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

Günlükleri yazdır:

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

görüntü açıklamasını buraya girin


2

consoleÇıktıya bir dosya adı ve satır numarası veya diğer yığın izleme bilgilerini eklerken mevcut günlük ifadelerinizi korumanın bir yolu :

(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;
  }, {}));
}());

O zaman şu şekilde kullanın:

<!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>

Bu Firefox, Opera, Safari, Chrome ve IE 10'da çalışır (henüz IE11 veya Edge üzerinde test edilmemiştir).


İyi iş, ama yine de ihtiyacım olan şey değil. Dosya adı ve satır numarası bilgisinin, kaynağı açmak için tıklanabileceği konsol görünümünün sağ tarafında olmasını istiyorum. Bu çözüm, bilgiyi mesajın bir parçası olarak gösterir (bunun gibi:) my test log message (myscript.js:42) VM167 mypage.html:15, bu da okunması kadar iyi değildir ve bağlantılı değildir. Hala iyi iş, bu yüzden bir olumlu oy.
Frederic Leitenberger

Evet, bu ideal olsa da, konsolda
görünen

@BrettZamir, burada bu kodla ilgili bir soru yayınladı: 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.'));

Bu bana verecek info: "Here is a msg." main.js(line:2).

Ama fazladan evalgerekli, yazık.


2
eval Kötüdür! Yani her kötülük.
fredrik

1

Http://www.briangrinstead.com/blog/console-log-helper-function kodu :

// 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);

Bu log, aranan orijinal satır numarasını göstermiyor gibi görünüyor
ragamufin

Test ettiğimde çalıştığından neredeyse eminim, ancak kodu aynı sayfadaki "tam" sürümle değiştirdim. En azından Chrome 45'te çalıştı.
Timo Kähkönen

Anladım. Şimdi sahip olduğunuz değişikliklerle, aslında diğer birkaç cevap ve çalışmayla aynı. Önceki kodunuzu merak ediyordum çünkü sonunda bunu daha fazla kullanmam için ilginç olasılıklar ortaya çıkaran bir başvurunuz vardı, ancak satır numarasını göstermediği için kareye geri döndüm. Yine de teşekkürler!
ragamufin

1

Son zamanlarda bu konuya kendim bakıyorum. Günlük kaydını kontrol etmek ve aynı zamanda satır numaralarını korumak için çok basit bir şeye ihtiyaç vardı. Çözümüm kod olarak zarif görünmüyor, ancak benim için gerekli olanı sağlıyor. Kapatma ve tutma konusunda yeterince dikkatli olunursa.

Uygulamanın başına küçük bir sarmalayıcı ekledim:

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

Böylece daha sonra şunları yapabilirim:

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

Firefox ve crome ile test ettim ve her iki tarayıcı da konsol günlüğünü amaçlandığı gibi gösteriyor gibi görünüyor. Bu şekilde doldurursanız, 'd' yöntemini her zaman genişletebilir ve diğer parametreleri ona iletebilirsiniz, böylece fazladan günlük kaydı yapabilir.

Giriş kodundaki çirkin satır dışında, yaklaşımım için henüz ciddi bir dezavantaj bulamadım.


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');

İşte bu soru hakkındaki çözümüm buydu. yöntemi çağırdığınızda: günlük, günlüğünüzü yazdırdığınız satır numarasını yazdıracaktır


1

Küçük bir varyasyon, debug () işlevinin daha sonra ihtiyacınız olan yerde çalıştırılan bir işlevi döndürmesini sağlamaktır - debug (message) (); ve böylece, bir uyarı olarak yeniden yönlendirme veya dosyaya kaydetme gibi varyasyonlara izin verirken, konsol penceresinde doğru satır numarasını ve arama komut dosyasını düzgün şekilde gösterir.

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() {});
  }

}

Bir işlev döndürdüğü için, bu işlevin hata ayıklama satırında (); ile çalıştırılması gerekir. İkincisi, mesaj, geri döndürülen işlev yerine hata ayıklama işlevine gönderilir; ön işlemeye veya günlük düzeyi durumunu kontrol etme, iletiyi daha okunaklı hale getirme, farklı türleri atlama veya yalnızca raporlama öğeleri gibi ihtiyaç duyabileceğiniz kontrol etmeye izin verir. günlük düzeyi kriterlerini karşılayan;

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

1

Burada mantığı basitleştirebilirsiniz. Bu, genel hata ayıklama bayrağınızın dinamik OLMADIĞINI ve uygulama yüklenirken ayarlandığını veya bazı yapılandırma olarak aktarıldığını varsayar. Bunun, ortam işaretlemesi için kullanılması amaçlanmıştır (örneğin, yalnızca geliştirme modundayken ve üretimde değilken yazdır)

Vanilya JS:

(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);

Modül:

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

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

export default Logger;

Açısal 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;
    }
  ]);

Şimdi yapmanız gereken tek şey, tüm konsol referanslarını Logger ile değiştirmek.


1

Bu uygulama, seçilen cevaba dayanmaktadır ve hata konsolundaki gürültü miktarını azaltmaya yardımcı olur: 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

Bu sorunun bazı yanıtlarını ihtiyaçlarım için biraz fazla karmaşık buldum. İşte Coffeescript'te oluşturulan basit bir çözüm. Brian Grinstead'in versiyonundan uyarlanmıştır. buradaki

Global konsol nesnesini varsayar.

# 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

Bunu çözme şeklim , bir nesne oluşturmak, ardından Object.defineProperty () kullanarak nesne üzerinde yeni bir özellik oluşturmak ve daha sonra normal işlev olarak kullanılan, ancak şimdi genişletilmiş yetenekle birlikte kullanılan console özelliğini döndürmekti.

var c = {};
var debugMode = true;

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

Ardından, yaptığınız bir özelliği tanımlamak için ...

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

Ve şimdi işlevinizi şu şekilde kullanabilirsiniz:

c.error("Error!");

0

Diğer yanıtlara dayanarak (çoğunlukla @arctelix one) bunu Node ES6 için oluşturdum, ancak hızlı bir test de tarayıcıda iyi sonuçlar gösterdi. Diğer işlevi referans olarak aktarıyorum.

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

0

İşte günlükçü fonksiyonum (bazı cevaplara göre). Umarım birisi bunu kullanabilir:

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;
        }
    };
}

Örnekler:

log( 'warn', 'log message', 'my_function' );
log( 'info', 'log message' );
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.