@probe.gl/log
Version:
JavaScript debug logging for browser and Node
443 lines (431 loc) • 13.2 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// dist/index.js
var dist_exports = {};
__export(dist_exports, {
COLOR: () => COLOR,
LocalStorage: () => LocalStorage,
Log: () => Log,
addColor: () => addColor,
autobind: () => autobind,
default: () => dist_default,
getHiResTimestamp: () => getHiResTimestamp,
leftPad: () => leftPad,
rightPad: () => rightPad
});
module.exports = __toCommonJS(dist_exports);
// dist/log.js
var import_env3 = require("@probe.gl/env");
// dist/utils/local-storage.js
function getStorage(type) {
try {
const storage = window[type];
const x = "__storage_test__";
storage.setItem(x, x);
storage.removeItem(x);
return storage;
} catch (e) {
return null;
}
}
var LocalStorage = class {
constructor(id, defaultConfig, type = "sessionStorage") {
this.storage = getStorage(type);
this.id = id;
this.config = defaultConfig;
this._loadConfiguration();
}
getConfiguration() {
return this.config;
}
setConfiguration(configuration) {
Object.assign(this.config, configuration);
if (this.storage) {
const serialized = JSON.stringify(this.config);
this.storage.setItem(this.id, serialized);
}
}
// Get config from persistent store, if available
_loadConfiguration() {
let configuration = {};
if (this.storage) {
const serializedConfiguration = this.storage.getItem(this.id);
configuration = serializedConfiguration ? JSON.parse(serializedConfiguration) : {};
}
Object.assign(this.config, configuration);
return this;
}
};
// dist/utils/formatters.js
function formatTime(ms) {
let formatted;
if (ms < 10) {
formatted = `${ms.toFixed(2)}ms`;
} else if (ms < 100) {
formatted = `${ms.toFixed(1)}ms`;
} else if (ms < 1e3) {
formatted = `${ms.toFixed(0)}ms`;
} else {
formatted = `${(ms / 1e3).toFixed(2)}s`;
}
return formatted;
}
function leftPad(string, length = 8) {
const padLength = Math.max(length - string.length, 0);
return `${" ".repeat(padLength)}${string}`;
}
function rightPad(string, length = 8) {
const padLength = Math.max(length - string.length, 0);
return `${string}${" ".repeat(padLength)}`;
}
// dist/utils/color.js
var import_env = require("@probe.gl/env");
var COLOR;
(function(COLOR2) {
COLOR2[COLOR2["BLACK"] = 30] = "BLACK";
COLOR2[COLOR2["RED"] = 31] = "RED";
COLOR2[COLOR2["GREEN"] = 32] = "GREEN";
COLOR2[COLOR2["YELLOW"] = 33] = "YELLOW";
COLOR2[COLOR2["BLUE"] = 34] = "BLUE";
COLOR2[COLOR2["MAGENTA"] = 35] = "MAGENTA";
COLOR2[COLOR2["CYAN"] = 36] = "CYAN";
COLOR2[COLOR2["WHITE"] = 37] = "WHITE";
COLOR2[COLOR2["BRIGHT_BLACK"] = 90] = "BRIGHT_BLACK";
COLOR2[COLOR2["BRIGHT_RED"] = 91] = "BRIGHT_RED";
COLOR2[COLOR2["BRIGHT_GREEN"] = 92] = "BRIGHT_GREEN";
COLOR2[COLOR2["BRIGHT_YELLOW"] = 93] = "BRIGHT_YELLOW";
COLOR2[COLOR2["BRIGHT_BLUE"] = 94] = "BRIGHT_BLUE";
COLOR2[COLOR2["BRIGHT_MAGENTA"] = 95] = "BRIGHT_MAGENTA";
COLOR2[COLOR2["BRIGHT_CYAN"] = 96] = "BRIGHT_CYAN";
COLOR2[COLOR2["BRIGHT_WHITE"] = 97] = "BRIGHT_WHITE";
})(COLOR || (COLOR = {}));
var BACKGROUND_INCREMENT = 10;
function getColor(color) {
if (typeof color !== "string") {
return color;
}
color = color.toUpperCase();
return COLOR[color] || COLOR.WHITE;
}
function addColor(string, color, background) {
if (!import_env.isBrowser && typeof string === "string") {
if (color) {
const colorCode = getColor(color);
string = `\x1B[${colorCode}m${string}\x1B[39m`;
}
if (background) {
const colorCode = getColor(background);
string = `\x1B[${colorCode + BACKGROUND_INCREMENT}m${string}\x1B[49m`;
}
}
return string;
}
// dist/utils/autobind.js
function autobind(obj, predefined = ["constructor"]) {
const proto = Object.getPrototypeOf(obj);
const propNames = Object.getOwnPropertyNames(proto);
const object = obj;
for (const key of propNames) {
const value = object[key];
if (typeof value === "function") {
if (!predefined.find((name) => key === name)) {
object[key] = value.bind(obj);
}
}
}
}
// dist/utils/assert.js
function assert(condition, message) {
if (!condition) {
throw new Error(message || "Assertion failed");
}
}
// dist/utils/hi-res-timestamp.js
var import_env2 = require("@probe.gl/env");
function getHiResTimestamp() {
var _a, _b, _c, _d, _e;
let timestamp;
if ((0, import_env2.isBrowser)() && import_env2.window.performance) {
timestamp = (_c = (_b = (_a = import_env2.window) == null ? void 0 : _a.performance) == null ? void 0 : _b.now) == null ? void 0 : _c.call(_b);
} else if ("hrtime" in import_env2.process) {
const timeParts = (_e = (_d = import_env2.process) == null ? void 0 : _d.hrtime) == null ? void 0 : _e.call(_d);
timestamp = timeParts[0] * 1e3 + timeParts[1] / 1e6;
} else {
timestamp = Date.now();
}
return timestamp;
}
// dist/log.js
var originalConsole = {
debug: (0, import_env3.isBrowser)() ? console.debug || console.log : console.log,
log: console.log,
info: console.info,
warn: console.warn,
error: console.error
};
var DEFAULT_LOG_CONFIGURATION = {
enabled: true,
level: 0
};
function noop() {
}
var cache = {};
var ONCE = { once: true };
var Log = class {
constructor({ id } = { id: "" }) {
this.VERSION = import_env3.VERSION;
this._startTs = getHiResTimestamp();
this._deltaTs = getHiResTimestamp();
this.userData = {};
this.LOG_THROTTLE_TIMEOUT = 0;
this.id = id;
this.userData = {};
this._storage = new LocalStorage(`__probe-${this.id}__`, DEFAULT_LOG_CONFIGURATION);
this.timeStamp(`${this.id} started`);
autobind(this);
Object.seal(this);
}
set level(newLevel) {
this.setLevel(newLevel);
}
get level() {
return this.getLevel();
}
isEnabled() {
return this._storage.config.enabled;
}
getLevel() {
return this._storage.config.level;
}
/** @return milliseconds, with fractions */
getTotal() {
return Number((getHiResTimestamp() - this._startTs).toPrecision(10));
}
/** @return milliseconds, with fractions */
getDelta() {
return Number((getHiResTimestamp() - this._deltaTs).toPrecision(10));
}
/** @deprecated use logLevel */
set priority(newPriority) {
this.level = newPriority;
}
/** @deprecated use logLevel */
get priority() {
return this.level;
}
/** @deprecated use logLevel */
getPriority() {
return this.level;
}
// Configure
enable(enabled = true) {
this._storage.setConfiguration({ enabled });
return this;
}
setLevel(level) {
this._storage.setConfiguration({ level });
return this;
}
/** return the current status of the setting */
get(setting) {
return this._storage.config[setting];
}
// update the status of the setting
set(setting, value) {
this._storage.setConfiguration({ [setting]: value });
}
/** Logs the current settings as a table */
settings() {
if (console.table) {
console.table(this._storage.config);
} else {
console.log(this._storage.config);
}
}
// Unconditional logging
assert(condition, message) {
if (!condition) {
throw new Error(message || "Assertion failed");
}
}
warn(message) {
return this._getLogFunction(0, message, originalConsole.warn, arguments, ONCE);
}
error(message) {
return this._getLogFunction(0, message, originalConsole.error, arguments);
}
/** Print a deprecation warning */
deprecated(oldUsage, newUsage) {
return this.warn(`\`${oldUsage}\` is deprecated and will be removed in a later version. Use \`${newUsage}\` instead`);
}
/** Print a removal warning */
removed(oldUsage, newUsage) {
return this.error(`\`${oldUsage}\` has been removed. Use \`${newUsage}\` instead`);
}
probe(logLevel, message) {
return this._getLogFunction(logLevel, message, originalConsole.log, arguments, {
time: true,
once: true
});
}
log(logLevel, message) {
return this._getLogFunction(logLevel, message, originalConsole.debug, arguments);
}
info(logLevel, message) {
return this._getLogFunction(logLevel, message, console.info, arguments);
}
once(logLevel, message) {
return this._getLogFunction(logLevel, message, originalConsole.debug || originalConsole.info, arguments, ONCE);
}
/** Logs an object as a table */
table(logLevel, table, columns) {
if (table) {
return this._getLogFunction(logLevel, table, console.table || noop, columns && [columns], {
tag: getTableHeader(table)
});
}
return noop;
}
time(logLevel, message) {
return this._getLogFunction(logLevel, message, console.time ? console.time : console.info);
}
timeEnd(logLevel, message) {
return this._getLogFunction(logLevel, message, console.timeEnd ? console.timeEnd : console.info);
}
timeStamp(logLevel, message) {
return this._getLogFunction(logLevel, message, console.timeStamp || noop);
}
group(logLevel, message, opts = { collapsed: false }) {
const options = normalizeArguments({ logLevel, message, opts });
const { collapsed } = opts;
options.method = (collapsed ? console.groupCollapsed : console.group) || console.info;
return this._getLogFunction(options);
}
groupCollapsed(logLevel, message, opts = {}) {
return this.group(logLevel, message, Object.assign({}, opts, { collapsed: true }));
}
groupEnd(logLevel) {
return this._getLogFunction(logLevel, "", console.groupEnd || noop);
}
// EXPERIMENTAL
withGroup(logLevel, message, func) {
this.group(logLevel, message)();
try {
func();
} finally {
this.groupEnd(logLevel)();
}
}
trace() {
if (console.trace) {
console.trace();
}
}
// PRIVATE METHODS
/** Deduces log level from a variety of arguments */
_shouldLog(logLevel) {
return this.isEnabled() && this.getLevel() >= normalizeLogLevel(logLevel);
}
_getLogFunction(logLevel, message, method, args, opts) {
if (this._shouldLog(logLevel)) {
opts = normalizeArguments({ logLevel, message, args, opts });
method = method || opts.method;
assert(method);
opts.total = this.getTotal();
opts.delta = this.getDelta();
this._deltaTs = getHiResTimestamp();
const tag = opts.tag || opts.message;
if (opts.once && tag) {
if (!cache[tag]) {
cache[tag] = getHiResTimestamp();
} else {
return noop;
}
}
message = decorateMessage(this.id, opts.message, opts);
return method.bind(console, message, ...opts.args);
}
return noop;
}
};
Log.VERSION = import_env3.VERSION;
function normalizeLogLevel(logLevel) {
if (!logLevel) {
return 0;
}
let resolvedLevel;
switch (typeof logLevel) {
case "number":
resolvedLevel = logLevel;
break;
case "object":
resolvedLevel = logLevel.logLevel || logLevel.priority || 0;
break;
default:
return 0;
}
assert(Number.isFinite(resolvedLevel) && resolvedLevel >= 0);
return resolvedLevel;
}
function normalizeArguments(opts) {
const { logLevel, message } = opts;
opts.logLevel = normalizeLogLevel(logLevel);
const args = opts.args ? Array.from(opts.args) : [];
while (args.length && args.shift() !== message) {
}
switch (typeof logLevel) {
case "string":
case "function":
if (message !== void 0) {
args.unshift(message);
}
opts.message = logLevel;
break;
case "object":
Object.assign(opts, logLevel);
break;
default:
}
if (typeof opts.message === "function") {
opts.message = opts.message();
}
const messageType = typeof opts.message;
assert(messageType === "string" || messageType === "object");
return Object.assign(opts, { args }, opts.opts);
}
function decorateMessage(id, message, opts) {
if (typeof message === "string") {
const time = opts.time ? leftPad(formatTime(opts.total)) : "";
message = opts.time ? `${id}: ${time} ${message}` : `${id}: ${message}`;
message = addColor(message, opts.color, opts.background);
}
return message;
}
function getTableHeader(table) {
for (const key in table) {
for (const title in table[key]) {
return title || "untitled";
}
}
return "empty";
}
// dist/init.js
globalThis.probe = {};
// dist/index.js
var dist_default = new Log({ id: "@probe.gl/log" });
//# sourceMappingURL=index.cjs.map