O ASP.NET 2.0 introduziu uma nova API chamada de Health Monitoring. Esta API permite-nos, de forma flexível, ajustar o log/auditoria de uma aplicação ASP.NET. Como sabemos, podemos hospedar um serviço WCF dentro de uma aplicação ASP.NET e, sendo assim, poderíamos utilizar esta mesma API para conseguirmos logar possíveis eventos (isso pode incluir exceções) que o serviço venha a disparar.
Basicamente o que precisamos fazer é criar um evento customizado para o WCF e configurá-lo como já acontecia (isso é mostrado em detalhes neste artigo). Uma vez que o evento é criado, podemos anexá-lo dentro do runtime do WCF, mas isso exige algumas técnicas. A primeira delas é implementar a Interface IErrorHandler que, por sua vez, disponibiliza dois métodos: HandleError e ProvideFault. O método HandleError é sempre invocado quando alguma exceção ocorre dentro do serviço e, é fornecido para esse método um parametro do tipo Exception que representa o erro ocorrido. É no interior deste método que devemos criar o evento, definir a mensagem e, finalmente, invocar o método Raise para persistí-lo no provider especificado na configuração do Health Monitoring (mais adiante).
Para concluir, ainda é necessário implementar a Interface IServiceBehavior que fornece um mecanismo para interceptar e inserir comportamentos específicos ao serviço como um todo. Nos métodos fornecidos por essa Interface, utilizaremos o ApplyDispatchBehavior, que nos permitirá adicionar extensões, como error handlers (tema do post), interceptors, etc.. Abaixo a classe que implementa essas Interfaces e também a Interface do contrato do serviço:
public class ServiceImpl : IData, IServiceBehavior, IErrorHandler
{
public string Teste(string value)
{
if (string.IsNullOrEmpty(value))
throw new FaultException<ArgumentNullException>(new ArgumentNullException(“value”));
return “Ola ” + value;
}
public void AddBindingParameters(…) { }
public void ApplyDispatchBehavior(…)
{
foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
dispatcher.ErrorHandlers.Add(this);
}
public void Validate(…) { }
public bool HandleError(Exception error)
{
new WCFErrorEvent(error.ToString(), null, 0).Raise();
return true;
}
public void ProvideFault(…) { }
}
Para o exemplo, eu implementei as duas Interfaces na mesma classe de serviço, o que não é muito aconselhável, já que polui muito o código, misturando características do runtime com a regra de negócio. Se notarem, dentro do método ApplyDispatchBehavior adicionamos em todos na coleção de dispatcher channels a instancia corrente da classe para que, no momento em que o erro for disparado, esse tratamento/log seja efetuado.
Para finalizar, apenas resta especificar a configuração do Health Monitoring dentro do arquivo Web.Config da aplicação para que finalmente todos os eventos sejam persistidos.
<healthMonitoring enabled=”true”>
<eventMappings>
<add name=”WCF Error Event” type=”MyService.WCFErrorEvent”/>
</eventMappings>
<rules>
<clear/>
<add
name=”All Errors Default”
eventName=”WCF Error Event”
provider=”EventLogProvider”
profile=”Default”
minInterval=”00:01:00″/>
</rules>
</healthMonitoring>