@3fv/logger-proxy 中文文档教程

发布于 3年前 浏览 23 项目主页 更新于 3年前

# @3fv/logger-proxy

Overview

有这么多的日志库,事实上我觉得我正在创建相同的样板配置 不同的库取决于目标平台以及日志记录后端等。我最终决定实现一个简单的 旨在与其他框架一起使用的日志记录框架 & 记录器; 猎空摩根温斯顿

适用于浏览器 & <代码>节点 & deno

现在,这是编写包括上述日志框架在内的那些人的一个相当普遍的声明; 但是这个 真正意味着成为一个代理 & 这样一来,它就可以启用后端异步上下文堆栈之类的东西。 即默认配置去 到一个文件追加器,但你的工作也有一个额外的追加通过异步上下文(想想 ThreadLocal in javac++ 中的 std::thread_local )。

@3fv/logger-proxy

Install

yarn add @3fv/logger-proxy

Usage

Basic

import {
  getLogger,
  LevelNames, getLoggingManager
} from "@3fv/logger-proxy"


getLoggingManager().configure({
  // Default appenders list is [ConsoleAppender], 
  // so the following is not needed and only 
  // remains as an example:
  //
  // appenders: [new ConsoleAppender()],
  rootLevel: "trace"
})

const log = getLogger(__filename)

LevelNames.forEach((name) =>
  log[name].call(log, `example %s`, name)
)

Context Stacks (the coolest bit)

hotswap logging backends 为了冗长以及我很懒惰的事实,这里有一个完整的单元测试来说明功能(在 jest 中)

import {
  Appender,
  getLoggingManager,
  LogContext,
  Logger,
  getLogger
} from "@3fv/logger-proxy"

type Jest = typeof jest
type MockAppender = Appender & {
  append: Appender["append"] & ReturnType<Jest["fn"]>
}

function newMockAppender(): MockAppender {
  const fn = jest.fn((record: any) => {
    console.log(`record`, record)
  })
  return {
    append: fn
  }
}

describe("NodeContextProvider", () => {
  jest.setTimeout(10000)

  const manager = getLoggingManager()
  let baseAppender: MockAppender
  let contextAppender1: MockAppender
  let contextAppender2: MockAppender
  let context1: LogContext
  let context2: LogContext
  let log1: Logger
  let log2: Logger

  beforeEach(() => {
    baseAppender = newMockAppender()

    contextAppender1 = newMockAppender()
    contextAppender2 = newMockAppender()

    context1 = LogContext.with([contextAppender1])
    context2 = LogContext.with([contextAppender2])

    manager.setAppenders(baseAppender).setRootLevel("debug")

    log1 = getLogger("log1")
    log2 = getLogger("log2")
  })

  it("works with no contexts", async () => {
    log1.info("test1")
    log2.info("test2")

    expect(baseAppender.append).toBeCalledTimes(2)
  })

  it("works with no context provider", async () => {
    log1.info("test1")
    await context1.use(async () => {
      log1.info("test2")
    })

    expect(baseAppender.append).toBeCalledTimes(2)
    expect(contextAppender1.append).toBeCalledTimes(0)
  })

  it("works with 1 contexts", async () => {

    // You must explicitly `install` the context provider to use contexts
    await import("@3fv/logger-proxy/context/providers/node")

    log1.info("test1")
    await context1.use(async () => {
      log1.info("test2")
    })

    expect(baseAppender.append).toBeCalledTimes(2)
    expect(contextAppender1.append).toBeCalledTimes(1)
  })

  it("works with n contexts", async () => {

    // You must explicitly `install` the context provider to use contexts
    await import("@3fv/logger-proxy/context/providers/node")

    log1.info("test1")
    await context1.use(async () => {
      log1.info("test2")
      await context2.use(async () => {
        log1.info("test3")
      })
    })

    expect(baseAppender.append).toBeCalledTimes(3)
    expect(contextAppender1.append).toBeCalledTimes(2)
    expect(contextAppender2.append).toBeCalledTimes(1)
  })
})

# @3fv/logger-proxy

Overview

With so many logging libraries out there, and the fact that I felt I was creating the same boilerplate configs with different libs depending on target platforms as well as logging backends, etc. I finally decided to implement a simple logging framework that's meant to be used with other frameworks & loggers; Tracer, Morgan, Winston.

Works across browser & node & deno

Now, that is a fairly common statement from those that write logging frameworks including the aforementioned; but this is truly meant to be a proxy & with that it enables things like backend async context stacks. i.e. default config goes to a file appender, but your job's also have an additional append via an async context (Think ThreadLocal in the java or std::thread_local in c++ ).

@3fv/logger-proxy hotswap logging backends

Install

yarn add @3fv/logger-proxy

Usage

Basic

import {
  getLogger,
  LevelNames, getLoggingManager
} from "@3fv/logger-proxy"


getLoggingManager().configure({
  // Default appenders list is [ConsoleAppender], 
  // so the following is not needed and only 
  // remains as an example:
  //
  // appenders: [new ConsoleAppender()],
  rootLevel: "trace"
})

const log = getLogger(__filename)

LevelNames.forEach((name) =>
  log[name].call(log, `example %s`, name)
)

Context Stacks (the coolest bit)

For verboseness as well as the fact I'm lazy, here's a complete unit test illustrating the capabilities (in jest)

import {
  Appender,
  getLoggingManager,
  LogContext,
  Logger,
  getLogger
} from "@3fv/logger-proxy"

type Jest = typeof jest
type MockAppender = Appender & {
  append: Appender["append"] & ReturnType<Jest["fn"]>
}

function newMockAppender(): MockAppender {
  const fn = jest.fn((record: any) => {
    console.log(`record`, record)
  })
  return {
    append: fn
  }
}

describe("NodeContextProvider", () => {
  jest.setTimeout(10000)

  const manager = getLoggingManager()
  let baseAppender: MockAppender
  let contextAppender1: MockAppender
  let contextAppender2: MockAppender
  let context1: LogContext
  let context2: LogContext
  let log1: Logger
  let log2: Logger

  beforeEach(() => {
    baseAppender = newMockAppender()

    contextAppender1 = newMockAppender()
    contextAppender2 = newMockAppender()

    context1 = LogContext.with([contextAppender1])
    context2 = LogContext.with([contextAppender2])

    manager.setAppenders(baseAppender).setRootLevel("debug")

    log1 = getLogger("log1")
    log2 = getLogger("log2")
  })

  it("works with no contexts", async () => {
    log1.info("test1")
    log2.info("test2")

    expect(baseAppender.append).toBeCalledTimes(2)
  })

  it("works with no context provider", async () => {
    log1.info("test1")
    await context1.use(async () => {
      log1.info("test2")
    })

    expect(baseAppender.append).toBeCalledTimes(2)
    expect(contextAppender1.append).toBeCalledTimes(0)
  })

  it("works with 1 contexts", async () => {

    // You must explicitly `install` the context provider to use contexts
    await import("@3fv/logger-proxy/context/providers/node")

    log1.info("test1")
    await context1.use(async () => {
      log1.info("test2")
    })

    expect(baseAppender.append).toBeCalledTimes(2)
    expect(contextAppender1.append).toBeCalledTimes(1)
  })

  it("works with n contexts", async () => {

    // You must explicitly `install` the context provider to use contexts
    await import("@3fv/logger-proxy/context/providers/node")

    log1.info("test1")
    await context1.use(async () => {
      log1.info("test2")
      await context2.use(async () => {
        log1.info("test3")
      })
    })

    expect(baseAppender.append).toBeCalledTimes(3)
    expect(contextAppender1.append).toBeCalledTimes(2)
    expect(contextAppender2.append).toBeCalledTimes(1)
  })
})
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文