Skip to content

Instantly share code, notes, and snippets.

@schuhwerk
Last active February 7, 2024 12:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save schuhwerk/1dd728f0c5acc7b7c98dfea310326dd3 to your computer and use it in GitHub Desktop.
Save schuhwerk/1dd728f0c5acc7b7c98dfea310326dd3 to your computer and use it in GitHub Desktop.
Simple Logger.ts
const stringToBool = (s: string) => (s.toString().match(/^(true|[1-9][0-9]*|[0-9]*[1-9]+|yes)$/i) ? true : false)
type levelNames = "emerg" | "alert" | "crit" | "error" | "warn" | "notice" | "info" | "debug"
type logLevel = {
name: levelNames
cb: CallableFunction
defaultEnabled: boolean
}
type callableNames = {
[K in levelNames]: CallableFunction
}
type levelsEnabled = { [Property in levelNames]?: boolean }
// info and debug are disabled by default.
const logLevelsN: logLevel[] = [
{ name: "emerg", cb: console.error, defaultEnabled: stringToBool(process.env?.REACT_APP_LOG_EMERG ?? "true") },
{ name: "alert", cb: console.warn, defaultEnabled: stringToBool(process.env?.REACT_APP_LOG_ALERT ?? "true") },
{ name: "crit", cb: console.error, defaultEnabled: stringToBool(process.env?.REACT_APP_LOG_CRIT ?? "true") },
{ name: "error", cb: console.error, defaultEnabled: stringToBool(process.env?.REACT_APP_LOG_ERROR ?? "true") },
{ name: "warn", cb: console.warn, defaultEnabled: stringToBool(process.env?.REACT_APP_LOG_WARN ?? "true") },
{ name: "notice", cb: console.log, defaultEnabled: stringToBool(process.env?.REACT_APP_LOG_NOTICE ?? "true") },
{ name: "info", cb: console.info, defaultEnabled: stringToBool(process.env?.REACT_APP_LOG_INFO ?? "false") },
{ name: "debug", cb: console.debug, defaultEnabled: stringToBool(process.env?.REACT_APP_LOG_DEBUG ?? "false") }
] as const
/**
* This is a simple logger, which outputs the right path in console (where its called from parent).
* There is multiple ways to configure this (further down overwrites further up)
* - You can toggle levels globally via .env (REACT_APP_LOG_DEBUG = false). Remember to rerun 'yarn run start'.
* - You can pass settings in the constructor: { enabled: { debug: false } } if you want to hide output from debug.
* - You can overwrite it for your instance like myLogger.enabled.debug = false
*/
export const Logger = class implements callableNames {
emerg: CallableFunction
alert: CallableFunction
crit: CallableFunction
error: CallableFunction
warn: CallableFunction
notice: CallableFunction
info: CallableFunction
debug: CallableFunction
private enStore: levelsEnabled
enabled: levelsEnabled
constructor(props?: { prefix?: string; enabled?: levelsEnabled }) {
this.emerg = this.alert = this.crit = this.error = this.warn = this.notice = this.info = this.debug = () => 0
this.enStore = props?.enabled ?? {}
// whenever somebody sets a key like enabled.debug we re-apply the appropriate function.
this.enabled = new Proxy(this.enStore, {
set: (target, lvlName: levelNames, value) => {
this[lvlName] = value
? Function.prototype.bind.call(
Logger.getLvl(lvlName).cb,
console,
`%c${props?.prefix ?? ""}(${lvlName})`,
"color: color-mix(in srgb, currentColor 55%, transparent)"
)
: () => 0
return true
}
})
// add the functions for all enabled levels.
logLevelsN.forEach((lvl) => {
// apply defaults to all enabled-levels => this triggers the proxy to set the functions.
this.enabled[lvl.name] = undefined === this.enStore?.[lvl.name] ? lvl.defaultEnabled : this.enStore[lvl.name]
})
}
// @todo: logLevelsN should probably be a record, so we don't have this issue...
static getLvl(lvlName: levelNames): logLevel {
const found = logLevelsN.find((lvl) => lvlName === lvl.name)
if (found === undefined) {
throw new TypeError("The value was promised to always be there!")
}
return found
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment