作成に至る発端
Log4js もあるが、ほとんどデバッグ目的のログ出力なので、console.assert や console.dir、可変長引数の console.log で出力する事が多い。文字列のみを出力する Log4js はオブジェクトや、XMLの出力において、console での出力に圧倒的に劣る。
また、Log4js自体のファイルサイズも大きい。
しかし、console は、ログ出力レベルを指定して出力をコントロールするといった機能が無い。
そんな事を考えていると、以下の記事が目に入り、ライブラリを作るかという事になった。
console.log は長くてつらい #JavaScript - Qiita
http://qiita.com/items/6f2ae599207fa9af323a
挫折
難しくないだろうと、こんなコードを書いた。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | var LoggerLevel={ ALL:-99, DEBUG:-1, INFO:0, WARN:1, ERROR:2, OFF:99 }, self= null ; var Logger= function (level){ self= this ; self.level=isNaN(level) ? LoggerLevel.INFO : level; }; for ( var key in console){ var level=LoggerLevel[key.toUpperCase()]; if (!level){level=99}; ( function (k,l){ Logger.prototype[k]= function (){ self= this ; if (self.level<=l){ return console[k].apply(console, arguments); } } } )(key, level); }; |
1 2 3 4 5 6 | var logger= new Logger(LoggerLevel.INFO); logger.debug( "debugメッセージ" ); logger.info( "infoメッセージ" ); logger.warn( "warnメッセージ" ); logger.error( "errorメッセージ" ); logger.dir([1,2,3,4,5]); |
ん・・・コンソールに表示される、どこでログ出力が呼ばれたかという行番号が、logger.js の console[k].apply の行番号になっている。
本当は、logger.info等を実行している行番号が出てほしいんだけど・・・。
これじゃデバッグが不便になるな。
うむ~まいった。
なやんでいると、こんな記事を見つけた。
console.logのエイリアス - hokaccha.hamalog v2
http://d.hatena.ne.jp/hokaccha/20111216/1324026093
bindね。これを使うと、bindされたファンクションを、コンストラクタとして扱えるようになるという事。
bind | Mozilla Developer Network
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind
そして完成
bindを使い、以下のように書き直した。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | var LoggerLevel={ ALL:- 99 , DEBUG:- 1 , INFO: 0 , WARN: 1 , ERROR: 2 , OFF: 99 }, self= null ; var Logger=function(level){ self= this ; self.level=isNaN(level) ? LoggerLevel.INFO : level; }; for (var key in console){ var level=LoggerLevel[key.toUpperCase()]; if (!level){level= 99 }; Logger.prototype[key]=( function(k,l){ self= this ; if (self.level<=l){ if (Function.bind){ return console[k].bind(console); } else { return console[k].apply(console, arguments); } } } )(key, level); }; |
今度は、ちゃんと呼び出し元のファイル名、行番号でコンソールに出力された。
めでたしめでたし。
ちょっと修正
上のコードでも問題ないんだけど、ちょっと見直し。ログ出力の度いちいちFunction.bindを判定するのもなぁ・・・と思ったので以下のようにした。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | var LoggerLevel={ ALL:-99, DEBUG:-1, INFO:0, WARN:1, ERROR:2, OFF:99 }, self= null ; var Logger= function (level){ self= this ; self.level=isNaN(level) ? LoggerLevel.INFO : level; }; for ( var key in console){ var level=LoggerLevel[key.toUpperCase()]; if (!level){level=LoggerLevel.OFF}; if (Function.bind){ Logger.prototype[key]=( function (k,l){ self= this ; if (self.level<=l){ return console[k].bind(console); } } )(key, level); } else { Logger.prototype[key]=( function (k,l){ self= this ; if (self.level<=l){ return console[k].apply(console, arguments); } } )(key, level); } }; |
console.timeとか使った際に、判定が入ることによる誤差を無くすための処置。
更に修正
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | var LoggerLevel={ ALL:- 99 , DEBUG:- 1 , INFO: 0 , WARN: 1 , ERROR: 2 , OFF: 99 }; var Logger=function(level){ var self= this ; self.level=isNaN(level) ? LoggerLevel.INFO : level; self.make(); }; Logger.prototype.make=function(){ var self= this ; for (var key in console){ var l=LoggerLevel[key.toUpperCase()]; if (!l){l=LoggerLevel.OFF}; if (self.level<=l){ if (Function.bind){ Logger.prototype[key]=( function(k){ return console[k].bind(console); } )(key); } else { Logger.prototype[key]=( function(k){ return console[k].apply(console, arguments); } )(key); } } else { Logger.prototype[key]=function(){}; } } }; |
一応最終版。
ダウンロード
- 非圧縮版(915B)
- https://sites.google.com/site/logroid/files/logger.js
- 圧縮版(661B)
- https://sites.google.com/site/logroid/files/logger.min.js
JavaScript
0 件のコメント:
コメントを投稿