Skip to content

Instantly share code, notes, and snippets.

@cmdruid
Created December 26, 2024 21:06
Show Gist options
  • Save cmdruid/752fe10c50e09ad952c5f369e9ebd47e to your computer and use it in GitHub Desktop.
Save cmdruid/752fe10c50e09ad952c5f369e9ebd47e to your computer and use it in GitHub Desktop.
Basic implementation of a logger
type LogLevel = keyof typeof LOG_LEVEL_MAP
interface LogState {
base_level : number
curr_level : number
curr_path : string | null
}
const { LOG_LEVEL, NODE_ENV } = process.env
const LOG_LEVEL_MAP = {
'DEBUG' : 0,
'INFO' : 1,
'WARN' : 2,
'ERROR' : 3
}
const now = () => Math.floor(Date.now() / 1000)
function format_stamp (stamp : number) {
const addLeadingZero = (num : number) => (num < 10 ? '0' + num : num);
const date = new Date(stamp * 1000)
const month = addLeadingZero(date.getMonth() + 1)
const day = addLeadingZero(date.getDate())
const year = date.getFullYear().toString().slice(2)
const hours = addLeadingZero(date.getHours())
const minutes = addLeadingZero(date.getMinutes())
const seconds = addLeadingZero(date.getSeconds())
return `${month}/${day}/${year}-${hours}:${minutes}:${seconds}`
}
function get_log_level_str (level? : string) : LogLevel {
let level_str : string
if (level !== undefined) {
level_str = level
} else if (LOG_LEVEL !== undefined) {
level_str = LOG_LEVEL
} else if (NODE_ENV !== 'production') {
level_str = 'DEBUG'
} else {
level_str = 'WARN'
}
level_str = level_str.toUpperCase()
if (Object.keys(LOG_LEVEL_MAP).includes(level_str)) {
return level_str as LogLevel
} else {
throw new Error('Invalid log level: ' + level_str)
}
}
function get_log_level_num (level_str : LogLevel) : number {
return LOG_LEVEL_MAP[level_str]
}
function logger (
ctx : LogState,
level : LogLevel,
path : string,
msgs : unknown[]
) {
const level_str = get_log_level_str(level)
const level_num = get_log_level_num(level_str)
if (level_num >= ctx.base_level) {
const tstamp = format_stamp(now())
const str_len = level.length + tstamp.length + path.length
const banner = '='.repeat(str_len + 12)
if (level_num !== ctx.curr_level || path !== ctx.curr_path) {
console.log(banner)
console.log(` [${level_str}] [${tstamp}] [${path}]`)
console.log(banner, '\n')
}
if (msgs.length === 1 && typeof msgs[0] === 'object') {
console.dir(msgs[0], { depth: null })
} else {
console.log(...msgs, '\n')
}
ctx.curr_level = level_num
ctx.curr_path = path
}
}
export default function (base_level? : string) {
const level_str = get_log_level_str(base_level)
const level_num = get_log_level_num(level_str)
const ctx = {
base_level : level_num,
curr_level : level_num,
curr_path : null
}
return (path : string) => {
return {
debug : (...msgs : unknown[]) => logger(ctx, 'DEBUG', path, msgs),
error : (...msgs : unknown[]) => logger(ctx, 'ERROR', path, msgs),
info : (...msgs : unknown[]) => logger(ctx, 'INFO', path, msgs),
warn : (...msgs : unknown[]) => logger(ctx, 'WARN', path, msgs)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment