vitis-engine-lib
Version:
Lib used on Vitis engines
303 lines (262 loc) • 8.15 kB
text/typescript
import fs from 'fs';
import os from 'os';
import path from 'path';
import moment from 'moment';
/**
* Class logger
* Permet de logger dans les différents fichiers
*/
export default class Logger {
// Properties
private properties_: any;
// Dossier de logs
private logFolder_: string = 'log';
// chemin vers le fichier de log
private logFullPath_: string[] = [];
// Niveaux de log
private appLogLevel: string = 'INFO';
private aLogLevels_: string[] = [
'DEBUG',
'INFO',
'NOTICE',
'WARNING',
'ERROR',
'CRITICAL',
'ALERT',
'EMERGENCY',
];
private pid_: number = 0;
// Moteur utilisé
private engine_: any;
private allow_console_return: boolean = true
/**
* Constructeur
* @param properties
*/
constructor(properties: any) {
// Properties
this.properties_ = properties;
// Niveau de log
if (this.properties_.log_level) {
this.appLogLevel = this.properties_.log_level;
} else {
this.appLogLevel = 'DEBUG';
}
this.logFolder_ = this.properties_.log_dir;
this.pid_ = process.pid;
this.logFullPath_ = this.getLogFilePath_();
}
/**
* Set moteur pour l'utiliser dans les logs
* @param {any} engine engine_id
*/
public setEngine(engine: any): void {
this.engine_ = engine;
// on met à jour le chemin
this.logFullPath_ = this.getLogFilePath_();
}
/**
* Set le chemin vers le fichier e log à utiliser
* @param {string} sPath chemin à utiliser pour logger
*/
public setLogFilePath(sPath: string): void {
// Conversion du format de date de php vers js
const sFormat: string = this.getDateFormat();
const sLogDate: string = this.getFormatedDate_(new Date(), sFormat)
sPath = sPath.replace(//, sLogDate);
// on met à jour le chemin
this.logFullPath_ = sPath.split('/');
}
/**
*
* @returns {string}
*/
private getDateFormat(): string {
let sFormat: string = this.properties_.log_period
sFormat = sFormat.replace('Y', 'YYYY');
sFormat = sFormat.replace('m', 'MM');
sFormat = sFormat.replace('d', 'DD');
return sFormat;
}
/**
* désactive les console.log du logger
*/
public disableConsoleMessage(): void {
this.allow_console_return = false;
}
/**
* active les console.log du logger
*/
public enableConsoleMessage(): void {
this.allow_console_return = true;
}
/**
* Écrit un message dans le logs
* @param {string} message
* @param {*} variable variable à logger dans le message
* @param {string|undefined} level
*/
public log(message: any, variable?: any, level: string = 'INFO'): void {
// si le message est manquant on a rien à log
if (!message) {
return;
}
if (this.allow_console_return) {
// envoi du log dans la console
if (variable) {
console.log(message, variable);
} else {
console.log(message);
}
}
// récupération des niveaux de log disponibles
const appLogLevels = this.getAppLogLevels_();
// si le niveau n'est pas disponible rien à logger
if (appLogLevels.indexOf(level) === -1) {
return;
}
// formattage du message
message = this.getFormatedMessage_(message, variable, level);
// Chemin vers le fichier
const aFilePath = this.logFullPath_;
const sFilePath = this.logFullPath_.join('/');
// analyse de la taille du fichier pour chunk si besoin
if (fs.existsSync(sFilePath)) {
// taille du fichier de log en octet
const stats = fs.statSync(sFilePath)
const iLogFileSize = stats["size"]
// taille du message en octet
const iMessageSize = Buffer.byteLength(message, 'utf8')
const iFinalSize = iLogFileSize + iMessageSize;
if ((this.properties_.log_size - 1) <= iFinalSize) {
try {
this.chunkLogFile(aFilePath);
} catch (error) {
console.log('could not rename log file', error);
return;
}
}
}
try {
// Crée le fichier de log si il n'existe pas
this.createLogFile_(aFilePath);
} catch (error) {
console.log('could not create log file', error);
return;
}
// Écrit dans le fichier
this.appendMessage_(sFilePath, message);
}
/**
* Calcule le nouveau nom du fichier de log et renome l'ancien fichier
* @param {string[]} aFilePath tableau chemin vers le fichier d'origine
*/
private chunkLogFile(aFilePath: string[]): void {
// création d'une copie du tableau pour modification
const aFinalFilePath = [...aFilePath];
// analyse du chemin pour modification du nom de chemin
if (aFinalFilePath) {
const sFileName: string | undefined = aFinalFilePath.pop();
if (typeof sFileName === 'string') {
const sChunkedFileName: string = sFileName.replace('.log', '.' + this.getFormatedDate_(new Date(), 'YYYY_MM_DD_X') + '.log');
aFinalFilePath.push(sChunkedFileName);
fs.renameSync(aFilePath.join('/'), aFinalFilePath.join('/'));
}
}
}
/**
* Retourne les niveaux de logs disponibles selon la configuration utilisateur
* @returns {Array}
*/
private getAppLogLevels_(): string[] {
// Filtrage en fonction du niveau de log
const availableLogLevels = [];
for (let i = this.aLogLevels_.length - 1; i >= 0; i--) {
const logLevel = this.aLogLevels_[i];
availableLogLevels.push(logLevel);
if (logLevel === this.appLogLevel) {
break;
}
}
return availableLogLevels;
}
/**
* Retourne le chemin vers le fichier de log
* @return {Array} chemin vers la fichier de log
*/
private getLogFilePath_(): string[] {
const path = [this.logFolder_];
const sFormat: string = this.getDateFormat();
path.push(this.getFormatedDate_(new Date(), sFormat));
path.push('engines');
if (this.properties_.use_hostname_in_logdir === true) {
path.push(os.hostname());
}
if (this.engine_ && this.engine_.gtf_engine_id) {
path.push(`engine_${this.engine_.gtf_engine_id}`);
}
path.push('engine.log');
return path;
}
/**
* Retourne la date formatée
* @param {Date} d Date
* @param {string | undefined} format https://momentjs.com/docs/#/displaying/format/
* @returns {string} formated date
*/
private getFormatedDate_(d: Date, format: string = 'YYYY/MM/DD'): string {
const oDate = moment(d);
return oDate.format(format);
}
/**
* Crée le fichier de log si il n'existe pas
* @param {Array} chemin vers le fichier
*/
private createLogFile_(filePath: string[]): void {
const sFilePath = filePath.join('/');
const directory = path.dirname(sFilePath);
const oldMask = process.umask(0)
// Crée les sous dossiers si besoin
fs.mkdirSync(directory, { recursive: true, mode: 0o777 });
// Crée le fichier si besoin
if (!fs.existsSync(sFilePath)) {
fs.writeFileSync(sFilePath, '', {
encoding: 'utf8',
mode: 0o766,
});
}
process.umask(oldMask);
}
/**
* Écrit le message
* @param {Array} filePath
* @param {string} message message formatté
*/
private appendMessage_(filePath: string, message: string): void {
if (filePath && message) {
// Écrit le message
fs.appendFileSync(filePath, message);
}
}
/**
* écrit un message dans un fichier de log
* @param {string} message message à logger
* @param {any} variable variable à associé au message
* @param {string} level Niveau de log
*/
private getFormatedMessage_(message: string, variable?: any, level: string = 'INFO'): string {
let formattedMessage = `${this.getFormatedDate_(new Date(), 'DD-MM-YYYY HH:mm:ss')}`;
formattedMessage += ` | ${this.pid_}`;
formattedMessage += ` | ${level}`;
formattedMessage += ` | ${message}`;
if (variable) {
try {
formattedMessage += ` ${JSON.stringify(variable)}`;
} catch (error) {
formattedMessage += ` ${String(variable)}`;
}
}
formattedMessage += `\n`;
return formattedMessage;
}
}