Get name of function that called current function

huangapple go评论80阅读模式
英文:

Get name of function that called current function

问题

我希望能够在不减慢或使日志功能过于复杂的情况下,为记录目的获取调用日志功能的函数的函数名。

.log.err:{[x;y]x y}[-2;]

例如,如果我在函数 f1 中调用 .log.err"记录错误消息",我希望它附加函数名。这将打印"记录错误消息 f1"。

我知道我可以运行 ```value .z.s``` 并将其传递给 .log.err,但我不想向该函数添加额外的参数。有没有什么好的方法来实现这个?
英文:

I want to be able to get the function name of the function that calls the log function for logging purposes without slowing down or making the log function too complicated.

.log.err:{[x;y]x y}[-2;]

For example, if I call .log.err"log error msg" inside function f1, I want it to append the function name. So it would print "log error msg f1".

I know I could run value .z.s and pass that through to .log.err but I don't want to add an additional argument to the function. Is there any good way to do this?

答案1

得分: 3

这是一个使用一些未记录的内部函数的替代方法(即在将来的q版本中可能会发生更改)。如果我们查看(已记录的)函数.Q.bt的代码,我们可以找到.Q.Ll.Q.btx - 我们可以使用这些来获取当前的调用堆栈,而无需捕获错误。

以下是一个提取调用者的函数名称(以及文件和行号)的示例脚本:

.log.err:{[x;y]
 d:dbg0[2]y;
 x d[`func]," [",d[`file],":",string[d`line],"] : ",y;
}[-2]

dbg0:{[x;y]
 f:first x _ .Q.btx .Q.Ll`;
 d:`func`file`line!3#f[1];
 d[`line]+:sum"\n"=f[2]#f[1;3];
 d
}

f1:{.log.err"test"}
f2:{.log.err"test"}
.jm.f:{.log.err"test"}

注意:我们将参数2传递给dbg0以从调用堆栈中移除dbg0.log.err,从而将顶部帧留给.log.err的调用者。如果您将代码从dbg0移到.log.err而不是一个单独的函数中,您将希望将此更改为仅删除1帧,即.log.err

演示如下:

q)f1[]
..f1 [/home/jmcmurray/test.q:15] : test
q)f2[]
..f2 [/home/jmcmurray/test.q:16] : test
q).jm.f[]
.jm.f [/home/jmcmurray/test.q:17] : test

请注意,顶级命名空间中的函数前缀为..以表示这一点。当然,您可以更改格式等。

对于在交互方式下定义的函数,不会显示文件和行号,而是为0,即:

q)f3:{.log.err"test"}
q)f3[]
..f3 [:0] : test

正如Terry提到的,您可能希望更多地查看回溯输出以实现更一般化的处理。

英文:

An alternative to Terry's solution, using some undocumented internal functions (i.e. could be subject to change in future versions of q). If we look at the code for the (documented) function .Q.bt, we find .Q.Ll and .Q.btx - we can use these to get the current call stack without trapping an error.

Here's an example script that extracts the function name (as well as file & line number) of the caller:

.log.err:{[x;y]
 d:dbg0[2]y;
 x d[`func]," [",d[`file],":",string[d`line],"] : ",y;
 }[-2]

dbg0:{[x;y]
 f:first x _ .Q.btx .Q.Ll`;
 d:`func`file`line!3#f[1];
 d[`line]+:sum"\n"=f[2]#f[1;3];
 d
 }

f1:{.log.err"test"}
f2:{.log.err"test"}
.jm.f:{.log.err"test"}

Note: we pass the arg 2 to dbg0 to remove dbg0 and .log.err from the call stack, thus leaving the top frame as the caller of .log.err. If you were to move the code from dbg0 into .log.err instead of a separate function, you'd want to change this to only drop 1 frame i.e. .log.err.

Demo of this in use:

q)f1[]
..f1 [/home/jmcmurray/test.q:15] : test
q)f2[]
..f2 [/home/jmcmurray/test.q:16] : test
q).jm.f[]
.jm.f [/home/jmcmurray/test.q:17] : test

Note that functions in top-level namespace are prefaced with .. to indicate this. Of course you could change how this is formatted etc.

For a function defined interactively, rather than within a script, this is shown with no file & line number 0 i.e.

q)f3:{.log.err"test"}
q)f3[]
..f3 [:0] : test

Again as Terry mentioned you may want to look more at the backtrace output to generalise this.

答案2

得分: 2

Credit to Steve Caron for this approach which was posted to the k4 listbox on 2023.05.24:

f1:{a:1;.log.err"foo";a+x};
f2:{a:2;.log.err"bar";a+x};
curstack:{.Q.trp[{`err};();{3_y}]}:
.log.err:{[x;y]x y," - ",last[curstack][1;3]}[-2;];

q)f1[10]
foo - f1[10]
11
q)f2[10]
bar - f2[10]
12

I don't think this will work in every situation - you should study the backtrace output in more detail as you would likely need to generalize this a bit more. Link to documentation

英文:

Credit to Steve Caron for this approach which was posted to the k4 listbox on 2023.05.24:

f1:{a:1;.log.err"foo";a+x};
f2:{a:2;.log.err"bar";a+x};
curstack:{.Q.trp[{'err};();{3_y}]};
.log.err:{[x;y]x y," - ",last[curstack`][1;3]}[-2;];

q)f1[10]
foo - f1[10]
11
q)f2[10]
bar - f2[10]
12

I don't think this will work in every situation - you should study the backtrace output in more detail as you would likely need to generalise this a bit more. https://code.kx.com/q/ref/dotq/#trp-extend-trap

huangapple
  • 本文由 发表于 2023年6月6日 00:15:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76408267.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定