올바른 줄 번호를 가진 console.log에 적합한 래퍼?


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

그런 다음 Firefox 콘솔 에서이 결과를 얻습니다.

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.
Alvin Wong

2
@AlvinWong 그래, 알지만 문제는 console사용할 필요가 있는지 제어하는 ​​전역 디버그 스위치 가 필요하다는 것입니다. 이러한 목표를 달성하기 위해 래퍼가 유일한 방법 인 것 같습니다.
Rufus

Chrome 의 경우 stackoverflow.com/a/25729203/1429301을 참조하십시오 . 귀하의 경우 패턴은 debug.js입니다
Frison Alexander

답변:


117

이것은 오래된 질문이며 제공된 모든 답변은 지나치게 많은 해키이며 MAJOR 교차 브라우저 문제가 있으며 매우 유용한 것은 없습니다. 이 솔루션은 모든 브라우저에서 작동하며 모든 콘솔 데이터를 정확하게보고합니다. 아니 해킹이 필요없고, 한 줄의 코드는 codepen 확인하세요 .

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

다음과 같은 스위치로 console.log를 대신 할 수도 있습니다.

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
내가 틀렸다면 바로 잡으십시오. 그래도 추가 기능을 추가 할 수는 없습니다. 맞습니까? 본질적으로 콘솔 개체의 별칭 만 지정하고 있습니까? 조잡한 예-모든 debug.log ()에 대해 이벤트를 console.log ()하는 방법이 두 번 있습니까?
AB 캐롤

3
@ABCarroll에 console.log대한 log()두 개의 호출을 포함 하는 사용자 지정 함수를 바인딩하여 두 번 할 수 console.log있지만 행 번호 는 호출 된 console.log위치 debug.log가 아니라 실제로 존재 하는 행을 반영합니다 . 그러나 동적 접두사 / 접미사 등을 추가하는 등의 작업을 수행 할 수 있습니다. 줄 번호 문제를 보완하는 방법도 있지만 다른 질문입니다. 예를 들어이 프로젝트를 체크 아웃 : github.com/arctelix/iDebugConsole/blob/master/README.md을
arctelix

2
이 방법은 Firefox 버전 47에서 49까지 작동하지 않습니다. 버전 50.0a2에서만 수정되었습니다. FF50은 2 주 후에 출시 될 예정이지만 왜 작동하지 않는지 깨닫기 위해 몇 시간을 보냅니다. 그래서 나는이 정보가 누군가에게 도움이 될 것이라고 생각합니다. 링크
Vladimir Liubimov

@ABCarroll의 의미는 인스턴스 내부의 모든 것을 런타임에 사용할 수 없다는 것입니다. 다른 인스턴스의 경우 전역 상태는 인스턴스화에서만 정의 할 수 있으므로 나중에로 변경 this.isDebug하면 false문제가되지 않습니다. 이 문제를 해결할 방법이 있는지 모르겠습니다. 아마도 디자인에 의한 것입니다. 그런 의미에서는 isDebug오해의 소지 var가 있으며 const대신 해야합니다 .
cregox

2
이것은 "debug ()가 호출되는 줄 번호로 로그인하려면 어떻게해야합니까?"라는 질문에 대답하지 않습니다.
technomage

24

@fredrik의 대답이 마음에 들었 으므로 Webkit stacktrace를 분할하는 다른 대답으로 롤업하여 @PaulIrish의 safe console.log wrapper 와 병합했습니다 . 을 " filename:line특수 객체"로 "표준화"하여 눈에 띄고 FF와 Chrome에서 거의 동일하게 보입니다.

바이올린 테스트 : 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

@sigod-아마도 브라우저에 의존하거나 2 년 전에 쓴 것으로 브라우저가 변경되었습니다. 당신의 시나리오는 무엇입니까?
drzaus

1
동료 중 한 명이 코드를 프로젝트에 복사하여 붙여 넣었습니다. IE11 및 Safari 5에서 사이트가 중단되었습니다.이 브라우저의 다른 버전에 대해서는 잘 모르겠습니다. 복사기 붙여 넣기에 대한 확인을 추가 할 수 있습니까?
sigod

1
@sigod 지금은 어떻습니까? 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의 오류 / 경고 / 정보 구분을 사용하고 여전히 사용자 지정 수준을 가질 수 있습니다. 시도 해봐!

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 namearguments그 작업을 수행하는 방법에 대한 어떤 생각? -
Daniel Sokolowski 2016 년

3
나는 많은 콘솔 래퍼 / 심 / 등을보고있다. 그리고 이것은 줄 번호 유지와 출력 사용자 정의를 결합한 첫 번째입니다. .bind도 약간의 카레를 수행 한다는 사실을 영리하게 사용 하므로 컨텍스트 외에도 하나 이상의 인수를 바인딩 할 수 있습니다 . 한 단계 더 나아가 로그 메소드가 호출 될 때 코드를 실행할 수있는 .toString 메소드로 noop 함수를 전달할 수 있습니다! 이 jsfiddle
Sam Hasler

2
어쩌면 모든 브라우저에서 (아직 살펴 보지 않았을 수도 있지만) Chrome 에서 %swith %o를 바꾸면 예상대로 매개 변수가 인쇄됩니다 (객체는 확장 가능하고 숫자와 문자열은 색상 등).
anson

이 솔루션을 사랑하십시오. 내 응용 프로그램에서 더 잘 작동하는 몇 가지 변경 사항을 만들었지 만 대부분 그대로 유지되고 아름답게 실행됩니다. 감사
Ward

9

보낸 사람 : JavaScript 발신자 기능 줄 번호를 얻는 방법은 무엇입니까? JavaScript 발신자 소스 URL을 얻는 방법? Error오브젝트 (FF)에 줄 수 속성을 갖는다. 따라서 이와 같은 것이 작동해야합니다.

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

Webkit 브라우저 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.
Rufus

1
요점이 Log = Error뭐야? 여전히 오류 클래스를 수정하고 있습니까?
drzaus

몇 다른 사람들과 답변 결합 - 아래 참조 stackoverflow.com/a/14841411/1037948
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.logfunction() { }디버깅하지 않는 경우.


7

다음과 같이 행 번호를 디버그 메소드에 전달할 수 있습니다.

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

여기에 코드 (new Error).lineNumber의 현재 줄 번호가 표시 javascript됩니다.


2
조금 장황하지 않습니까?
Rufus

2
귀하의 질문에 대답하는 것으로 충분하다고 생각합니다. :)
Subodh December

1
lineNumber 속성은 비표준이며 현재 Firefox에서만 작동합니다. 여기
Matthias

6

Chrome Devtools를 사용하면 Blackboxing으로 이를 달성 할 수 있습니다 . 부작용이 있거나 다른 함수를 호출하는 등의 래퍼 함수를 ​​계속 호출 할 수있는 console.log 래퍼를 만들 수 있습니다.

작은 console.log 래퍼를 별도의 파일에 넣으십시오.

(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와 같은 이름을 지정하십시오.

그런 다음 Chrome Devtools 설정으로 이동하여 '블랙 박스'섹션을 찾고 블랙 박스에 추가하려는 파일 이름의 패턴을 추가합니다 (이 경우 log-blackbox.js).


참고 : 확인 당신이 코드가없는 그것은 또한 추적에서 제거되므로, 동일한 파일에 스택 추적에 표시하고자합니다.
jamesthollowell

6

허용 된 답변 (console.log / error / etc에 바인딩)과 외부 로그를 결합하여 실제로 기록되는 것을 필터링하는 간단한 솔루션을 찾았습니다.

// 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조건부 로깅 을 사용합니다.
  • 브라우저의 개발 도구가 모든 메시지 레벨을 표시하는지 확인하십시오!

로그 번호를 표시하는 행 번호 나 실제 예제를 제공하지 않기 때문입니다.
not2qubit

줄 번호는 콘솔을 직접 사용하는 것과 같습니다. 사용법 예제로 답변을 업데이트했습니다. 내가 :) 2 년 후에 그것을 대답 때문에 많은 표를 가지고 있지 않습니다
야곱 필립스에게

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

