logging/logger.js

'use strict';

/**
 * @author schukai GmbH
 */

import {Monster} from '../namespace.js';
import {validateInteger, validateObject, validateString} from '../types/validate.js';
import {Handler} from '../logging/handler.js';
import {LogEntry} from '../logging/logentry.js';
import {Base} from '../types/base.js';


/**
 * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF
 * @type {number}
 * @memberOf Monster/Logging
 */
const ALL = 255;
/**
 * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF
 * @type {number}
 * @memberOf Monster/Logging
 */
const TRACE = 64;
/**
 * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF
 * @type {number}
 * @memberOf Monster/Logging
 */
const DEBUG = 32;
/**
 * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF
 * @type {number}
 * @memberOf Monster/Logging
 */
const INFO = 16;
/**
 * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF
 * @type {number}
 * @memberOf Monster/Logging
 */
const WARN = 8;
/**
 * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF
 * @type {number}
 * @memberOf Monster/Logging
 */
const ERROR = 4;
/**
 * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF
 * @type {number}
 * @memberOf Monster/Logging
 */
const FATAL = 2;
/**
 * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF
 * @type {number}
 * @memberOf Monster/Logging
 */
const OFF = 0;

/**
 * you can call the method via the monster namespace `new Monster.Logging.Logger()`.
 *
 * ```
 * <script type="module">
 * import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.6.0/dist/modules/logging/logger.js';
 * console.log(new Monster.Logging.Logger())
 * </script>
 * ```
 *
 * Alternatively, you can also integrate this function individually.
 *
 * ```
 * <script type="module">
 * import {ID} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.6.0/dist/modules/logging/logger.js';
 * console.log(new Logger())
 * </script>
 * ```
 *
 * @since 1.5.0
 * @copyright schukai GmbH
 * @memberOf Monster/Logging
 */
class Logger extends Base {

    /**
     *
     */
    constructor() {
        super();
        this.handler = new Set;
    }

    /**
     *
     * @param {Handler} handler
     * @returns {Logger}
     * @throws {Error} the handler must be an instance of Handler
     */
    addHandler(handler) {
        validateObject(handler)
        if (!(handler instanceof Handler)) {
            throw new Error("the handler must be an instance of Handler")
        }

        this.handler.add(handler)
        return this;
    }

    /**
     *
     * @param {Handler} handler
     * @returns {Logger}
     * @throws {Error} the handler must be an instance of Handler
     */
    removeHandler(handler) {
        validateObject(handler)
        if (!(handler instanceof Handler)) {
            throw new Error("the handler must be an instance of Handler")
        }

        this.handler.delete(handler);
        return this;
    }

    /**
     * log Trace message
     *
     * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF  (ALL = 0xff;OFF = 0x00;
     *
     * @param {*} arguments
     * @returns {Logger}
     * @since 1.5.0
     */
    logTrace() {
        triggerLog.apply(this, [TRACE, ...arguments]);
        return this;
    };

    /**
     * log Debug message
     *
     * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF  (ALL = 0xff;OFF = 0x00;
     *
     * @param {*} arguments
     * @returns {Logger}
     * @since 1.5.0
     */
    logDebug() {
        triggerLog.apply(this, [DEBUG, ...arguments]);
        return this;
    };

    /**
     * log Info message
     *
     * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF  (ALL = 0xff;OFF = 0x00;
     *
     *
     * @param {*} arguments
     * @returns {Logger}
     * @since 1.5.0
     */
    logInfo() {
        triggerLog.apply(this, [INFO, ...arguments]);
        return this;
    };

    /**
     * log Warn message
     *
     * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF  (ALL = 0xff;OFF = 0x00;
     *
     * @param {*} arguments
     * @returns {Logger}
     * @since 1.5.0
     */
    logWarn() {
        triggerLog.apply(this, [WARN, ...arguments]);
        return this;
    };

    /**
     * log Error message
     *
     * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF  (ALL = 0xff;OFF = 0x00;
     *
     * @param {*} arguments
     * @returns {Logger}
     * @since 1.5.0
     */
    logError() {
        triggerLog.apply(this, [ERROR, ...arguments]);
        return this;
    };

    /**
     * log Fatal message
     *
     * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF  (ALL = 0xff;OFF = 0x00;
     *
     * @param {*} arguments
     * @returns {Logger}
     * @since 1.5.0
     */
    logFatal() {
        triggerLog.apply(this, [FATAL, ...arguments]);
        return this;
    };


    /**
     * Labels
     *
     * @param {integer} level
     * @returns {string}
     */
    getLabel(level) {
        validateInteger(level);

        if (level === ALL) return 'ALL';
        if (level === TRACE) return 'TRACE';
        if (level === DEBUG) return 'DEBUG';
        if (level === INFO) return 'INFO';
        if (level === WARN) return 'WARN';
        if (level === ERROR) return 'ERROR';
        if (level === FATAL) return 'FATAL';
        if (level === OFF) return 'OFF';

        return 'unknown';
    };

    /**
     * Level
     *
     * @param {string} label
     * @returns {integer}
     */
    getLevel(label) {
        validateString(label);

        if (label === 'ALL') return ALL;
        if (label === 'TRACE') return TRACE;
        if (label === 'DEBUG') return DEBUG;
        if (label === 'INFO') return INFO;
        if (label === 'WARN') return WARN;
        if (label === 'ERROR') return ERROR;
        if (label === 'FATAL') return FATAL;
        if (label === 'OFF') return OFF;

        return 0;
    };


}

Monster.assignToNamespace('Monster.Logging', Logger);
export {Monster, Logger, ALL, TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF};


/**
 * Log triggern
 *
 * @param {integer} loglevel
 * @param {*} args
 * @returns {Logger}
 * @private
 */
function triggerLog(loglevel, ...args) {
    var logger = this;

    for (let handler of logger.handler) {
        handler.log(new LogEntry(loglevel, args))
    }

    return logger;

}