XSJSのログのDB格納

# はじめに
トレースログに出力し、確認もできますが検索が大変な為、
xsjsでの実行結果やデバックログをDBに格納できないかを思案してみました。

# トレースログの出力方法
以下の記述を入れることによりトレースログが出力され、Tracesメニューから確認できます。

```JS:xsjs
$.trace.debug("log comments"); 
```


前述しておりますが1実行でそこそこの行数が出力されるので
特定の文字列をつける等して、検索できるようにしておく事をお勧めします。

# DB格納の思案内容

コミットタイミングも考慮するとConnectionは別途用意し、
xsjsの処理後に書き出すのが良いかと考えました。

その為には、配列に書き出すログを溜めておく必要があります。

では、実際に上記の処理を形にしてみます。
今回は、xsjslibを作成し、各xsjsの処理から呼べるようにします。

```JS:logger.xsjslib
/*
@function 時間文字列作成
@param 
@returns yyyy/mm/dd hh:ii:ss.ddd
*/
function _getDateTimeNow() {
    //
    var dateObj = new Date();
    
    var dateTime = String(dateObj.getFullYear()) + "/" + String(("0" + (dateObj.getMonth() + 1)).slice(-2)) + "/" + String(("0" + dateObj.getDate()).slice(-2)) + " " + 
                   String(("0" + (dateObj.getHours())).slice(-2)) + ":" + String(("0" + (dateObj.getMinutes())).slice(-2)) + ":" + String(("0" + (dateObj.getSeconds())).slice(-2)) + "." + 
                   String(("00" + (dateObj.getMilliseconds())).slice(-3));
	
	return dateTime;
}


function getInstance() {
    return {
        
        logOutTarget: $.import('./dblog.xsjslib'),
        logcache: [],
        loglevel: {
            DEBUG: {"name": "debug", "priority": 10},
            INFO:  {"name": "info" , "priority": 20},
            WARN:  {"name": "warn" , "priority": 30},
            ERROR: {"name": "error", "priority": 40}
        },
        
        // ログ出力関係
        _logFormatta: function( loglevel, message ) {
            var msgArr = message;
            if (msgArr instanceof Array){
                msgArr = JSON.stringify(message);
            } 
            var dateTime = _getDateTimeNow();
            var logUserId = $.request.parameters.get("userid");
            logUserId = (logUserId) ? logUserId : 'testuser';
            var logger = {
                "dateTime"    : dateTime,
                "userId"      : logUserId,
                "loglevel"    : loglevel.priority,
                "loglevelName": loglevel.name,
                "message"     : String(msgArr)
            };
            return logger ;
        },
        _appendLogCache: function( rec ) {
            this.logcache.push( rec );
        },
        log: function( loglevel, message ) {
            var rec = this._logFormatta( loglevel, message );
            this._appendLogCache( rec );
        },
        
        // ログ出力　呼び出す関連
        debug: function(message) {
            this.log( this.loglevel.DEBUG, message );
        },
        info: function(message) {
            this.log( this.loglevel.INFO, message );
        }, 
        warn: function(message) {
            this.log( this.loglevel.WARN, message );
        }, 
        error: function(message) {
            this.log( this.loglevel.ERROR, message );
        }, 
        flush: function() {
            this.logOutTarget.write( this.logcache );
        }
    };
}
```
上記の処理では、まずXSJSにてgetInstanceを行い、
各処にログレベルをつけて配列に格納できるようにしております。

最終はflushを行うことでDBへの書き出しを想定しております。

DB書き出し用の処理は別途xsjslibにしております。

```JS:dblog.xsjslib
/*
@function ログ書き出し処理
@param loglist:ログ格納配列
@returns 
*/
function write( loglist ) {
    $.trace.debug("write");
    // ない場合はそこで終了
    if( !loglist ) {
        // null等
        $.trace.debug("nullerror");
        return;
    }
    if( !loglist instanceof Array ) {
        // 配列以外
        $.trace.debug("Arrerror");
        return;
    }
    
    try {
        // ■ db接続
        var conn = $.db.getConnection();
        conn.setAutoCommit(true);
        
        var query = this._getInsQuery();
        var pstmt = conn.prepareStatement(query);
        
        // SQL連続実行
        for(var i = 0; i < loglist.length; i++ ) {
            var logno = i + 1;
            var rec = loglist[ i ];
            this._bindInsQuery( pstmt, rec, logno);
            pstmt.execute();
        }
    }
    catch( e ) {
        $.trace.error("" + e);
    }
    if( conn ) {
        conn.close();
    }
}
/*
@function bindセット処理
@param 
@returns
*/
function _bindInsQuery( pstmt, rec , logno) {
    // トレースログへの書き出し
    $.trace.debug("dt: " + String(rec.dateTime));
    $.trace.debug("ui: " + String(rec.userId));
    $.trace.debug("no: " + String(logno));
    $.trace.debug("lv: " + String(rec.loglevel));
    $.trace.debug("nm: " + String(rec.loglevelName));
    $.trace.debug("ms: " + String(rec.message));
    // bindセット
    pstmt.setString( 1, rec.dateTime);      // DATE_TIME
	pstmt.setString( 2, rec.userId);        // USER_ID
	pstmt.setInteger(3, logno);             // LOG_NO
	pstmt.setInteger(4, rec.loglevel);      // LOG_LEVEL
	pstmt.setString( 5, rec.loglevelName);  // LOG_LEVEL_NAME
	pstmt.setText( 6, rec.message);       // MESSEGE
}

/*
@function クエリ文字列取得
@param 
@returns クエリ文字列
*/
function _getInsQuery() {
    var queryStr = "INSERT INTO \"XSJSLOG\" (DATE_TIME, USER_ID, LOG_NO, LOG_LEVEL, LOG_LEVEL_NAME, MESSEGE) VALUES (?, ?, ?, ?, ?, ?)"; 
    return queryStr;
}
```

# XSJS側のログ書き出しlibの設定

各xsjsの先頭で以下の記述を行います。
パスにつきましては環境に合わせて読み替えてください。

```JS:xsjs
var loggerlib = $.import('../../libs/log/logger.xsjslib'); 
var logger = loggerlib.getInstance();
```

ログを出力したい個所にて以下のように記述します。

```JS:xsjs
logger.debug("log comments");
logger.info("log comments");
logger.warn("log comments");
logger.error("log comments");
```

xsjsの最後に処理あたりにてflushを行います。

```JS:xsjs
logger.flush();
```

# 最後に
今回は、DBへのログ格納をトレースログのように行うというところで実装してみました。
トレースログで事足りるという方、また上記のロジックについては、
まだまだブラッシュアップできるところがあるかと思いますがご容赦ください。

トレースログが見にくいという方は、１つの方法として
この記事をご参考にしていただければ幸いです。