如何记录导致异常的源行并添加自定义信息?

发布于 2024-11-27 19:02:10 字数 1571 浏览 1 评论 0原文

我们的应用程序使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

_畞蕅 2024-12-04 19:02:10

除了 Marjan Vennema 的答案(我将遵循)之外,您还可以引发新异常并使其看起来像是来自旧异常的地址。

except
  on E: Exception do
    raise Exception.CreateFmt('myvar = %s', [myvar]) at ExceptAddr;
end;

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.

except
  on E: Exception do
    raise Exception.CreateFmt('myvar = %s', [myvar]) at ExceptAddr;
end;
爱的故事 2024-12-04 19:02:10

您正在丢失异常的原始源代码行,因为

  except
    on E: Exception do
      raise TException.CreateFmt('myvar = %s', [myvar]);
  end; 

有效地处理了原始异常(使其消失)并引发了一个新异常。当然,其中将有自己的“例外源行”。

@balazs 的解决方案在新异常的消息中保留原始异常的源行。 @Stephane 的解决方案接近我会使用的解决方案。不幸的是,他只用 myvar 的值替换了原始消息。我要做的就是在原始消息的顶部添加一行,然后重新引发异常:

except
  on E: Exception do
  begin
    E.Message := Format('%s'#13#10'%s', [Format('MyVar: %s', [MyVar]), E.Message]);
    raise;
  end;
end; 

You are losing the original source line of the exception, because

  except
    on E: Exception do
      raise TException.CreateFmt('myvar = %s', [myvar]);
  end; 

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:

except
  on E: Exception do
  begin
    E.Message := Format('%s'#13#10'%s', [Format('MyVar: %s', [MyVar]), E.Message]);
    raise;
  end;
end; 
鸠魁 2024-12-04 19:02:10

我你试过类似的事情吗?

 try    
    myvar := MyFunc;    
    ComplexFunc(myvar); 
 except
    on E: Exception do
    begin
      e.message := format('myvar = %s', [myvar]);
      raise ;
    end; 
  end;

I've you tried something like that ?

 try    
    myvar := MyFunc;    
    ComplexFunc(myvar); 
 except
    on E: Exception do
    begin
      e.message := format('myvar = %s', [myvar]);
      raise ;
    end; 
  end;
平生欢 2024-12-04 19:02:10

我不知道 LogLastException 会做什么,但是如果您可以将其结果重定向到字符串而不是日志中,则可以像这样重新引发异常:

  except
    on E: Exception do
    begin
      str := LogLastExceptionToString(E, 'Unhandled Exception (%s)', [E.Message], 20);  
      raise TException.CreateFmt( str + 'myvar = %s message so far:' , [myvar]);
    end; 
  end;

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:

  except
    on E: Exception do
    begin
      str := LogLastExceptionToString(E, 'Unhandled Exception (%s)', [E.Message], 20);  
      raise TException.CreateFmt( str + 'myvar = %s message so far:' , [myvar]);
    end; 
  end;
︶葆Ⅱㄣ 2024-12-04 19:02:10

一种简单的方法是定义一个全局变量,为其分配额外的信息,然后在记录异常信息时将其内容添加到日志中。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文