はじめてのLog4js
社内環境で再現しない不具合が残ってしまったため、ログを取得して障害再発時に解析のネタを得ようとしています。怪しいのはクライアントサイドのJavaScriptです。車輪の再発明を避けるべく、ありがたく先人達の成果を使わせていただきます。
Log4jsを入手する - Object汚染問題対策版(勝手に命名)
Log4jsを使う環境下でfor-in構文を使うと意図せずLog4jsが追加したメソッド・プロパティまでループが実行されたり*1、prototype.jsと競合したり*2するそうなので、Object汚染を回避する必要があるそうです。
この対策が取られたバージョンのソースが下記より入手できます。
http://js.nice-777.com/log4js/memo.html
一応、Log4jsのObject汚染問題は影響が無いはずですが、安全サイドに振って対策版を使うことにします。
#for-inは凶悪らしいので、for-inを使っていなかったのは
#自然な結果のようです。
基本的な使い方
- log4js - JavaScriptログ出力ライブラリ: ある SE のつぶやき
- http://www.fourmeisters.com/blog/ttaka/2007/10/javascriptlog4js.html
- はじめてのlog4js
とかにあります。fnyaさんのエントリをよーく見て自分のコーディングミスに気づきました。orz
Could not run the listener function(){return __method.apply(object,arguments);}. [object error]
とか(たぶん)やらかしてました。headタグの後にloggerのインスタンスを作るとダメっぽい。なおってConsoleのウィンドウが出てきたときはちょっと感動しますた。
Log4jsの資料のぐぐりかたは
概要とか基本的な使い方とか入手のしかたは普通に高度なhackingの成果もそれで得られます。
ただし、ちょっとだけ基本的じゃない使い方をするときはそれでは見つかりませんでした。*3 そんなときは元ネタのLog4jでぐぐると良いようです。google:Log4j PatternLayout
レガシーなVB6 + IEコンポーネントなアプリとの相性は
ConsoleAppenderでは微妙なようです。window.open()まわりがちゃんと実装されて無いせいかもしれませんが。業務系アプリなのでFileAppenderで逃げますた。orz
FileAppenderの場合はあらかじめIEのセキュリティ設定で穴をあけておく必要があります。私の場合は http://d.hatena.ne.jp/babydaemons/20080520/1211255011 で開けておいたので結果オーライでした。
バージョンは1.0-RC1だけど・・・
細かいバグが残ってます。
バグ改修(?)&ミリ秒精度のログ出力拡張hacking
んでもってパッチを作りました。先の対策版との差分です。所要工数およそ1人日w
私が考えてる仕様が正しくて改修も正しいなら、RC2に取り込んでもらうのが吉だと思うのですが・・・ お持ち帰りはこちらから。
--- log4js.js.orig 2008-06-12 19:16:58.000000000 +0900 +++ log4js.js 2008-06-27 13:38:21.166956800 +0900 @@ -18,7 +18,14 @@ * KenjiNagao * ---------------------------------------------------------------------*/ -/*jsl:option explicit*/ +/* --------------------------------------------------------------------- + * To acquire the log in the accuracy of the millisecond, + * this script was customized. +.* This comment can be removed if you want. + * babydaemons(at)gmail.com + * ---------------------------------------------------------------------*/ + + /*jsl:option explicit*/ /** * Object extention (OO) methods if no prototype avaliable. @@ -1952,7 +1959,8 @@ * @type String */ format: function(loggingEvent) { - return loggingEvent.categoryName + "~" + loggingEvent.startTime.toLocaleString() + " [" + loggingEvent.level.toString() + "] " + loggingEvent.message + this.LINE_SEP; +// return loggingEvent.categoryName + "~" + loggingEvent.startTime.toLocaleString() + " [" + loggingEvent.level.toString() + "] " + loggingEvent.message + this.LINE_SEP; + return loggingEvent.categoryName + "~" + loggingEvent.logger.getFormattedTimestamp(loggingEvent.startTime) + " [" + loggingEvent.level.toString() + "] " + loggingEvent.message + this.LINE_SEP; }, /** * Returns the content type output by this layout. @@ -2473,15 +2481,16 @@ formatDate : function(vDate, vFormat) { var vDay = this.addZero(vDate.getDate()); var vMonth = this.addZero(vDate.getMonth()+1); - var vYearLong = this.addZero(vDate.getFullYear()); + var vYearLong = this.addZero(vDate.getFullYear(), "0000"); var vYearShort = this.addZero(vDate.getFullYear().toString().substring(3,4)); var vYear = (vFormat.indexOf("yyyy")>-1?vYearLong:vYearShort); var vHour = this.addZero(vDate.getHours()); var vMinute = this.addZero(vDate.getMinutes()); var vSecond = this.addZero(vDate.getSeconds()); + var vMilliseconds = this.addZero(vDate.getMilliseconds(), "000"); var vTimeZone = this.O(vDate); var vDateString = vFormat.replace(/dd/g, vDay).replace(/MM/g, vMonth).replace(/y{1,4}/g, vYear); - vDateString = vDateString.replace(/hh/g, vHour).replace(/mm/g, vMinute).replace(/ss/g, vSecond); + vDateString = vDateString.replace(/hh/g, vHour).replace(/mm/g, vMinute).replace(/ss/g, vSecond).replace(/SSS/g, vMilliseconds); vDateString = vDateString.replace(/O/g, vTimeZone); return vDateString; }, @@ -2490,8 +2499,11 @@ * @private * @static */ - addZero : function(vNumber) { - return ((vNumber < 10) ? "0" : "") + vNumber; + addZero : function(vNumber, vFormat) { +// return ((vNumber < 10) ? "0" : "") + vNumber; + function right(str, len) { return (new String(str)).substr(str.length - len, len); } + if (!vFormat) vFormat = "00"; + return right(vFormat + vNumber, vFormat.length); }, /** @@ -2510,6 +2522,22 @@ } }; +Log4js.SimpleDateFormat = function(dateFormat) +{ + this.dateFormat = dateFormat; + this.formatter = new Log4js.DateFormatter(); +}; + +Log4js.SimpleDateFormat.prototype = { + /** + * Format input date by Log4js.DateFormatter.formatDate(). + * @return formatted date string. + * @type String + */ + format : function (date) { + return this.formatter.formatDate(date, this.dateFormat); + } +}; /** * internal Logger to be used