이면 etc가 실제로는 별칭 isDebug == true이므로 콘솔에 표시된 행 번호와 파일 이름이 정확합니다.debug.logconsole.log 등 .

인 경우 isDebug == false디버그 메시지가 표시되지 않습니다.debug.log etc로 아무것도 수행하지 되지 않습니다 (빈 기능).

이미 알고 있듯이 래퍼 함수는 줄 번호와 파일 이름을 엉망으로 만들므로 래퍼 함수 사용을 방지하는 것이 좋습니다.


우수함, 나는 순서에주의해야 isDebug = true하고 debug.js,하지만이 답변이 작업을 수행합니다!
Rufus

3
window.debug = window.console조금 더 깨끗합니다.
fredrik

@fredrik 그런 다음 모든 멤버 함수를 "구현"해야합니다 isDebug == false. : {
Alvin Wong

@AlvinWong 나는 단지 menat에 대한 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 개의 공감 만 가지고 있지만 페이지의 다른 어떤 것보다 엄청나게 더 풍부하고 깨끗합니다.
Tom

그러나 모든 유용한 부분이 외부 요지에있는 것처럼 보입니다.
Ryan The Leach

3

바인드 아이디어 Function.prototype.bind는 훌륭합니다. npm library lines-logger를 사용할 수도 있습니다 . 원본 소스 파일을 보여줍니다.

프로젝트에서 로거를 한 번 작성하십시오.

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>

Firefox, Opera, Safari, Chrome 및 IE 10 (IE11 또는 Edge에서 아직 테스트되지 않음)에서 작동합니다.


좋은 일이지만 여전히 내가 필요한 것을 100 %는 아닙니다. console-view의 오른쪽에 파일 이름과 줄 번호 정보가 있고, 여기를 클릭하여 소스를 열 수 있습니다. 이 솔루션은 메시지의 일부로 정보를 표시합니다 (예 my test log message (myscript.js:42) VM167 mypage.html:15:). 읽기에 좋지 않고 연결되지 않습니다. 여전히 좋은 일이므로 공감.
Frederic Leitenberger

예, 이상적이지만 콘솔에 표시되는 파일 이름 링크를 스푸핑하는 방법은 없습니다.
Brett Zamir

@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
평가는 악이다! 모든 악.
fredrik

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

테스트 할 때 제대로 작동했다고 확신하지만 같은 페이지의 코드를 "전체"버전으로 교체했습니다. Chrome 45 이상에서 근무했습니다.
Timo Kähkönen

이해했다. 변경 사항이 있으면 이제 다른 답변 및 작동과 동일합니다. 이전 코드에 대해 궁금한 점이 있었기 때문에 마지막에 적용하여 더 많은 것을 사용할 수있는 흥미로운 가능성을 제기했지만 줄 번호를 표시하지 않았기 때문에 다시 사각형으로 돌아갔습니다. 그래도 고마워!
ragamufin

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

이 질문에 대한 나의 해결책은 다음과 같습니다. 메소드를 호출하면 : log, 로그를 인쇄하는 줄 번호를 인쇄합니다


1

약간의 변형은 debug ()가 함수를 리턴하도록하는 것입니다. 그런 다음 필요한 곳에서 실행됩니다.-debug (message) (); 따라서 경고로 경로 재 지정 또는 파일로 저장과 같은 변형을 허용하면서 콘솔 창에 올바른 줄 번호 및 호출 스크립트를 올바르게 표시합니다.

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

여기서 논리를 단순화 할 수 있습니다. 이것은 전역 디버그 플래그가 동적이 아니며 앱로드시 설정되거나 일부 구성으로 전달되었다고 가정합니다. 환경 플래그 지정에 사용하기위한 것입니다 (예 : 개발 모드 일 때만 인쇄)

바닐라 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);

기준 치수:

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

이 문제에 대한 답변 중 일부가 내 요구에 비해 너무 복잡하다는 것을 알았습니다. 다음은 Coffeescript로 렌더링 된 간단한 솔루션입니다. Brian Grinstead의 버전 에서 수정되었습니다.

글로벌 콘솔 오브젝트를 가정합니다.

# 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' );
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.