f5-conx-core
Version:
F5 SDK for JavaScript with Typescript type definitions
258 lines • 8.67 kB
JavaScript
/*
* Copyright 2020. F5 Networks, Inc. See End User License Agreement ("EULA") for
* license terms. Notwithstanding anything to the contrary in the EULA, Licensee
* may copy and modify this software product for its internal business purposes.
* Further, Licensee may upload, publish and distribute the modified version of
* the software product on devcentral.f5.com.
*/
'use strict';
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const util_1 = require("util");
const misc_1 = require("./utils/misc");
const LOG_LEVELS = {
error: 3,
warn: 4,
info: 6,
debug: 7
};
// levels have been updated to allign better with typical syslog
// https://support.solarwinds.com/SuccessCenter/s/article/Syslog-Severity-levels?language=en_US
/**
*
* Basic Example:
*
* ```ts
* // set logging to debug
* process.env.F5_CONX_CORE_LOG_LEVEL = 'DEBUG';
*
* // instantiate and import logger
* import { logger } from './logger';
*
* // turn off console logging
* logger.console = false;
*
* // create OUTPUT channel
* const f5OutputChannel = window.createOutputChannel('f5');
*
* // inject vscode output into logger
* logger.output = function (log: string) {
* f5OutputChannel.appendLine(log);
};
* ```
*
* ```bash
* export F5_CONX_CORE_LOG_LEVEL='DEBUG'
* ```
*/
class Logger {
// private static instance: Logger = new Logger();
constructor(env) {
/**
* journal array of log messages
*/
this.journal = [];
/**
* log level
*/
this.logLevel = "INFO";
/**
* buffer log messages in the journal
* @default true
*/
this.buffer = true;
/**
* output log messages to console
* @default true
*/
this.console = true;
/**
* overwritable function to allow additional output integrations
*
* ```ts
* // inject vscode output into logger
* logger.output = function (log: string) {
* f5OutputChannel.appendLine(log);
* };
* ```
* @param x log message
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
this.output = function (x) {
// by default, do nothing...
// to be overwritten by user/app
// I guess we could have just emitted an event...
// but, this function method could be modified to allow formatting changes
};
this.logEnv = env;
// set the log level during instantiation
this.logLevel = process.env[this.logEnv] || 'INFO';
}
// /**
// * Get logger instance (singleton)
// *
// * @returns logger instance
// */
// static getLogger(): Logger {
// return Logger.instance;
// }
/**
* clear/delete buffer/journal
*/
clearLogs() {
return this.journal.length = 0;
}
haveLogEnv() {
if (!this.logEnv) {
throw Error('NO LOGGER ENV SET');
}
// assign log level
this.logLevel = process.env[this.logEnv] || 'INFO';
}
/**
*
* log http request information depending on env logging level (info/debug)
*
* ex. process.env.F5_CONX_CORE_LOG_LEVEL === 'INFO/DEBUG'
*
* @param config
*/
httpRequest(config) {
return __awaiter(this, void 0, void 0, function* () {
// use logging level env to log "info" or "debug" request information
const url = config.baseURL ? `${config.baseURL}${config.url}` : config.url;
if (process.env[this.logEnv] === 'DEBUG') {
// stringify and reparse base request to remove js object details
const req = JSON.parse(JSON.stringify({
url,
headers: config.headers,
method: config.method,
uuid: config.uuid,
}));
// if POST with data
if (config.data) {
// stringify data to make it easily searchable
const dataString = JSON.stringify(config.data);
// hide passwords
const dS = dataString.replace(/("password":")(?:\\"|[^"])*"/g, "\"password\":\"***\"");
// json parse data and add back to req for logging
req.data = JSON.parse(dS);
}
this.debug('debug-http-request', req);
}
else {
this.info(`HTTPS-REQU [${config.uuid}]: ${config.method} -> ${url}`);
}
});
}
/**
*
* log http response information depending on env logging level (info/debug)
*
* ex. process.env.F5_CONX_CORE_LOG_LEVEL === 'INFO/DEBUG'
*
* @param resp
*/
httpResponse(resp) {
return __awaiter(this, void 0, void 0, function* () {
const smallResp = yield (0, misc_1.simplifyHttpResponse)(resp);
const smallerResp = JSON.parse(JSON.stringify(smallResp));
if (process.env[this.logEnv] === 'DEBUG') {
this.debug('debug-http-response', smallerResp);
}
else {
this.info(`HTTPS-RESP [${smallResp.request.uuid}]: ${smallResp.status} - ${smallResp.statusText}`);
}
});
}
/**
* Log debug message
*/
debug(...msg) {
const x = LOG_LEVELS.debug;
const y = LOG_LEVELS[this._checkLogLevel()];
if (x <= y) {
this.log('DEBUG', ...msg);
}
}
/**
* Log informational message
*/
info(...msg) {
if (LOG_LEVELS.info <= LOG_LEVELS[this._checkLogLevel()]) {
this.log('INFO', ...msg);
}
}
/**
* Log warning message
*/
warn(...msg) {
if (LOG_LEVELS.warn <= LOG_LEVELS[this._checkLogLevel()]) {
this.log('WARNING', ...msg);
}
}
/**
* Log error message
*/
error(...msg) {
// all error messages get logged...
this.log('ERROR', ...msg);
}
/**
* base log function
*/
log(level, ...messageParts) {
// join all the log message parts
const message = messageParts.map(this.stringify).join(' ');
// make timestamp
const dateTime = new Date().toISOString();
// put everything together
const log = `[${dateTime}] [${level}]: ${message}`;
// pass log to external output function option
this.output(`${this.journal.length + 1} ${log}`);
// /\/\/\ added journal lenght to output so I can see if singleton is actually being used in the differen implementations
if (this.buffer) {
// todo: put some sort of limit on the buffer size (max 500?)
this.journal.push(log);
}
if (this.console) {
console.log(log);
}
}
_checkLogLevel() {
this.haveLogEnv();
const logLevels = Object.keys(LOG_LEVELS);
// const logLevelFromEnvVar = process.env.F5_CONX_CORE_LOG_LEVEL || 'info';
// check/update log level with every log
this.logLevel = process.env[this.logEnv] || 'INFO';
if (process.env.F5_CONX_CORE_LOG_BUFFER) {
this.buffer = (process.env.F5_CONX_CORE_LOG_BUFFER == 'true');
}
if (process.env.F5_CONX_CORE_LOG_CONSOLE) {
this.console = (process.env.F5_CONX_CORE_LOG_CONSOLE == 'true');
}
if (this.logLevel && logLevels.includes(this.logLevel.toLowerCase())) {
return this.logLevel.toLowerCase();
}
return 'info';
}
stringify(val) {
if (typeof val === 'string') {
return val;
}
return (0, util_1.inspect)(val, {
colors: false,
depth: 6, // heuristic
});
}
}
exports.default = Logger;
//# sourceMappingURL=logger.js.map