用 bind 包装 consol.log 以保持调用者上下文

wrap consol.log with bind to keep caller context

我想记录一些消息文本并保留原始上下文(class,行号)。仅在与 console.log.bind(console) 一起正常工作的控制台输出上。问题是我还想将消息发送到某些 http 服务器以进行日志记录。

示例 1. 使用 getter & 绑定我可以将 console.log 传递给调用者并获取消息和上下文(class,行号)。但是 getter 函数在运行时不会有参数,因为这些参数已直接传递给控制台。所以我无法记录消息。

示例 2。如果我从 getter 更改为函数,我有参数(又名消息),可以将它发送到某个地方并并行 console.log 它。但是 console.log 行将显示我的记录器 class 因为它在那里使用并且未绑定。

示例 1


get debug() {
    let message = Array.prototype.slice.call(arguments);
    // send message over to some http server
    // ...

    return console.log.bind(console);
}

示例 2


public debug() {
    let message = Array.prototype.slice.call(arguments);
    // send message over to some http server
    // ...
    console.log.apply(console, args);
}

有没有一种方法可以保留 console.log 的上下文,但同时获取日志消息以进行进一步操作(将其发送到 http 服务器)?

首先上下文(当console.log为运行ning时this的值)在这里是没有意义的。这不会影响报告的 file/line 以任何方式记录。

对于 console.log 报告的 file/line 而言,重要的是调用函数的位置。由于它是本机代码的内置函数,您无法替换它并让它仍然有效。

所有这一切都意味着,如果您包装 console.log,以便对其参数进行任意操作,您将掩盖您打算成为调用站点的内容。


所以我认为你能得到的最好的办法是自己推导堆栈跟踪并将其与 JS 解释器认为正确的位置一起报告。您可以通过实例化一个 Error 并请求它的 stack.

来做到这一点
function debug(...args: any[]) {

  // Do your stuff here...
  sendArgsToServer(args) 

  // Get the line from the stack trace that is the previous caller.
  const callSite = new Error().stack!.split('\n')[2].trim()

  // Call console.log with the call site you want also reported on the end.
  console.log(...args, callSite)
}

function foo() {
  debug('my debug line')
}

foo()

当我在 Chrome 中 运行 时,我在控制台中得到了这个:

右边的index.ts:132是调试函数中console.log()的位置。但是 index.ts:135:5 紧接在您记录的内容之后是调用 debug() 的地方。

而且至少在 Chrome 中,这些链接都有效!单击其中一个会将您带到源窗格中源映射代码的相关位。

我很确定这是你在这里得到的最好的。