/**
* StreamRoller Copyright 2023 "SilenusTA https://www.twitch.tv/olddepressedgamer"
*
* StreamRoller is an all in one streaming solution designed to give a single
* 'second monitor' control page and allow easy integration for configuring
* content (ie. tweets linked to chat, overlays triggered by messages, hue lights
* controlled by donations etc)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
// ############################# LOGGER.js ####################################
// This file is to handle all our logging in one place. If you need to add
// logging to the code use this inport to do it so it can easily be turn on
// or off as required.
// ---------------------------- creation --------------------------------------
// Author: Silenus aka twitch.tv/OldDepressedGamer
// GitHub: https://github.com/SilenusTA/StreamRoller
// Date: 14-Jan-2021
// --------------------------- functionality ----------------------------------
// Adds console messages for logging, errors and warnings.
// .....
// Environment variable "STREAMTOOL_DEBUG_LEVEL" can be changed to format
// the output.
// Options include
// 0 : errors only (always on)
// 1 : warn and err
// 2 : log, warn and err
// 3 : log, info, awrn and err.
// 4 : extra, additional info/heavy logging
// *** no flag set defaults to standard logging
// .....
// Environment variable "STREAMTOOL_DEBUG_FORMAT" can be changed to format
// the output.
// Options include
// extended, extended-line, off
// *** no flag set defaults to standard logging
// ----------------------------- notes ----------------------------------------
// TBD. Still need to update this to a better formatting for logging
// ============================================================================
// ============================================================================
// IMPORTS/VARIABLES
// ============================================================================
import * as fs from "fs";
import process from 'node:process';
import { dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const logfilename = __dirname + "/../../../streamroller.log"
// This will pipe all normal logging to a common file
const __createlogfile = false;
let firstrun = true;
// this is for user specified logging
let filestreams = [];
// cap message to 300 chars max
let cap_message_length = 300;
//default level
let loglevel = 5;
// what color scheme to use
let usecolor = "default";
// empty colors
let bgColour = "";
let resetColour = "";
let dimText = "";
let brightText = "";
let logColour = "";
let infoColour = "";
let warnColour = "";
let errColour = "";
let extraColour = ""
/**
* Turn on or off color
* @param {string} val "off","default" or a color code
*/
function usecoloredlogs (val)
{
usecolor = val;
if (val === "off")
{
bgColour = "";
resetColour = "";
dimText = "";
brightText = "";
logColour = "";
infoColour = "";
warnColour = "";
errColour = "";
extraColour = "";
}
else if (val === "default")
{
if (process.platform === "win32")
{
//bgColour = "\x1b[44m";
bgColour = "";
resetColour = "\x1b[0m";
dimText = "\x1b[1m";
brightText = "\x1b[1m";
infoColour = "\x1b[32m";
logColour = "\x1b[33m";
warnColour = "\x1b[35m";
errColour = "\x1b[31m";
extraColour = "\x1b[32m";
}
else if (process.platform === "linux")
{
bgColour = "";
resetColour = "\x1b[0m";
dimText = "\x1b[1m";
brightText = "\x1b[1m";
infoColour = "\x1b[32m";
logColour = "\x1b[33m";
warnColour = "\x1b[35m";
errColour = "\x1b[31m";
extraColour = "\x1b[32m";
}
}
else
{
bgColour = "";
resetColour = "\x1b[0m";
dimText = val;
brightText = val;
logColour = val;
infoColour = val;
warnColour = val;
errColour = val;
extraColour = val;
}
}
/* color reference
Reset = "\x1b[0m"
Bold = "\x1b[1m"
Underscore = "\x1b[4m"
Blink = "\x1b[5m"
Reverse = "\x1b[7m"
Hidden = "\x1b[8m"
FgBlack = "\x1b[30m"
FgRed = "\x1b[31m"
FgGreen = "\x1b[32m"
FgYellow = "\x1b[33m"
FgBlue = "\x1b[34m"
FgMagenta = "\x1b[35m"
FgCyan = "\x1b[36m"
FgWhite = "\x1b[37m"
BgBlack = "\x1b[40m"
BgRed = "\x1b[41m"
BgGreen = "\x1b[42m"
BgYellow = "\x1b[43m"
BgBlue = "\x1b[44m"
BgMagenta = "\x1b[45m"
BgCyan = "\x1b[46m"
BgWhite = "\x1b[47m"
*/
/**
* Sets the logging level for this module
* 0) errors only
* 1) 0 + warnings
* 2) 1 + logging
* 3) 2 + info
* @param {string} level
*/
function setLoggingLevel (level)
{
loglevel = level;
/*
console.log("LOG:STREAMTOOL_DEBUG_LEVEL: ", loglevel);
if (!process.env.STREAMTOOL_DEBUG_FORMAT)
process.env.STREAMTOOL_DEBUG_FORMAT = "off"
console.log("LOG:Log system: " + process.platform);
console.log("LOG:Log color: " + usecolor);
*/
}
/**
* gets the current logging elvel
* @returns logging level (string)
*/
function getLoggingLevel ()
{
return loglevel;
}
// ============================================================================
// FUNCTION: log
// ============================================================================
/**
* log a message
* logging level 2 or above
* @param {String} source log source. Normall "filename.function"
* @param {...any} args additional arguments
*/
function log (source, ...args)
{
if (__createlogfile)
addToLogfile("[log]" + source, args)
if (loglevel >= 2)
output(brightText + bgColour + logColour + "%s" + resetColour, source, "[log]", args);
}
// ============================================================================
// FUNCTION: info
// ============================================================================
/**
* log additional informational message
* logging level 3 or above
* @param {String} source log source. Normall "filename.function"
* @param {...any} args additional arguments
*/
function info (source, ...args)
{
if (__createlogfile)
addToLogfile("[info]" + source, args)
if (loglevel >= 3)
output(brightText + bgColour + infoColour + "%s" + resetColour, source, "[info]", args);
}
// ============================================================================
// FUNCTION: warn
// ============================================================================
/**
* log a warning messge message
* logging level 1 or above
* @param {String} source log source. Normall "filename.function"
* @param {...any} args additional arguments
*/
function warn (source, ...args)
{
if (__createlogfile)
addToLogfile("[warn]" + source, args)
if (loglevel >= 1)
output(brightText + bgColour + warnColour + "%s" + resetColour, source, "!#! WARNING !#!", args);
}
// ============================================================================
// FUNCTION: err
// ============================================================================
/**
* log an error message
* logging level 0 or above
* @param {String} source log source. Normall "filename.function"
* @param {...any} args additional arguments
*/
function err (source, ...args)
{
if (__createlogfile)
addToLogfile("[err]" + source, args)
output(brightText + bgColour + errColour + "%s" + resetColour, source, "!!! ERROR !!!", args);
}
// ============================================================================
// FUNCTION: extra
// ============================================================================
/**
* log an extra message
* logging level 0 or above
* @param {String} source log source. Normall "filename.function"
* @param {...any} args additional arguments
*/
function extra (source, ...args)
{
if (__createlogfile)
addToLogfile("[extra]" + source, args)
if (loglevel >= 4)
output(brightText + bgColour + extraColour + "%s" + resetColour, source, "[extra]", args);
}
// ============================================================================
// FUNCTION: output
// ============================================================================
/**
* outputs a message to the log
* @param {String} col colour for message
* @param {String} func source of the nessge "filename.function"
* @param {String} tag tag "[EXTENSION]"
* @param {String} message message to log
*/
function output (col, func, tag, message)
{
try
{
if (typeof (message) == "object")
message = JSON.stringify(message);
if (message.length > cap_message_length)
message = message.substring(0, cap_message_length) + "...";
if (process.env.STREAMTOOL_DEBUG_FORMAT == "extended-line")
console.log(col, message, tag, func, tag);
else if (process.env.STREAMTOOL_DEBUG_FORMAT == "extended")
console.log(col, tag, func, tag, "\n", message);
else if (process.env.STREAMTOOL_DEBUG_FORMAT != "off")
console.log(col, tag, func, message);
else
console.log(col, tag, func, message);
}
catch (err)
{
console.log(brightText + bgColour + errColour + "%s" + resetColour, "!!! LOGGING ERROR !!!", message)
}
}
// ============================================================================
// FUNCTION: output
// ============================================================================
/**
*
* @param {String} func source of the nessge "filename.function"
* @param {String} tag tag "[EXTENSION]"
* @param {String} message message to log
*/
function addToLogfile (func, tag, message)
{
if (firstrun)
{
fs.unlink(logfilename, err =>
{
if (err)
{
console.error(err)
return
}
})
firstrun = false;
}
if (typeof (func) === "object")
func = JSON.stringify(func);
if (typeof (tag) === "object")
tag = JSON.stringify(tag);
if (typeof (message) === "object")
message = JSON.stringify(message);
else if (typeof (message) === "undefined")
message = ""
fs.appendFile(logfilename, tag + " " + func + " " + message + "\n", err =>
{
if (err)
{
console.error(err)
return
}
})
}
// ============================================================================
// FUNCTION: file_log
// For debug purposes. logs raw message data
// ============================================================================
//logger.file_log("./", "streamlabstest", "some test data")
function file_log (childdir, file_name, message)
{
childdir += "/" + childdir
if (!fs.existsSync(childdir))
{
fs.mkdirSync(childdir, { recursive: true });
}
let msg = JSON.stringify(message, null, 2)
// check if we already have this handler
if (!filestreams.file_name)
{
filestreams[file_name] = fs.createWriteStream(childdir + file_name + ".log", { flags: 'a' });
}
filestreams[file_name].write(msg + "\n");
}
// ============================================================================
// EXPORTS:
// ============================================================================
export { err, extra, file_log, getLoggingLevel, info, log, loglevel, setLoggingLevel, usecoloredlogs, warn, bgColour, resetColour, dimText, brightText, logColour, infoColour, warnColour, errColour, extraColour };