Desenvolvimento - C#

Tracing em serviços WCF

Esse artigo tem a finalidade de demonstrar a integração que os serviços WCF possibilitam para a captura e persistência dos erros para uma posterior análise.

por Israel Aéce



function doClick(index, numTabs, id) { document.all("tab" + id, index).className = "tab"; for (var i=1; i Toda e qualquer tipo de aplicação sempre exige uma forma de armazenar possíveis erros que possam acontecer durante a sua execução. Isso irá ajudar imensamente para diagnosticarmos problemas que ocorrem e, conseqüentemente, facilitar na sua solução. Isso não é diferente em serviços WCF. Esse artigo tem a finalidade de demonstrar a integração que os serviços WCF possibilitam para a captura e persistência dos erros para uma posterior análise.

Felizmente, o WCF já têm embutido em sua infraestrutura uma integração muito forte com o namespace System.Diagnostics que, por sua vez, fornece toda a parte de monitoramento da "saúde" das aplicações construídas sob a plataforma .NET. O monitoramento não está habilitado por padrão e, para isso, basta configurarmos algumas informações necessárias para o funcionamento do mesmo dentro do arquivo *.config.

É bom informar que, como pré-requisito para este artigo, você precisa conhecer as principais funcionalidades que são disponibilizadas pelo System.Diagnostics. O WCF já define alguns trace sources que você pode estar utilizando para efetuar os logs. Entre os trace sources disponíveis temos um chamado System.ServiceModel. Este trace source loga todos os estágios de um processamento de um serviço WCF, que vai desde a criação do mesmo, passando pela autenticação e transporte da mensagem, até o retorno do método. O código abaixo trata-se de um trecho do arquivo App.Config, que foi extraído de uma aplicação que consome o serviço WCF:

<system.diagnostics>
  <sources>
    <source
      name="System.ServiceModel"
      switchValue="All"
      propagateActivity="true">
      <listeners>
        <add
            name="TraceInXml"
            type="System.Diagnostics.XmlWriterTraceListener"
            initializeData="C:\AppLog.svclog" />
      </listeners>
    </source>
  </sources>
  <trace autoflush="true" />
</system.diagnostics>
App.Config

Analisando o trecho de código acima, especificamos o source como sendo System.ServiceModel para ser capaz de capturar todos os estágios do processamento do WCF. O elemento source possui dois outros atributos, chamados: switchValue e propagateActivity. O primeiro deles, switchValue, recebe uma combinação de valores (separados por vírgula) que especifica quais serão os tipos de informações que serão capturadas, ou seja, uma espécie de filtro. Como há várias possibilidades, a tabela abaixo descreve cada uma delas:

Nível Descrição
Off

Nenhum tipo de informação é capturada.

Critical

Somente eventos considerados "negativos" são capturados, ou seja, eventos que indicam um processamento inesperado ou um erro condicional. Neste cenário, algumas exceções não tratadas são capturadas e devidamente logadas. Entre essas exceções temos: OutOfMemoryException, ThreadAbortException, StackOverflowException, entre algumas outras.

Error

Somente eventos considerados "negativos" são capturados, ou seja, eventos que indicam um processamento inesperado ou um erro condicional. Neste cenário, todo e qualquer tipo de exceção não tratada é capturada e devidamente logada.

Warning

Somente eventos considerados "negativos" são capturados, ou seja, eventos que indicam um processamento inesperado ou um erro condicional. Refere-se a problemas que acontecem na sua aplicação, mas ela é capaz de continuar trabalhando.

Information

Somente eventos considerados "positivos" são capturados, ou seja, eventos que indicam o sucesso de uma determinada tarefa.

Verbose

Somente eventos considerados "positivos" são capturados, mas com a diferença em relação ao Information, de que estes eventos são considerados de "baixo nível", úteis em procedimento de debugging ou otimização.

ActivityTracing

Permite capturar eventos que estão contidos dentro uma determinada atividade. As atividades são abordadas de forma mais detalhada logo abaixo.

All

Todo e qualquer tipo de evento (que vimos acima) são capturados e devidamente logados.

Observação: Atente-se aos tipos de evento (filtro) que se aplica ao tracing. Utilize isso com uma restrição muito grande, definindo somente o que você precisa realmente capturar em sua aplicação/serviço. Dependendo, você pode estar forçando o runtime a salvar informações desnecessárias, comprometendo a performance da aplicação.

O segundo atributo é o propagateActivity. Ele é utilizado quando o atributo switchValue estiver definido como ActivityTracing, e recebe um valor booleano indicando se a atividade deve ou não ser propagada para os endpoints que participam do processo. Veremos mais detalhes sobre atividades e propagações a seguir. E, finalmente, depois do source configurado, devemos definir um listener (ou vários) que será responsável por persistir as informações em formato XML (quando utilizar o XmlWriterTraceListener) mas, como o WCF se utiliza dos listeners contidos dentro do namespace System.Diagnostics, nada impede de utilizar o TextWriterTraceListener e gerar o output em formato texto.

Atividades

As atividades são unidades de processamento que nos ajudam no processo de identificação de uma possível falha. Essas atividades agrupam todos os traces para cada unidade de processamento, facilitando o rastreamento de possíveis falhas que possam vir a ocorrer durante a execução de um determinado serviço WCF. As atividades estão sempre relacionadas e com o auxílio de uma ferramenta chamada Service Trace Viewer (mais abaixo falaremos sobre ela) poderemos visualizar o processo de forma gráfica.

Quando falamos de atividades, é importante saber que elas podem acontecer tanto no cliente quanto no servidor. Sendo assim, é importante que as atividades entre cliente e servidor também estejam relacionadas para conseguirmos mesclá-las e, conseqüentemente, termos uma visualização completa do processo. Para que isso seja possível, há uma técnica chamada propagação de atividade. Quando esse recurso é habilitado, uma espécie de ID é gerado e enviado no header da mensagem, justamente para correlacionar as atividades através das aplicações. Como vimos no exemplo acima, para habilitarmos a propagação, definimos como True o atributo propagateActivity do elemento source.

Service Trace Viewer Tool (SvcTraceViewer.exe)

Este utilitário nos ajuda a analisar e dignosticar os traces que são gerados pelos serviços WCF disponibilizando, de uma forma bastante simples e intuitiva, a visualização de todo o processo da requisição, dividida em várias atividades. Além disso, ele permite selecionarmos vários arquivos, o que permite escolhermos o trace gerado pelo cliente e servidor, e a própria ferramenta mescla as informações dos arquivos, apresentando-os da forma que elas realmente acontecem.

É importante dizer que essa ferramenta não é disponibilizada apenas com a instalação do .NET Framework 3.0. Para poder obtê-la, é necessário que você faça o download e instale o Microsoft SDK for .NET Framework 3.0, que pode ser encontrado neste endereço.

Figura 1 - Utilizando o utilitário SvcTraceViewer.exe para analisar um tracing gerado pelo cliente e servidor.

Se analisarmos a figura acima, podemos reparar que eu optei por mostrar de forma gráfica todo o processo. Logo na parte superior do gráfico é possível visualizar os processos (cliente e servidor) que fizeram parte da requisição para o serviço. Neste mesmo gráfico ainda é possível analisarmos exatamente o momento da criação do proxy, do host e, o principal, do momento onde a exceção ocorre, que é onde o cursor está posicionado. Ainda a respeito do gráfico, cada um dos ícones que ali consta representa uma determinada ação e, para maiores detalhes sobre cada um deles, consulte este documento.

Esse utilitário permite a criação de projetos (*.stvproj) de forma que podemos agrupar todos os traces relacionados a alguma aplicação/serviço. Além das várias funcionalidades fornecidas por este utilitário, há uma outra que merece uma atenção, que é o Step Forward (F10) ou Step Backward (F9). O primeiro permite você avançar para o próximo trace e o segundo permite voltar para o trace anterior. É bem semelhante ao Step Into e Step Over do debugger do Visual Studio .NET.

Conclusão: Que o trace é essencial em qualquer tipo de aplicação, isso já não é novidade. Felizmente, como pudemos notar neste artigo, o WCF sabe dessa importância e já incorporou em sua infraestrutura todo o procedimento necessário para gerar os logs e disponibilizar para uma posterior análise. Além disso, a utilização da ferramenta Service Trace Viewer torna a compreensão do processo como um todo muito mais legível e fácil de encontrar uma possível falha.
Israel Aéce

Israel Aéce - Especialista em tecnologias de desenvolvimento Microsoft, atua como desenvolvedor de aplicações para o mercado financeiro utilizando a plataforma .NET. Como instrutor Microsoft, leciona sobre o desenvolvimento de aplicações .NET. É palestrante em diversos eventos Microsoft no Brasil e autor de diversos artigos que podem ser lidos a partir de seu site http://www.israelaece.com/. Possui as seguintes credenciais: MVP (Connected System Developer), MCP, MCAD, MCTS (Web, Windows, Distributed, ASP.NET 3.5, ADO.NET 3.5, Windows Forms 3.5 e WCF), MCPD (Web, Windows, Enterprise, ASP.NET 3.5 e Windows 3.5) e MCT.