@waiting/log
Version:
Lightweight logging for browser
298 lines (281 loc) • 8.37 kB
JavaScript
/**
* @waiting/log
* Lightweight logging for browser
*
* @version 1.0.2
* @author waiting
* @license MIT
* @link https://github.com/waitingsong/log#readme
*/
const defaultConfig = {
maxMsgLength: 1024,
runLevel: 'log',
persist: true,
persistTTL: 7 * 24 * 3600,
storagePrefix: 'log',
};
var LogLevel;
(function (LogLevel) {
LogLevel[LogLevel['trace'] = 0] = 'trace';
LogLevel[LogLevel['debug'] = 1] = 'debug';
LogLevel[LogLevel['log'] = 2] = 'log';
LogLevel[LogLevel['info'] = 3] = 'info';
LogLevel[LogLevel['warn'] = 4] = 'warn';
LogLevel[LogLevel['error'] = 5] = 'error';
LogLevel[LogLevel['silent'] = 6] = 'silent';
})(LogLevel || (LogLevel = {}));
/** Whether the key of LocalStorage item is generated myself */
function isLocalStorageKey(key, storagePrefix) {
const arr = key.split('-');
/* istanbul ignore else */
if (arr.length < 3) {
return false
}
const prefix = arr.shift();
const level = arr.shift();
const time = arr.join('-');
/* istanbul ignore else */
if (prefix !== storagePrefix) {
return false
}
/* istanbul ignore else */
if (!level) {
return false
}
if (!time) {
return false
}
else {
const dd = new Date(time);
/* istanbul ignore else */
if (typeof dd.getTime !== 'function' || Number.isNaN(dd.getTime())) {
return false
}
}
return true
}
/** Whether supress the log level if lower then the runLevel */
function isSuppressLogLevel(runLevel, logLevel) {
return LogLevel[logLevel] < LogLevel[runLevel] ? true : false
}
function isLogLevelToPrune(logLevel, pruneLevel) {
/* istanbul ignore else */
if (!logLevel) {
return false
}
/* istanbul ignore else */
if (!pruneLevel) {
return true
}
return logLevel === pruneLevel ? true : false
}
function isTimeToPrune(time, pruneTime) {
if (!time) {
return false
}
const dd = new Date(time);
return dd < pruneTime ? true : false
}
function setMaxMsgLength(length) {
validateMaxMsgLength(length);
defaultConfig.maxMsgLength = Math.ceil(length);
}
function validateMaxMsgLength(length) {
/* istanbul ignore else */
if (typeof length !== 'number' || length <= 0) {
throw new TypeError('Value of parameter maxMsgLenth invalid')
}
}
function setPersist(persist) {
validatePersist(persist);
defaultConfig.persist = persist;
}
function validatePersist(persist) {
/* istanbul ignore else */
if (typeof persist !== 'boolean') {
throw new TypeError('Value of parameter persist invalid')
}
}
function setPersistTTL(ttl) {
validatePersistTTL(ttl);
defaultConfig.persistTTL = Math.ceil(ttl);
}
function validatePersistTTL(ttl) {
/* istanbul ignore else */
if (typeof ttl !== 'number') {
throw new TypeError('Value of parameter ttl invalid')
}
/* istanbul ignore else */
if (+ttl < 0) {
throw new TypeError('Value of parameter ttl invalid')
}
}
/** Set runLevel to supressing the logLevel listed in ENUM LogLevel which lower then the runLevel */
function setRunLevel(runLevel) {
validateLogLevel(runLevel);
defaultConfig.runLevel = runLevel;
}
function validateLogLevel(logLevel) {
/* istanbul ignore else */
// @ts-ignore
if (logLevel !== 'silent' && typeof console[logLevel] !== 'function') {
throw new TypeError(`Function console.${logLevel}() NOT exists`)
}
/* istanbul ignore else */
else if (!logLevel || typeof LogLevel[logLevel] !== 'number') {
throw new TypeError('Value of parameter logLevel invalid: ' + logLevel)
}
}
/** minus(-) be convert to underline _ */
function setStoragePrefix(key) {
validateStoragePrefix(key);
defaultConfig.storagePrefix = key.replace(/-/g, '_');
}
function validateStoragePrefix(key) {
/* istanbul ignore else */
if (!key || typeof key !== 'string') {
throw new TypeError('Value of parameter key invalid')
}
}
/**
* Save message into LocalStorage
*
* @returns key of LocalStorage item, blank if 'silent'
*/
function localSave(level, data, prefix, maxLen) {
/* istanbul ignore else */
if (level === 'silent') {
return ''
}
const time = new Date().toISOString();
const key = `${prefix}-${level}-${time}`;
save(key, data, maxLen);
return key
}
function save(key, data, maxLen) {
let cont = data;
/* istanbul ignore else */
if (typeof data === 'string' && data.length > maxLen) {
cont = data.slice(0, maxLen) + ' ...';
}
const content = JSON.stringify(cont);
/* istanbul ignore else */
if (typeof localStorage === 'object') {
try {
localStorage.setItem(encodeURIComponent(key), content);
}
catch (ex) {
console.error(ex);
}
}
}
function logger(level, message) {
/* istanbul ignore else */
if (level === 'silent') {
return
}
if (Array.isArray(message)) {
console.group('Group log:');
// tslint:disable-next-line:prefer-for-of
for (let i = 0; i < message.length; i++) {
// @ts-ignore
console[level](message[i]);
}
console.groupEnd();
}
else {
// @ts-ignore
console[level](message);
}
}
function trace(data, persist) {
return proxy('trace', data, persist)
}
function debug(data, persist) {
return proxy('debug', data, persist)
}
function log(data, persist) {
return proxy('log', data, persist)
}
function info(data, persist) {
return proxy('info', data, persist)
}
function warn(data, persist) {
return proxy('warn', data, persist)
}
function error(data, persist) {
return proxy('error', data, persist)
}
function silent(data, persist) {
return proxy('silent', data, persist)
}
/** Get copy of defaultConfig */
function getConfig() {
return Object.assign({}, defaultConfig)
}
/** Set value of key of defaultConfig and return copy of defaultConfig */
function setConfig(config) {
if (config && typeof config === 'object') {
for (const [key, value] of Object.entries(config)) {
switch (key) {
case 'maxMsgLength':
setMaxMsgLength(value);
break
case 'persist':
setPersist(value);
break
case 'persistTTL':
setPersistTTL(value);
break
case 'runLevel':
setRunLevel(value);
break
case 'storagePrefix':
setStoragePrefix(value);
break
/* istanbul ignore next */
default:
info(`setConfig(config): value of param invalid: key "${key}"/value "${value}"`);
break
}
}
}
else {
info(`setConfig(config): value of param invalid: "${config}"`);
}
return getConfig()
}
function getAvailableLogLevel() {
const ret = [];
Object.keys(LogLevel).forEach(key => {
if (key && typeof key === 'string' && Number.isNaN(+key)) {
try {
validateLogLevel(key);
ret.push(key);
}
catch (ex) {
// void
}
}
});
return ret
}
/**
* @returns void or key of LocalStorage Item (if persist true)
*/
function proxy(level, data, persist) {
/* istanbul ignore else */
if (isSuppressLogLevel(defaultConfig.runLevel, level)) {
return
}
/* istanbul ignore else */
if (level === 'silent') {
return
}
logger(level, data);
const persistNew = typeof persist === 'boolean' ? persist : defaultConfig.persist;
if (persistNew) {
localSave(level, data, defaultConfig.storagePrefix, defaultConfig.maxMsgLength);
}
}
export { trace, debug, log, info, warn, error, silent, getConfig, setConfig, getAvailableLogLevel, LogLevel, isLocalStorageKey, isSuppressLogLevel, isLogLevelToPrune, isTimeToPrune, setMaxMsgLength, validateMaxMsgLength, setPersist, validatePersist, setPersistTTL, validatePersistTTL, setRunLevel, validateLogLevel, setStoragePrefix, validateStoragePrefix };