Внедрение логгирования в вызов функции

Настраиваю логгер у себя в проекте, мне нужно отследить все действия связанные с буфером, например. Первое, что приходит в голову, это следующий код:

Buffer.alloc = (...args) => {
  log(`Buffer allocated!`)
  return Buffer.alloc(...args)
}

Что естественно вызовет переполнение стека.

Другой способ работает, но он достаточно муторный и требует танцев с бубнами над TypeScript

Buffer.alloc = 
(arg1, arg2, arg3, logged: boolean) => { // <-- Implicit any + [signature] is not assignable...
  if(logged) return
  log()
  return Buffer.alloc(arg1, arg2, arg3, true)
}

Хочется чего-то вроде

inject(Buffer.alloc, size => log(`Allocating buffer with ${size} size`))

Ответы (1 шт):

Автор решения: LIMPIX64

Пришёл к такому TypeScript-friendly решению.

const inject = <T extends (...args: Parameters<T>) => ReturnType<T>, P extends Parameters<T>>(target: T, cb: (meta, ...args: P) => void): T => {
  const metadata = {
    /* e.g. stacktrace */
  }
  return ((...args: P) => {
    cb(metadata, ...args)
    return target(...args)
  }) as T
}

Buffer.alloc = inject(Buffer.alloc, (meta, size) => console.log(`Allocating buffer with ${size} bytes`))

Buffer.alloc(128) // Allocating buffer with 128 bytes
Buffer.alloc(256) // Allocating buffer with 256 bytes
→ Ссылка