【问题标题】:How to log the "path taken" by the code and its exceptions如何记录代码及其异常的“路径”
【发布时间】:2017-10-25 00:11:55
【问题描述】:

我需要通过用户点击中的代码所采用的路径来编写日志消息。我举个例子:

想象一下经典示例:用户单击视图中的按钮,从业务层调用代码,从数据访问层调用代码,将数据返回给业务,返回视图。 我想通过这些层编写我的日志消息。启动整个过程的调用方方法(在视图中)将收到完整的消息。这里有一些代码示例只是为了帮助我解释我想要实现的目标。

public void ViewMethod()
{
    try
    {
        BussinessMethod();           
    }
    catch (Exception ex)
    {
         Logger.Enqueue("exception occured");
         Logger.Print();
    }
}

public void BussinessMethod()
{
    try
    {
        DataAcessMethod();
    }
    catch (Exception ex)
    {
         Logger.Enqueue("exception occured in the bussiness method")
    }
}

public void DataAcessMethod()
{
    try
    {
        // some code that executes an SQL command
        // Log the SQL Command 1
        // Log the SQL Command 2 and do on...
    }
    catch (Exception ex)
    {
         Logger.Enqueue("Error occurred, sqls executed are ...", sqlExecuted);
    }
}

EDIT: 我需要它的原因是我需要记录整个过程中执行的所有 SQL。如果整个过程中的任何一点发生错误,都不会警告用户,我需要尽可能多地存储信息,因为支持技术人员稍后会需要它。

我的问题是,是否有任何设计模式来开发它或跨“层”传递 Logger 引用是否可以接受?

【问题讨论】:

  • 您可以创建一个上下文类并在线程上设置它。或者,一些可以是线程静态的属性。但实际上,为什么不直接在ViewMethod 中捕获异常?可以说,DataAcessMethod 失败了。在BussinessMethod 中继续执行甚至没有意义。在BussinessMethod 中尝试捕获与其代码相关的异常。并且对从数据层传播的异常不做任何事情
  • 恕我直言,Logger(无论您使用哪个)不只是用于例外 - 它们具有“级别”,其中之一是 Info(信息日志记录)。
  • 您关心堆栈跟踪还是只想记录消息?
  • @T.S.我这样提出问题的原因是我想记录整个过程中执行的sql。
  • @JohanP 堆栈跟踪对我非常有用。

标签: c# .net exception exception-handling


【解决方案1】:

我会做这样的事情

public class Context
{
     [ThreadStatic]
     private static LogStore _store; 

     public static Log(....)
     {
         .....
     } 
}

public void ViewMethod()
{

    var response = BussinessMethod();           
    if (response.Status = ResponseStatus.Success)
        // do something with response.Data
    else
        // show message?
}

public BusinessMethodResponse BussinessMethod()
{

    var response = new BusinessMethodResponse() {Status = ResponseStatus.Failure};
    SomeData data;
    try
    {
        data = DataAcessMethod();
    }
    catch (Exception ex)
    {
        Context.Log(....);
        response.Message = "Data retrieval failed";
        return response;
    }
    try
    {
        // massage the data here
        response.Status = ResponseStatus.Success;
        response.Data = myMassagedData;
    }
    catch (Exception ex)
    {
         Context.Log(....);
         response.Message = "Something failed";
    }

    return response;
}

public void DataAcessMethod()
{
    // some code that executes an SQL command
}

这是做什么的?现在您可以从 MVC、WPF、WinForms、Web 窗体等调用您的业务对象...

【讨论】:

  • 小心 MVC 或 Web 窗体的 ThreadStatic。 ASP.NET 有一个称为线程关联的功能,它允许在某些情况下 Web 请求在一个线程上开始处理并切换到另一个线程。我已经看到在负载下的系统上发生这种情况的生产案例,最终将数据放入 ThreadStatic 成员“以提高效率”,将一个用户的数据暴露给另一个用户。诚然,这是一个边缘案例,但最好是在知道风险的情况下走这条路,而不是措手不及。
  • @KyleBurns 同意。但我认为,它不会影响直接调用链。
  • 如果某些东西最终等待 I/O(如数据库或服务调用),则在负载下,可以选择线程暂停,然后在完成阻塞调用后在另一个线程上恢复。这是一个艰难的教训......
猜你喜欢
  • 1970-01-01
  • 2022-11-28
  • 2010-10-17
  • 2014-02-28
  • 1970-01-01
  • 2015-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多