All Projects → aigoncharov → Cls Proxify

aigoncharov / Cls Proxify

Licence: mit
Logging on steroids with CLS and Proxy. Integrated with express, koa, fastify.

Programming Languages

typescript
32286 projects

Projects that are alternatives of or similar to Cls Proxify

Class Logger
Boilerplate-free decorator-based class logging
Stars: ✭ 64 (-51.52%)
Mutual labels:  hacktoberfest, proxy, logging
Pizzly
The simplest, fastest way to integrate your app with an OAuth API 😋
Stars: ✭ 796 (+503.03%)
Mutual labels:  hacktoberfest, proxy
Splat
Makes things cross-platform
Stars: ✭ 753 (+470.45%)
Mutual labels:  hacktoberfest, logging
Axios Module
Secure and easy axios integration with Nuxt.js
Stars: ✭ 998 (+656.06%)
Mutual labels:  hacktoberfest, proxy
Logary
Logs and metrics are one! Professional logging, metrics and analytics for your apps.
Stars: ✭ 479 (+262.88%)
Mutual labels:  logging, tracing
Zipkin Js
Zipkin instrumentation for Node.js and browsers
Stars: ✭ 489 (+270.45%)
Mutual labels:  hacktoberfest, tracing
Reqray
Log call tree summaries after each request for rust programs instrumented with `tracing`.
Stars: ✭ 37 (-71.97%)
Mutual labels:  logging, tracing
Socks5
A full-fledged high-performance socks5 proxy server written in C#. Plugin support included.
Stars: ✭ 286 (+116.67%)
Mutual labels:  hacktoberfest, proxy
Zio Logging
Simple logging for ZIO apps, with correlation, context & pluggable backends out of the box.
Stars: ✭ 85 (-35.61%)
Mutual labels:  logging, tracing
Tracing
Application level tracing for Rust.
Stars: ✭ 1,294 (+880.3%)
Mutual labels:  logging, tracing
Capture Thread
Lock-free framework for loggers, tracers, and mockers in multithreaded C++ programs.
Stars: ✭ 93 (-29.55%)
Mutual labels:  logging, tracing
Memento
Memento is a development-only tool that caches HTTP calls once they have been executed.
Stars: ✭ 380 (+187.88%)
Mutual labels:  hacktoberfest, proxy
Exceptionless.net
Exceptionless clients for the .NET platform
Stars: ✭ 362 (+174.24%)
Mutual labels:  hacktoberfest, logging
Gf
GoFrame is a modular, powerful, high-performance and enterprise-class application development framework of Golang.
Stars: ✭ 6,501 (+4825%)
Mutual labels:  logging, tracing
Stream
🗄️ Stream plugin for WordPress
Stars: ✭ 335 (+153.79%)
Mutual labels:  hacktoberfest, logging
Eliot
Eliot: the logging system that tells you *why* it happened
Stars: ✭ 874 (+562.12%)
Mutual labels:  logging, tracing
Aiologger
Asynchronous logging for python and asyncio
Stars: ✭ 284 (+115.15%)
Mutual labels:  hacktoberfest, logging
Nestjs Pino
Platform agnostic logger for NestJS based on Pino with REQUEST CONTEXT IN EVERY LOG
Stars: ✭ 283 (+114.39%)
Mutual labels:  hacktoberfest, logging
Drf Api Tracking
Fork of aschn/drf-tracking so that we can maintain and release newer versions
Stars: ✭ 117 (-11.36%)
Mutual labels:  hacktoberfest, logging
Madelineproto
Async PHP client/server API for the telegram MTProto protocol
Stars: ✭ 1,776 (+1245.45%)
Mutual labels:  hacktoberfest, proxy

cls-proxify Build Status Coverage Status Tweet

Logging on steroids with CLS and Proxy. A small library that proxies any arbitrary object with a proxy from Continuation-Local Storage a.k.a. CLS if found one. Super-useful for creating child loggers per each request with dynamic context from the request itself (e.g. adding request trace ID, adding request payload). Integrated with express, koa, fastify out-of-the-box.

Many thanks to @mcollina for the idea of combining Proxy and CLS.

Installation

npm i cls-proxify cls-hooked

Quick start

Express

TypeScript users, clsProxifyExpressMiddleware uses typings from @types/express. Please, run npm i -D @types/express

import { clsProxify } from 'cls-proxify'
import { clsProxifyExpressMiddleware } from 'cls-proxify/integration/express'
import * as express from 'express'

const logger = {
  info: (msg: string) => console.log(msg),
}
const loggerCls = clsProxify('clsKeyLogger', logger)

const app = express()
app.use(
  clsProxifyExpressMiddleware('clsKeyLogger', (req) => {
    const headerRequestID = req.headers.Traceparent
    const loggerProxy = {
      info: (msg: string) => `${headerRequestID}: ${msg}`,
    }
    // this value will be accesible in CLS by key 'clsKeyLogger'
    // it will be used as a proxy for `loggerCls`
    return loggerProxy
  }),
)

app.get('/test', (req, res) => {
  loggerCls.info('My message!')
  // Logs `${headerRequestID}: My message!` into the console
  // Say, we send GET /test with header 'Traceparent' set to 12345
  // It's going to log '12345: My message!'
  // If it doesn't find anything in CLS by key 'clsKeyLogger' it uses the original `logger` and logs 'My message!'
})

Koa

TypeScript users, clsProxifyKoaMiddleware uses typings from @types/koa. Please, run npm i -D @types/koa

import { clsProxify } from 'cls-proxify'
import { clsProxifyKoaMiddleware } from 'cls-proxify/integration/koa'
import * as Koa from 'koa'

const logger = {
  info: (msg: string) => console.log(msg),
}
const loggerCls = clsProxify('clsKeyLogger', logger)

const app = new Koa()
app.use(
  clsProxifyKoaMiddleware('clsKeyLogger', (ctx) => {
    const headerRequestID = ctx.req.headers.Traceparent
    const loggerProxy = {
      info: (msg: string) => `${headerRequestID}: ${msg}`,
    }
    // this value will be accesible in CLS by key 'clsKeyLogger'
    // it will be used as a proxy for `loggerCls`
    return loggerProxy
  }),
)

app.use((ctx) => {
  loggerCls.info('My message!')
  // Logs `${headerRequestID}: My message!` into the console
  // Say, we send GET / with header 'Traceparent' set to 12345
  // It's going to log '12345: My message!'
  // If it doesn't find anything in CLS by key 'clsKeyLogger' it uses the original `logger` and logs 'My message!'
})

Fastify

import { clsProxify } from 'cls-proxify'
import { clsProxifyFastifyMiddleware } from 'cls-proxify/integration/fastify'
import * as fastify from 'fastify'

const logger = {
  info: (msg: string) => console.log(msg),
}
const loggerCls = clsProxify('clsKeyLogger', logger)

const app = fastify()
app.use(
  clsProxifyFastifyMiddleware('clsKeyLogger', (req) => {
    const headerRequestID = ctx.req.headers.Traceparent
    const loggerProxy = {
      info: (msg: string) => `${headerRequestID}: ${msg}`,
    }
    // this value will be accesible in CLS by key 'clsKeyLogger'
    // it will be used as a proxy for `loggerCls`
    return loggerProxy
  }),
)

app.get('/test', (req, res) => {
  loggerCls.info('My message!')
  // Logs `${headerRequestID}: My message!` into the console
  // Say, we send GET /test with header 'Traceparent' set to 12345
  // It's going to log '12345: My message!'
  // If it doesn't find anything in CLS by key 'clsKeyLogger' it uses the original `logger` and logs 'My message!'
})

Any other framework or library

import { clsProxify, clsProxifyNamespace } from 'cls-proxify'
import AbstractWebServer from 'abstract-web-server'

const logger = {
  info: (msg: string) => console.log(msg),
}
const loggerCls = clsProxify('clsKeyLogger', logger)

const app = new AbstractWebServer()
// Assuming this AbstractWebServer supports some form of middlewares
app.use((request, response, next) => {
  // Assuming your request and response are event emitters
  clsProxifyNamespace.bindEmitter(request)
  clsProxifyNamespace.bindEmitter(response)

  clsProxifyNamespace.run(() => {
    const headerRequestID = request.headers.Traceparent
    // this value will be accesible in CLS by key 'clsKeyLogger'
    // it will be used as a proxy for `loggerCls`
    const loggerProxy = {
      info: (msg: string) => `${headerRequestID}: ${msg}`,
    }
    setClsProxyValue('clsKeyLogger', loggerProxy)

    next()
  })
})

app.get('/test', (req, res) => {
  loggerCls.info('My message!')
  // Logs `${headerRequestID}: My message!` into the console
  // Say, we send GET /test with header 'Traceparent' set to 12345
  // It's going to log '12345: My message!'
  // If it doesn't find anything in CLS by key 'clsKeyLogger' it uses the original `logger` and logs 'My message!'
})

In depth

How it works

If you're struggling to grasp the idea behind CLS at these two articles: Request Id Tracing in Node.js Applications, A Pragmatic Overview of Async Hooks API in Node.js.

Take a look at this article which overviews how CLS works and covers the idea behind this library.

We wrap our original logger in a Proxy. Every time we try to access any property of that object we first check if there's an updated logger in CLS available. If it's there we take the property from it. If it's not we take the property from the original logger. Then for every request we create a CLS context using run and bindEmitter. Once the context is created we enhance our original logger with some extra data and put the updated logger in the context. Once we try to call any method of our logger we'll actually call the same method on our logger in CLS.

Does it work only for loggers?

No. You can proxify any object you want. Moreover you can even proxify functions and class constructors.

Here's a list of traps cls-proxify provides:

Take a look at the tests to get an idea of how you can utilize them.

Live demos

Usage with pino and fastify

Usage with pino and express

Troubleshooting

My context got lost

Note that some middlewares may cause CLS context to get lost. To avoid it use any third party middleware that does not need access to request ids before you use this middleware.

I'm experiencing a memory leak

Make sure you don't keep any external references to the objects inside of CLS. It may prevent them from being collected by GC. Take a look at this issues: #21, #11.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].