Skip to content

Instantly share code, notes, and snippets.

@nexpr
Created July 10, 2021 12:53
Show Gist options
  • Save nexpr/aae3dcbfa2edd95f02944e966a1ffc4d to your computer and use it in GitHub Desktop.
Save nexpr/aae3dcbfa2edd95f02944e966a1ffc4d to your computer and use it in GitHub Desktop.
イベントリスナ形式のロガー

event logger

イベントリスナ形式のロガー

info, error などのメソッドではイベントを送信する
このロガーを使ったモジュールを使う側がリスナをセットする
console やファイルへの出力などをリスナに記述
リスナがなければログされない

リスナでは all を使うとすべてのログ種別のイベントを受け取れる

import logger from "./evlogger.js"

logger.on("all", console.log)

logger.info("aaa")
logger.error("bbb")

/*
{
  id: 'default',
  timestamp: 2021-07-10T12:17:12.082Z,
  type: 'info',
  messages: [ 'aaa' ]
}
{
  id: 'default',
  timestamp: 2021-07-10T12:17:12.095Z,
  type: 'error',
  messages: [ 'bbb' ]
}
*/

info などログ種別ごとにも設定できる
info だけに設定すると error などはログされない

import logger from "./evlogger.js"

logger.on("info", console.log)

logger.info("aaa")
logger.error("bbb")

/*
{
  id: 'default',
  timestamp: 2021-07-10T12:17:12.082Z,
  type: 'info',
  messages: [ 'aaa' ]
}
*/

名前付きエクスポートされる createLogger を使うとグローバルのロガー以外のロガーオブジェクトを作れる
引数にはロガーの ID を指定する
ID はリスナで受け取れる
logger.create(id) でサブロガーを作れる
サブロガーは新規作成と基本は同じだけど id が親と結合される

logger.create(id, true) とすると親ロガーを継承する
登録済みリスナを共有するので個別にリスナ登録しなくてもよくなる
id を変えたいときに有効

import { createLogger } from "./evlogger.js"

const foo = createLogger("foo")
foo.on("info", console.log)
foo.info("aaa")

const bar = foo.create("bar")
bar.on("info", console.log)
bar.info("bbb")

const baz = bar.create("baz", true)
baz.info("ccc")

/*
{
  id: 'foo',
  timestamp: 2021-07-10T12:22:23.629Z,
  type: 'info',
  messages: [ 'aaa' ]
}
{
  id: 'foo.bar',
  timestamp: 2021-07-10T12:22:23.644Z,
  type: 'info',
  messages: [ 'bbb' ]
}
{
  id: 'foo.bar.baz',
  timestamp: 2021-07-10T12:22:23.645Z,
  type: 'info',
  messages: [ 'ccc' ]
}
*/
export const createLogger = (id, parent) => {
const listeners = parent?.listeners || {}
const logger = {}
const on = (type, fn) => {
if (!listeners[type]) {
listeners[type] = new Set()
}
listeners[type].add(fn)
}
const off = (type, fn) => {
if (listeners[type]) {
listeners[type].delete(fn)
}
}
const call = (type, values) => {
if (listeners[type]) {
for (const fn of listeners[type]) {
fn(values)
}
}
}
const log = (type) => (...messages) => {
const values = {
id,
timestamp: new Date(),
type,
messages,
}
call(type, values)
call("all", values)
}
const addType = (type) => {
logger[type] = log(type)
}
addType("debug")
addType("info")
addType("warn")
addType("error")
const create = (sid, inherit) => createLogger(id + "." + sid, inherit ? { listeners } : null)
Object.assign(logger, { on, off, addType, create })
return logger
}
export default createLogger("default")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment