如何记录导致异常的源行并添加自定义信息?
我们的应用程序使用 JCL 记录导致异常的源代码行,并且效果很好。 我用的是D2007。我有一个 TApplicationEvents.OnException 事件来执行实际的日志记录。 考虑一下:
function MyFunc: String;
begin
// Codelines that may raise exception.
// Call functions that also may raise exception
end;
procedure ComplexFunc(aVariable: String);
begin
// also here can it be exceptions....
// Code here that is the cause of exception
end;
procedure foo;
var
myVar: String;
begin
myvar := MyFunc;
ComplexFunc(myvar);
end;
procedure TMainForm.ApplicationEvents1Exception(Sender: TObject; E: Exception);
begin
LogLastException(E, 'Unhandled Exception (%s)', [E.Message], 20);
end;
我有 3 个方法和 onException 事件。 LogLastException 发生异常时记录调用堆栈。问题是我无法在不丢失导致异常的源代码行的情况下向 E.Message 添加信息。假设这是 ComplexFunc 中的第二行引发异常。我还想记录 myvar 变量的值。因此,我将代码更改为:
function MyFunc: String;
begin
// Codelines that may raise exception.
// Call functions that also may raise exception
end;
procedure ComplexFunc(aVariable: String);
begin
// also here can it be exceptions....
// Code here that is the cause of exception
end;
procedure foo;
var
myVar: String;
begin
try
myvar := MyFunc;
ComplexFunc(myvar);
except
on E: Exception do
raise TException.CreateFmt('myvar = %s', [myvar]);
end;
end;
procedure TMainForm.ApplicationEvents1Exception(Sender: TObject; E: Exception);
begin
LogLastException(E, 'Unhandled Exception (%s)', [E.Message], 20);
end;
现在记录了 myvar 的值,但代价是我丢失了异常的原始源代码行。相反,会记录带有 raise TException.CreateFmt 的行。关于如何做到这两点有什么建议吗?
问候
Our application log the source line causing exception with JCL and it works great.
I use D2007. I have a TApplicationEvents.OnException event that do the actual logging.
Consider this:
function MyFunc: String;
begin
// Codelines that may raise exception.
// Call functions that also may raise exception
end;
procedure ComplexFunc(aVariable: String);
begin
// also here can it be exceptions....
// Code here that is the cause of exception
end;
procedure foo;
var
myVar: String;
begin
myvar := MyFunc;
ComplexFunc(myvar);
end;
procedure TMainForm.ApplicationEvents1Exception(Sender: TObject; E: Exception);
begin
LogLastException(E, 'Unhandled Exception (%s)', [E.Message], 20);
end;
I have 3 methods and my onException event.
LogLastException log the callstack when an exception occurs. The problem is that I cannot add information to the E.Message without loose the sourceline that cause exception. Pretend it is the second line in ComplexFunc that raise exception. I also want to log the value of myvar variable. So I change the code to:
function MyFunc: String;
begin
// Codelines that may raise exception.
// Call functions that also may raise exception
end;
procedure ComplexFunc(aVariable: String);
begin
// also here can it be exceptions....
// Code here that is the cause of exception
end;
procedure foo;
var
myVar: String;
begin
try
myvar := MyFunc;
ComplexFunc(myvar);
except
on E: Exception do
raise TException.CreateFmt('myvar = %s', [myvar]);
end;
end;
procedure TMainForm.ApplicationEvents1Exception(Sender: TObject; E: Exception);
begin
LogLastException(E, 'Unhandled Exception (%s)', [E.Message], 20);
end;
Now the value of myvar is logged, BUT at the price of I loose the original sourceline of the exception. Instead the line with raise TException.CreateFmt is logged. Any suggestion of how to do both ?
Regards
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
除了 Marjan Vennema 的答案(我将遵循)之外,您还可以引发新异常并使其看起来像是来自旧异常的地址。
In addition to Marjan Vennema's answer (which I would follow), you can raise your new exception and make it look like it came from the address of the old exception.
您正在丢失异常的原始源代码行,因为
有效地处理了原始异常(使其消失)并引发了一个新异常。当然,其中将有自己的“例外源行”。
@balazs 的解决方案在新异常的消息中保留原始异常的源行。 @Stephane 的解决方案接近我会使用的解决方案。不幸的是,他只用 myvar 的值替换了原始消息。我要做的就是在原始消息的顶部添加一行,然后重新引发异常:
You are losing the original source line of the exception, because
effectively handles the original exception (making it go away) and raising a new one. Which, of course then will have its own "source line of exception."
@balazs' solution preserves the source line of the original exception in the message of the new exception. @Stephane's solution comes close to the one I would use. Unfortunately he is replacing the original message with only the value of myvar. What I would do is add a line on top of the original message and then just re-raise the exception:
我你试过类似的事情吗?
I've you tried something like that ?
我不知道 LogLastException 会做什么,但是如果您可以将其结果重定向到字符串而不是日志中,则可以像这样重新引发异常:
I don't know what LogLastException do, but if you can redirect it's result into a string rather than your log, you can reraise the exception like this:
一种简单的方法是定义一个全局变量,为其分配额外的信息,然后在记录异常信息时将其内容添加到日志中。
A simple approach would be to define a global variable, assign the extra information to it, and then add its contents to your log when you log the exception information.