/*
* Copyright (C) 2012-2016 NS Solutions Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* hifive
*/
/* ------ h5.log ------ */
(function() {
// =========================================================================
//
// Constants
//
// =========================================================================
// =============================
// Production
// =============================
// エラーコード
/**
* ログターゲット(targets)の指定が不正なときのエラーコード
*/
var ERR_CODE_LOG_TARGET_TYPE = 10000;
/*
* out.categoryのが指定されていないときのエラーコード
* ERR_CODE_OUT_CATEGORY_INVALIDに統合したためver.1.1.0で廃止
* var ERR_CODE_OUT_CATEGORY_IS_NONE = 10001;
*/
/*
* カテゴリが複数回指定されたときのエラーコード
* 出力定義にマッチするかどうかは、カテゴリ名に加えてレベルしても判定するようになったので1.1.15で廃止 #410
* var ERR_CODE_CATEGORY_NAMED_MULTIPLE_TIMES = 10002;
*/
/**
* ログレベルの指定が不正なときのエラーコード
*/
var ERR_CODE_LEVEL_INVALID = 10003;
/**
* 存在しないログターゲットを指定されたときのエラーコード
*/
var ERR_CODE_LOG_TARGETS_IS_NONE = 10004;
/**
* カテゴリに文字列以外または空文字を指定したときのエラーコード
*/
var ERR_CODE_CATEGORY_INVALID = 10005;
/**
* ログターゲット(targets)が複数回指定されたときのエラーコード
*/
var ERR_CODE_LOG_TARGETS_NAMED_MULTIPLE_TIMES = 10007;
/**
* ログターゲット(targets)に文字列以外または空文字を指定されたときのエラーコード
*/
var ERR_CODE_LOG_TARGETS_INVALID = 10008;
/**
* ログターゲット(target)にオブジェクト以外を指定されたときのエラーコード
*/
var ERR_CODE_LOG_TARGET_INVALID = 10009;
/**
* out.categoryが指定されていないときのエラーコード
*/
var ERR_CODE_OUT_CATEGORY_INVALID = 10010;
/**
* スタックトレース出力時に1行目(メッセージ部)に表示するトレース件数
*/
var PREVIEW_TRACE_COUNT = 3;
// =============================
// Development Only
// =============================
/* del begin */
/**
* 各エラーコードに対応するメッセージ
*/
var errMsgMap = {};
errMsgMap[ERR_CODE_LOG_TARGET_TYPE] = 'ログターゲットのtypeには、オブジェクト、もしくは"console"のみ指定可能です。';
errMsgMap[ERR_CODE_LEVEL_INVALID] = 'level"{0}"の指定は不正です。Number、もしくはtrace, info, debug, warn, error, noneを指定してください。';
errMsgMap[ERR_CODE_LOG_TARGETS_NAMED_MULTIPLE_TIMES] = 'ログターゲット"{0}"が複数回指定されています。';
errMsgMap[ERR_CODE_LOG_TARGETS_IS_NONE] = '"{0}"という名前のログターゲットはありません。';
errMsgMap[ERR_CODE_CATEGORY_INVALID] = 'categoryは必須項目です。空文字で無い文字列を指定して下さい。';
errMsgMap[ERR_CODE_LOG_TARGETS_INVALID] = 'ログターゲット(targets)の指定は1文字以上の文字列、または配列で指定してください。';
errMsgMap[ERR_CODE_LOG_TARGET_INVALID] = 'ログターゲット(target)の指定はプレーンオブジェクトで指定してください。';
errMsgMap[ERR_CODE_OUT_CATEGORY_INVALID] = 'outの各要素についてcategoryは文字列で指定する必要があります。';
// メッセージの登録
addFwErrorCodeMap(errMsgMap);
/* del end */
// =========================================================================
//
// Cache
//
// =========================================================================
// =========================================================================
//
// Privates
//
// =========================================================================
// =============================
// Variables
// =============================
var logLevel = {
/**
* ログレベル: ERROR
*
* @memberOf Log.LEVEL
* @const {Object} ERROR
* @type Number
*/
ERROR: 50,
/**
* ログレベル: WARN
*
* @memberOf Log.LEVEL
* @const {Object} WARN
* @type Number
*/
WARN: 40,
/**
* ログレベル: INFO
*
* @memberOf Log.LEVEL
* @const {Object} INFO
* @type Number
*/
INFO: 30,
/**
* ログレベル: DEBUG
*
* @memberOf Log.LEVEL
* @const {Object} DEBUG
* @type Number
*/
DEBUG: 20,
/**
* ログレベル: TRACE
*
* @memberOf Log.LEVEL
* @const {Object} TRACE
* @type Number
*/
TRACE: 10,
/**
* ログレベル: ALL
*
* @memberOf Log.LEVEL
* @const {Object} ALL
* @type Number
*/
ALL: 0,
/**
* ログレベル: NONE
*
* @memberOf Log.LEVEL
* @const {Object} NONE
* @type Number
*/
NONE: -1
};
// コンパイル済ログ設定
var compiledLogSettings = null;
// =============================
// Functions
// =============================
/**
* 指定されたレベルを文字列に変換します。
*/
function levelToString(level) {
if (level === logLevel.ERROR) {
return 'ERROR';
} else if (level === logLevel.WARN) {
return 'WARN';
} else if (level === logLevel.INFO) {
return 'INFO';
} else if (level === logLevel.DEBUG) {
return 'DEBUG';
} else if (level === logLevel.TRACE) {
return 'TRACE';
}
}
/**
* 指定された文字列をレベルに変換します。
*/
function stringToLevel(str) {
if (str.match(/^error$/i)) {
return logLevel.ERROR;
} else if (str.match(/^warn$/i)) {
return logLevel.WARN;
} else if (str.match(/^info$/i)) {
return logLevel.INFO;
} else if (str.match(/^debug$/i)) {
return logLevel.DEBUG;
} else if (str.match(/^trace$/i)) {
return logLevel.TRACE;
} else if (str.match(/^all$/i)) {
return logLevel.ALL;
} else if (str.match(/^none$/i)) {
return logLevel.NONE;
} else {
return null;
}
}
/**
* トレース情報からトレース結果のオブジェクト取得します。
* <p>
* 以下のようなオブジェクトを返します
* </p>
*
* <pre><code>
* {
* all: maxStackSize maxStackSizeまでのトレース結果を改行で結合した文字列
* preview: 最大でPREVIEW_TRACE_COUNTまでのトレース結果を" <- "で結合した文字列 "[func1_2 () <- func1_1 () <- func1 () ...]"
* }
* </code></pre>
*
* @param {String[]} traces トレース結果
* @param {Integer} maxStackSize 最大トレース数
*/
function getFormattedTraceMessage(traces, maxStackSize) {
var result = {};
var slicedTraces = traces.slice(0, maxStackSize);
var previewLength = Math.min(PREVIEW_TRACE_COUNT, maxStackSize);
var preview = slicedTraces.slice(0, previewLength).join(' <- ');
if (slicedTraces.length > previewLength) {
preview += ' ...';
}
result.preview = preview;
result.all = slicedTraces.join('\n');
return result;
}
/**
* 指定されたFunction型のオブジェクトから、名前を取得します。
*
* @param {Function} fn
*/
function getFunctionName(fn) {
var ret = '';
if (!fn.name) {
var regExp = /^\s*function\s*([\w\-\$]+)?\s*\(/i;
regExp.test(fn.toString());
ret = RegExp.$1;
} else {
ret = fn.name;
}
return ret;
}
/**
* 指定されたFunction型のオブジェクトから、引数の型の一覧を取得します。
*/
function parseArgs(args) {
var argArray = h5.u.obj.argsToArray(args);
var result = [];
for (var i = 0, len = argArray.length; i < len; i++) {
result.push($.type(argArray[i]));
}
return result.join(', ');
}
// =========================================================================
//
// Body
//
// =========================================================================
/**
* コンソールにログを出力するログターゲット
*
* @name ConsoleLogTarget
* @constructor
*/
function ConsoleLogTarget() {
// 空コンストラクタ
}
ConsoleLogTarget.prototype = {
/**
* コンソールログターゲットの初期化を行います。
*
* @memberOf ConsoleLogTarget
* @function
* @param {Object} param 初期化パラメータ
*/
init: function(param) {
// 今は特定のパラメータはない
},
/**
* ログをコンソールに出力します。
*
* @memberOf ConsoleLogTarget
* @function
* @param {Object} logObj ログ情報を保持するオブジェクト
*/
log: function(logObj) {
if (!window.console) {
return;
}
var args = logObj.args;
if (!isString(args[0])) {
this._logObj(logObj);
} else {
this._logMsg(logObj);
}
},
/**
* 指定された文字列をコンソールに出力します。
*
* @memberOf ConsoleLogTarget
* @private
* @function
* @param {Object} logObj ログ情報を保持するオブジェクト
*/
_logMsg: function(logObj) {
var args = logObj.args;
var msg = null;
if (args.length === 1) {
msg = args[0];
} else {
msg = h5.u.str.format.apply(h5.u.str, args);
}
var logMsg = this._getLogPrefix(logObj) + msg;
if (logObj.logger.enableStackTrace) {
logMsg += ' [' + logObj.stackTrace.preview + ']';
}
if (logObj.logger.enableStackTrace && console.groupCollapsed) {
console.groupCollapsed(logMsg);
} else {
this._consoleOut(logObj.level, logMsg);
}
if (logObj.logger.enableStackTrace) {
// if (console.trace) {
// console.trace();
// } else {
this._consoleOut(logObj.level, logObj.stackTrace.all);
// }
}
if (logObj.logger.enableStackTrace && console.groupEnd) {
console.groupEnd();
}
},
_consoleOut: function(level, str) {
var logPrinted = false;
// 専用メソッドがあればそれを使用して出力
if ((level == logLevel.ERROR) && console.error) {
console.error(str);
logPrinted = true;
} else if ((level == logLevel.WARN) && console.warn) {
console.warn(str);
logPrinted = true;
} else if ((level == logLevel.INFO) && console.info) {
console.info(str);
logPrinted = true;
} else if ((level == logLevel.DEBUG) && console.debug) {
console.debug(str);
logPrinted = true;
}
if (!logPrinted && console.log) {
// this.trace()の場合、または固有メソッドがない場合はlogメソッドで出力
console.log(str);
}
},
/**
* 出力するログのプレフィックスを作成します。
*
* @memberOf ConsoleLogTarget
* @private
* @function
* @param {Object} logObj ログ情報を保持するオブジェクト
* @return ログのプレフィックス
*/
_getLogPrefix: function(logObj) {
return '[' + logObj.levelString + ']' + logObj.date.getHours() + ':'
+ logObj.date.getMinutes() + ':' + logObj.date.getSeconds() + ','
+ logObj.date.getMilliseconds() + ': ';
},
/**
* 指定されたオブジェクトをコンソールに出力します。
*
* @memberOf ConsoleLogTarget
* @private
* @function
* @param {Object} logObj ログ情報を保持するオブジェクト
*/
_logObj: function(logObj) {
// 専用メソッドがあればそれを使用して出力
var args = logObj.args;
var prefix = this._getLogPrefix(logObj);
args.unshift(prefix);
if ((logObj.level == logLevel.ERROR) && console.error) {
this._output(console.error, args);
} else if ((logObj.level == logLevel.WARN) && console.warn) {
this._output(console.warn, args);
} else if ((logObj.level == logLevel.INFO) && console.info) {
this._output(console.info, args);
} else if ((logObj.level == logLevel.DEBUG) && console.debug) {
this._output(console.debug, args);
} else {
this._output(console.log, args);
}
},
_output: function(func, args) {
try {
// IEでは、console.log/error/info/warnにapplyがない。
// IE11ではapplyを参照しただけでエラーが発生するので、
// try-catchの中でfunc.applyがあるかどうか確認する
if (func.apply) {
// IE以外では、applyを使って呼び出さないと『TypeError:Illegal invocation』が発生する
func.apply(console, args);
return;
}
} catch (e) {
// 何もしない
}
func(args);
}
};
/**
* h5.settings.logにあるログ設定を適用します。
*
* @function
* @name configure
* @memberOf h5.log
*/
var configure = function() {
// defaultOutのデフォルト
var defaultOut = {
level: 'NONE',
targets: null
};
/* del begin */
// h5.dev.jsではデフォルトのdefaultOutをログ出力するようにしておく。
defaultOut = {
level: 'debug',
targets: 'console'
};
/* del end */
// 設定オブジェクト
var settings = $.extend(true, {}, h5.settings.log);
// デフォルトアウトの設定
var dOut = settings.defaultOut;
if (!dOut) {
dOut = defaultOut;
settings.defaultOut = dOut;
}
function compileLogTarget(targets) {
if (!$.isPlainObject(targets)) {
throwFwError(ERR_CODE_LOG_TARGET_INVALID);
}
for ( var prop in targets) {
var obj = targets[prop];
var type = $.type(obj.type);
// 今は"remote"でもエラーとなる
if (type !== 'object' && obj.type !== 'console') {
throwFwError(ERR_CODE_LOG_TARGET_TYPE);
}
var compiledTarget = null;
if (obj.type === 'console') {
compiledTarget = new ConsoleLogTarget();
} else {
// typeがオブジェクトの場合
var clone = $.extend(true, {}, obj.type);
compiledTarget = clone;
}
if (compiledTarget.init) {
compiledTarget.init(obj);
}
obj.compiledTarget = compiledTarget;
}
targets.console = {
type: 'console',
compiledTarget: new ConsoleLogTarget()
};
}
var categoryCache = [];
function compileOutput(_logTarget, out, isDefault) {
if (!isDefault) {
// デフォルトアウトでない場合はcategoryの設定を行う
var category = out.category;
if (!isString(category) || $.trim(category).length === 0) {
throwFwError(ERR_CODE_OUT_CATEGORY_INVALID);
}
category = $.trim(category);
out.compiledCategory = getRegex(category);
categoryCache.push(category);
}
// レベルのコンパイル(数値化)
var compiledLevel;
if (out.level == null) {
compiledLevel = stringToLevel(isDefault ? defaultOut.level : dOut.level);
} else {
compiledLevel = isString(out.level) ? stringToLevel($.trim(out.level)) : out.level;
}
if (typeof compiledLevel !== 'number') {
throwFwError(ERR_CODE_LEVEL_INVALID, out.level);
}
out.compiledLevel = compiledLevel;
// ターゲットのコンパイル
var compiledTargets = [];
var targets = out.targets;
if (targets != null) {
var targetNames = [];
// targetsの指定は文字列または配列またはnull,undefinedのみ
if (!(targets == null || isArray(targets) || (isString(targets) && $.trim(targets).length))) {
throwFwError(ERR_CODE_LOG_TARGETS_INVALID);
}
targets = wrapInArray(targets);
for (var i = 0, len = targets.length; i < len; i++) {
if (!(targets[i] == null || (isString(targets[i]) && $.trim(targets[i]).length))) {
throwFwError(ERR_CODE_LOG_TARGETS_INVALID);
}
var targetName = targets[i];
if (!targetName) {
continue;
}
if ($.inArray(targetName, targetNames) !== -1) {
throwFwError(ERR_CODE_LOG_TARGETS_NAMED_MULTIPLE_TIMES, targetName);
}
var l = _logTarget[targetName];
if (!l) {
throwFwError(ERR_CODE_LOG_TARGETS_IS_NONE, targetName);
}
targetNames.push(targetName);
compiledTargets.push(l.compiledTarget);
}
}
out.compiledTargets = compiledTargets;
}
// ログターゲットをコンパイル
var logTarget = settings.target;
if (!logTarget) {
logTarget = {};
settings.target = logTarget;
}
compileLogTarget(logTarget);
// 出力定義をコンパイル
compileOutput(logTarget, dOut, true);
var outs = settings.out;
if (outs) {
outs = wrapInArray(outs);
for (var i = 0, len = outs.length; i < len; i++) {
compileOutput(logTarget, outs[i]);
}
}
// ここまでの処理でエラーが起きなかったら設定を適用する
compiledLogSettings = settings;
};
/**
* ログを生成するクラス
*
* @class
* @name Log
*/
function Log(category) {
// categoryの指定が文字列以外、または空文字、空白文字ならエラー。
if (!isString(category) || $.trim(category).length === 0) {
throwFwError(ERR_CODE_CATEGORY_INVALID);
}
/**
* ログカテゴリ
*
* @memberOf Log
* @type String
* @name category
*/
this.category = $.trim(category);
}
Log.prototype = {
/**
* ログ出力時、スタックトレース(関数呼び出し関係)を表示するか設定します。<br>
* (デフォルト: false[表示しない])
*
* @type Boolean
* @memberOf Log
*/
enableStackTrace: false,
/**
* ログに表示するトレースの最大数を設定します。<br>
* (デフォルト:10)
*
* @type Number
* @memberOf Log
*/
maxStackSize: 10,
/**
* LEVEL.ERROR レベルのログを出力します。
* <p>
* 引数がObject型の場合はオブジェクト構造を、String型の場合は引数の書式に合わせてログを出力します。
* <p>
* 書式については、h5.u.str.format関数のドキュメントを参照下さい。
*
* @see h5.u.str.format
* @memberOf Log
* @function
* @param {Any} var_args コンソールに出力する内容
*/
error: function(var_args) {
this._log(logLevel.ERROR, arguments, this.error);
},
/**
* LEVEL.WARN レベルのログを出力します。
* <p>
* 引数がObject型の場合はオブジェクト構造を、String型の場合は引数の書式に合わせてログを出力します。
* <p>
* 書式については、h5.u.str.format関数のドキュメントを参照下さい。
*
* @see h5.u.str.format
* @memberOf Log
* @function
* @param {Any} var_args コンソールに出力する内容
*/
warn: function(var_args) {
this._log(logLevel.WARN, arguments, this.warn);
},
/**
* LEVEL.INFO レベルのログを出力します。
* <p>
* 引数がObject型の場合はオブジェクト構造を、String型の場合は引数の書式に合わせてログを出力します。
* <p>
* 書式については、h5.u.str.format関数のドキュメントを参照下さい。
*
* @see h5.u.str.format
* @memberOf Log
* @function
* @param {Any} var_args コンソールに出力する内容
*/
info: function(var_args) {
this._log(logLevel.INFO, arguments, this.info);
},
/**
* LEVEL.DEBUG レベルのログを出力します。
* <p>
* 引数がObject型の場合はオブジェクト構造を、String型の場合は引数の書式に合わせてログを出力します。
* <p>
* 書式については、h5.u.str.format関数のドキュメントを参照下さい。
*
* @see h5.u.str.format
* @function
* @memberOf Log
* @param {Any} var_args コンソールに出力する内容
*/
debug: function(var_args) {
this._log(logLevel.DEBUG, arguments, this.debug);
},
/**
* LEVEL.TRACE レベルのログを出力します。
* <p>
* 引数がObject型の場合はオブジェクト構造を、String型の場合は引数の書式に合わせてログを出力します。
* <p>
* 書式については、h5.u.str.format関数のドキュメントを参照下さい。
*
* @see h5.u.str.format
* @memberOf Log
* @function
* @param {Any} var_args コンソールに出力する内容
*/
trace: function(var_args) {
this._log(logLevel.TRACE, arguments, this.trace);
},
/**
* スタックトレース(関数呼び出し関係)を取得します。
*
* @private
* @memberOf Log
* @function
* @param fn {Function} トレース対象の関数
* @returns {Object} 以下のようなオブジェクトを返します
*
* <pre><code>
* {
* all: maxStackSize maxStackSizeまでのトレース結果を改行で結合した文字列
* preview: 最大でPREVIEW_TRACE_COUNTまでのトレース結果を" <- "で結合した文字列 "[func1_2 () <- func1_1 () <- func1 () ...]"
* }
* </code></pre>
*/
_traceFunctionName: function(fn) {
var traces = [];
// エラーオブジェクトを生成してスタックトレースを取得
var e = new Error();
var errMsg = e.stack || e.stacktrace;
if (errMsg) {
// stackまたはstacktraceがある場合(IE,Safari以外)
// stackにはFW内部の関数も含まれるので、それを取り除く
// new Error()を呼んだ場合に関数呼び出し3つ分省略すればいいが、minifyするとnew演算子が省略される
// Chrome,FireFoxではnew演算子を省略するコンストラクト呼び出しがstackに入り、newを使った場合と結果が異なる
// Operaではnew演算子を省略しても結果は変わらない
// min版、dev版の互換とブラウザ互換をとるために、取り除く関数呼び出しはここの関数名を基点に数えて取り除く
var CURRENT_FUNCTION_REGEXP = /_traceFunctionName/;
// トレースされたログのうち、ここの関数から3メソッド分先までの関数呼び出しはログに出力しない。
// (_traceFunction, _log, debug|info|warn|error|trace の3つ。この関数+2の箇所でsliceする)
var DROP_TRACE_COUNT = 3;
traces = errMsg.replace(/\r\n/, '\n').replace(
/at\b|@|Error\b|\t|\[arguments not available\]/ig, '').replace(
/(http|https|file):.+[0-9]/g, '').replace(/ +/g, ' ').split('\n');
var ret = null;
var currentFunctionIndex = null;
traces = $.map(traces, function(value, index) {
if (value.length === 0) {
// 不要なデータはnullを返して削除(Chromeは配列の先頭, FireFoxは配列の末尾に存在する)
// ただしslice箇所が決定する前は削除しない(nullを返さないようにする)
return currentFunctionIndex == null ? '' : null;
} else if ($.trim(value) === '') {
ret = '{anonymous}'; // ログとして出力されたが関数名が無い
} else {
ret = $.trim(value);
}
if (currentFunctionIndex === null && CURRENT_FUNCTION_REGEXP.test(value)) {
currentFunctionIndex = index;
}
return ret;
}).slice(currentFunctionIndex + DROP_TRACE_COUNT);
} else {
// IE, Safari
// 呼び出された関数を辿って行ったときに"use strict"宣言を含む関数がある場合、
// IE11だとcallerプロパティへアクセスすると以下のようにエラーが発生する
// 『strict モードでは、関数または arguments オブジェクトの 'caller' プロパティを使用できません』
// (例えばjQuery1.9.0は"use strict"宣言がされており、jQuery1.9.0内の関数を経由して呼ばれた関数は全てstrictモード扱いとなり、
// callerプロパティにアクセスできない)
// そのため、try-catchで囲んで、取得できなかった場合は{unable to trace}を出力する
// fnは、(debug|info|warn|error|trace)の何れかなので、その呼び出し元から辿る
var caller = fn.caller;
for (var i = 0, l = this.maxStackSize; i < l; i++) {
var funcName = getFunctionName(caller);
var argStr = parseArgs(caller.arguments);
var nextCaller;
try {
nextCaller = caller.caller;
} catch (e) {
// エラーが発生してトレースできなくなったら終了
traces.push('{unable to trace}');
break;
}
if (funcName) {
// 関数名が取得できているときは関数名を表示
traces.push('{' + funcName + '}(' + argStr + ')');
} else if (nextCaller) {
// 関数名は取得できていなくても次の関数ができているなら{anonymous}として表示
traces.push('{anonymous}(' + argStr + ')');
} else {
// 次の関数が無い場合はルートからの呼び出し
traces.push('{root}(' + argStr + ')');
}
if (!nextCaller) {
// これ以上トレースできないので終了
break;
}
caller = nextCaller;
}
}
return getFormattedTraceMessage(traces, this.maxStackSize);
},
/**
* ログ情報を保持するオブジェクトに以下の情報を付与し、コンソールまたはリモートサーバにログを出力します。
* <ul>
* <li>時刻
* <li>ログの種別を表す文字列(ERROR, WARN, INFO, DEBUG, TRACE, OTHER)
* </ul>
*
* @private
* @memberOf Log
* @function
* @param {Number} level ログレベル
* @param {Arguments} args 引数
* @param {Function} func 元々呼ばれた関数
*/
_log: function(level, args, func) {
var logObj = {
level: level,
args: h5.u.obj.argsToArray(args),
stackTrace: this.enableStackTrace ? this._traceFunctionName(func) : ''
};
var outs = compiledLogSettings.out;
var defaultOut = compiledLogSettings.defaultOut;
var targetOuts = [];
var terminated = false;
if (outs) {
outs = wrapInArray(outs);
for (var i = 0, len = outs.length; i < len; i++) {
var out = outs[i];
if (out.compiledCategory.test(this.category)
&& (level >= out.compiledLevel && out.compiledLevel >= 0)) {
// カテゴリとレベル指定を満たした出力定義が出力対象
targetOuts.push(out);
if (out.terminate !== false) {
// terminate:falseが明示的に指定されていない場合、出力定義にマッチするかどうかの探索を打ち切る
terminated = true;
break;
}
}
}
}
if (!targetOuts.length || !terminated) {
// いずれの出力定義の条件も満たさなかったまたは、何れかの条件を満たしたが、terminateしていない場合は、defaultOutも出力対象
targetOuts.push(defaultOut);
}
for (var i = 0, l = targetOuts.length; i < l; i++) {
var targetOut = targetOuts[i];
var levelThreshold = targetOut.compiledLevel;
var logTarget = targetOut.compiledTargets;
if (level < levelThreshold || levelThreshold < 0) {
return;
}
logObj.logger = this;
logObj.date = new Date();
logObj.levelString = this._levelToString(level);
if (!logTarget || logTarget.length === 0) {
return;
}
for (var j = 0, len = logTarget.length; j < len; j++) {
logTarget[j].log(logObj);
}
}
},
/**
* ログレベルを判定して、ログの種別を表す文字列を取得します。
*
* @private
* @memberOf Log
* @function
* @param {Object} level
*/
_levelToString: levelToString
};
/**
* ロガーを作成します。
*
* @param {String} [category=null] カテゴリ.
* @returns {Log} ロガー.
* @name createLogger
* @function
* @memberOf h5.log
* @see Log
*/
var createLogger = function(category) {
return new Log(category);
};
// =============================
// Expose to window
// =============================
/**
* @namespace
* @name log
* @memberOf h5
*/
h5.u.obj.expose('h5.log', {
createLogger: createLogger,
configure: configure
});
})();