WCF、IErrorHandler 和 log4Net

发布于 2024-10-14 00:56:30 字数 2009 浏览 8 评论 0原文

我正在尝试在 wcf 服务上实现错误处理行为,该服务将使用 log4net 记录异常

[AttributeUsage(AttributeTargets.Class)]
public class AErrorHandlerBehaviorAttribute : Attribute, IServiceBehavior, IErrorHandler{

  private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

  protected Type ServiceType { get; set; }
  public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
  {
   //Dont do anything
  }

  public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection <ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
  {
   //dont do anything
  }

  public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
  {
   ServiceType = serviceDescription.ServiceType;
   foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
   {
    dispatcher.ErrorHandlers.Add(this);
   }
  }

  public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
  {
   fault = null; //Suppress any faults in contract
  }

  public bool HandleError(Exception error)
  {   
   log.Error("Page Load failed : " + error.Message); 
   return false;
  }
}

,然后实现使用该行为的服务。如果我在服务中声明 ILog 变量,则效果很好。

[AErrorHandlerBehavior]
public class AService : IAService
{

     private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        ....//various methods
}

但是,当未声明 ILog 变量时,日志记录将停止工作。

[AErrorHandlerBehavior]
public class AService : IAService
{

     //private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        ....//various methods
}

理想情况下,我不想在我生成的每个服务中都声明 ILog 变量,特别是当它已经在行为中声明时。

有人可以解释一下 a) 为什么必须在行为和服务中声明这一点。 b) 避免双重声明的任何方法或 c) 登录 wcf 的更好方法。

I am trying to implement an error handling behavior on a wcf service that will use log4net to log an exception

[AttributeUsage(AttributeTargets.Class)]
public class AErrorHandlerBehaviorAttribute : Attribute, IServiceBehavior, IErrorHandler{

  private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

  protected Type ServiceType { get; set; }
  public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
  {
   //Dont do anything
  }

  public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection <ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
  {
   //dont do anything
  }

  public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
  {
   ServiceType = serviceDescription.ServiceType;
   foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
   {
    dispatcher.ErrorHandlers.Add(this);
   }
  }

  public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
  {
   fault = null; //Suppress any faults in contract
  }

  public bool HandleError(Exception error)
  {   
   log.Error("Page Load failed : " + error.Message); 
   return false;
  }
}

I then implement a service that uses the behavior. This works fine if I declare the ILog variable within the service

[AErrorHandlerBehavior]
public class AService : IAService
{

     private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        ....//various methods
}

However, when the ILog variable is not declared the logging stops working.

[AErrorHandlerBehavior]
public class AService : IAService
{

     //private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        ....//various methods
}

Ideally I don't want to have to declare the ILog variable in every service I produce, especially when it is already declared in the behavior.

Could someone please explain a) why this has to be declared in both the behavior and in the service. and b) any way of avoiding the double declaration or c) a better way of logging in wcf.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(2

携余温的黄昏 2024-10-21 00:56:30

我不相信您用来解析该 Log 对象的代码:

private static readonly ILog log = 
  LogManager.GetLogger(
    System.Reflection.MethodBase.GetCurrentMethod().DeclaringType
  );

这将始终解析为编写代码行的类型,因为它首先解析自动定义的静态构造函数(使用 MethodInfo.周围类的 GetCurrentMethod()),然后获取其声明类型。

好吧,我说总是...

我不喜欢这种模式,因为它隐式依赖于您尚未亲自编写的代码(因此编译器的一个内部功能 >可能随时更改);如果您明确地将其放置在您自己编写的静态构造函数中,效果会稍微好一些。

如果你想这样做,那么使用

typeof(_whatever_type_you_declare_it_in_);

...不要依赖编译器和运行时。

同样 - 我有一种感觉,您可能会错误地认为该模式会解析为定义该属性的服务,但实际上不会。

您是否打算能够控制在服务级别使用的日志,并使用行为级别默认值?

如果是这样,那么我建议您:

1) 在您的行为中添加一个名为 _serviceLog 的实例级 ILog 属性

2) 在您的 ApplyDispatchBehaviour 实现中> 这样做:

_serviceLog = LogManager.GetLogger(serviceDescription.ServiceType);

3) 然后你的 HandleError 实现可能如下:

public bool HandleError(Exception error)
{
  //use the service-level log, or a default
  ILog targetLog = _serviceLog ?? log;
  if(targetLog != null)
    targetLog.Error("Page Load failed : " + error.Message);
  return false;
}

I'm not convinced of the code you're using to resolve that Log object:

private static readonly ILog log = 
  LogManager.GetLogger(
    System.Reflection.MethodBase.GetCurrentMethod().DeclaringType
  );

This will always resolve to the type within which the line of code is written as it resolves first the auto-defined static constructor (with MethodInfo.GetCurrentMethod() of the surrounding class) and then gets its declaring type.

Well, I say always...

I don't like this kind of pattern as it implicitly relies on code that you haven't physically written yourself (and therefore an internal feature of the compiler that could change at any time); it would be marginally better if you explicitly placed it inside a static constructor you write yourself.

If you want to do this, then use

typeof(_whatever_type_you_declare_it_in_);

... don't rely on the compiler and the runtime.

Equally - I have a feeling you might be using this pattern under the mistaken belief that it'll resolve to the service on which the attribute is defined, it won't.

Is your intention to be able to control the log to be used at the service-level, with a behaviour-level default?

If so, then I suggest you:

1) Add an instance-level ILog property to your behaviour, called _serviceLog

2) In your implementation of ApplyDispatchBehaviour do this:

_serviceLog = LogManager.GetLogger(serviceDescription.ServiceType);

3) And then your implementation of HandleError could be as follows:

public bool HandleError(Exception error)
{
  //use the service-level log, or a default
  ILog targetLog = _serviceLog ?? log;
  if(targetLog != null)
    targetLog.Error("Page Load failed : " + error.Message);
  return false;
}
九局 2024-10-21 00:56:30

实际的问题是,忽略获取记录器的正确方法是什么,在行为中我没有配置记录器。

解决方法只是将配置语句添加到 ApplyDispatchBehavior

public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            XmlConfigurator.Configure();            
            foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
            {
                dispatcher.ErrorHandlers.Add(this);
            }
        }

我推测我可以在没有此行为的情况下进行日志记录的原因是因为服务中 ILog 的声明导致了错误发生之前记录器的配置抛出

the actual problem, ignoring what is the correct way to get the logger, was that in the behaviour I had not configured the logger.

The fix was simply to add the Configure statement to ApplyDispatchBehavior

public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            XmlConfigurator.Configure();            
            foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
            {
                dispatcher.ErrorHandlers.Add(this);
            }
        }

I presume the reason why I could log from the behaiour without this was because the declaration for ILog in the service caused the configuration of the logger before the error was thrown

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