UNPKG

pear-api

Version:

Pear API Base & Integration Module

148 lines (136 loc) 4.74 kB
'use strict' const { isBare } = require('which-runtime') const hrtime = isBare ? require('bare-hrtime') : process.hrtime const pear = require('./cmd')(global.Bare.argv.slice(1)) const switches = { log: pear?.flags.log ?? false, level: pear?.flags.logLevel ?? (pear?.flags.log ? 2 : 0), labels: pear?.flags.logLabels ?? '', fields: pear?.flags.logFields ?? '', stacks: pear?.flags.logStacks ?? false } class Logger { static switches = switches static OFF = 0 static ERR = 1 static INF = 2 static TRC = 3 constructor ({ labels = '', fields, stacks, level, pretty } = {}) { this._fields = this._parseFields(fields) labels = this._parseLabels(labels) .concat(this._parseLabels(this.constructor.switches.labels)) .filter(Boolean) this._labels = new Set(labels) this._show = this._fields.show this._stacks = stacks ?? this.constructor.switches.stacks this._times = {} if (pretty) { if (this._fields.seen.has('level') === false) this._show.level = false if (this._fields.seen.has('label') === false) this._show.label = this._labels.size > 2 } this.stack = '' this.LEVEL = this._parseLevel(level ?? this.constructor.switches.level) } get OFF () { return this.LEVEL === this.constructor.OFF } get ERR () { return this.LEVEL >= this.constructor.ERR } get INF () { return this.LEVEL >= this.constructor.INF } get TRC () { return this.LEVEL >= this.constructor.TRC } _args (level, label, ...args) { const now = hrtime.bigint() const ms = Number(now) / 1e6 const delta = this._times[label] ? ms - Number(this._times[label]) / 1e6 : 0 this._times[label] = now const datetime = (this._show.date || this._show.time) ? new Date().toISOString().split('T') : [] const date = this._show.date ? datetime[0] : '' const time = this._show.time ? datetime[1].slice(0, -1) : '' label = this._show.label ? '[ ' + label.slice(0, 21) + ' ]' : '' level = this._show.level ? level : '' const prefix = [level, date, time, label].filter(Boolean) return [...prefix, ...args, this._show.delta ? '[+' + (Math.round(delta * Math.pow(10, 4)) / Math.pow(10, 4)) + 'ms]' : ''] } error (label, ...args) { if (this.LEVEL < this.constructor.ERR) return if (Array.isArray(label)) { for (const lbl of label) this.error(lbl, ...args) return } if (!this._labels.has(label)) return if (this._stacks) Error.captureStackTrace(this, this.error) args = this._args('ERR', label, ...args) if (this._stacks) { console.error(...args, this.stack) this.stack = '' } else { console.error(...args) } } info (label, ...args) { if (this.LEVEL < this.constructor.INF) return if (Array.isArray(label)) { for (const lbl of label) this.info(lbl, ...args) return } if (!this._labels.has(label)) return if (this._stacks) Error.captureStackTrace(this, this.info) args = this._args('INF', label, ...args) if (this._stacks) { console.log(...args, this.stack) this.stack = '' } else { console.log(...args) } } trace (label, ...args) { if (this.LEVEL < this.constructor.TRC) return if (Array.isArray(label)) { for (const lbl of label) this.trace(lbl, ...args) return } if (!this._labels.has(label)) return if (this._stacks) Error.captureStackTrace(this, this.trace) args = this._args('TRC', label, ...args) if (this._stacks) { console.error(...args, this.stack) this.stack = '' } else { console.error(...args) } } _parseLevel (level) { if (typeof level === 'number') return level if (typeof level === 'string') level = level.toUpperCase() if (level === 'OFF' || level === '0') return 0 if (level === 'ERR' || level === 'ERROR' || level === '1') return 1 if (level === 'INF' || level === 'INFO' || level === '2') return 2 if (level === 'TRC' || level === 'TRACE' || level === 'TRA' || level === '3') return 3 return 2 } _parseFields (fields = '') { const show = { date: false, time: false, level: true, label: true, delta: true } const seen = new Set() for (let field of fields.split(',').concat(this.constructor.switches.fields.split(','))) { if (seen.has(field)) continue field = field.trim() if (field.startsWith('h:')) { field = field.slice(2) seen.add(field) show[field] = false continue } seen.add(field) show[field] = true } return { seen, show } } _parseLabels (labels) { if (typeof labels !== 'string') return labels return labels.split(',') } } module.exports = Logger