Filtros para MessageLogging

Já mostrei neste artigo e vídeo como podemos fazer para habilitar o log de mensagens do WCF, onde podemos capturar o envelope da mensagem SOAP que está sendo trafegado entre as partes envolvidas.

Somente o fato de habilitar já é o suficiente para capturar todas as mensagens que chegam ao serviço e também aquelas que são devolvidas para os respectivos clientes, contendo o resultado do processamento da operação. Dependendo do tamanho do envelope e do volume de requisições, em pouco tempo, você pode consumir uma grande quantidade de espaço em disco.

Para melhorar isso, o message logging do WCF fornece filtros que podemos aplicar aos headers do envelope SOAP, e com isso, analisar e decidir se queremos ou não catalogar aquela mensagem. Para exemplificar, considere o contrato abaixo, que possui duas operações simples:

[ServiceContract(Namespace = “http://www.israelaece.com/servicos“)]
public interface IContrato
{
    [OperationContract]
    ItemDeExtrato[] VisualizarExtrato(string conta);

    [OperationContract]
    void Debitar(string conta, decimal valor);
}

A operação VisualizarExtrato retorna um array de itens que fazem parte de um extrato de uma determinada conta, informada através do parâmetro conta. Já a segunda operação, recebe a conta e o valor a ser debitado da mesma. Como sabemos, podemos ligar o logging do WCF para começarmos a capturar as mensagens que chegam para este serviço como um todo. O código abaixo ilustra essa configuração:

<?xml version=”1.0″ encoding=”utf-8″ ?>
<configuration>
  <system.diagnostics>
    <sources>
      <source name=”System.ServiceModel.MessageLogging”
              switchValue=”All”
              propagateActivity=”true”>
        <listeners>
          <add name=”Xml”
               type=”System.Diagnostics.XmlWriterTraceListener”
               initializeData=”C:TempMessageLogging.svclog” />
        </listeners>
      </source>
    </sources>
    <trace autoflush=”true” />
  </system.diagnostics>
  <system.serviceModel>
    <diagnostics>
      <messageLogging logEntireMessage=”true”
                      logMessagesAtServiceLevel=”true”
                      maxMessagesToLog=”100″
                      maxSizeOfMessageToLog=”200000″ />
    </diagnostics>
  </system.serviceModel>
</configuration>

Com isso, ao abrir o arquivo gerado pelo logging recém habilitado, veremos a mensagem que chegou para o serviço com a requisição de débito:

<s:Envelope xmlns:a=”http://www.w3.org/2005/08/addressing&#8221;
            xmlns:s=”http://www.w3.org/2003/05/soap-envelope”&gt;
  <s:Header>
    <Action a:mustUnderstand=”1″
            xmlns=”http://www.w3.org/2005/08/addressing&#8221;
            xmlns:a=”http://www.w3.org/2003/05/soap-envelope”&gt;http://www.israelaece.com/servicos/IContrato/Debitar</Action>
    <a:MessageID>urn:uuid:25eb06f3-b1d5-41a4-99c8-37f1a5905d7f</a:MessageID>
    <a:ReplyTo>
      <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address&gt;
    </a:ReplyTo>
    <a:To s:mustUnderstand=”1″>net.tcp://localhost:9392/srv</a:To>
  </s:Header>
  <s:Body>
    <Debitar xmlns=”http://www.israelaece.com/servicos”&gt;
      <conta>000001</conta>
      <valor>1200</valor>
    </Debitar>
  </s:Body>
</s:Envelope>

Mas o problema é que também as mensagens que chegam para a operação VisualizarExtrato também serão catalogadas, e como elas possuem uma grande quantidade de informações, neste caso, não temos a necessidade de monitorar essas mensagens. É aqui que entra em cena os filtros, tema deste artigo. Dentro do elemento messageLogging temos um sub-elemento chamado de filters, que nada mais é que uma coleção, onde você pode elencar diversos filtros, utilizando a linguagem/tecnologia XPath para analisar e escrever tais filtros. Exemplo:

<system.serviceModel>
  <diagnostics performanceCounters=”All”>
    <messageLogging logEntireMessage=”true”
                    logMessagesAtServiceLevel=”true”
                    logMessagesAtTransportLevel=”false”
                    maxMessagesToLog=”100″
                    maxSizeOfMessageToLog=”200000″>
      <filters>
        <add xmlns:a=”http://www.w3.org/2005/08/addressing&#8221;
             xmlns:s=”http://www.w3.org/2003/05/soap-envelope”>/s:Envelope/s:Header/a:Action%5Btext()=&#8221;http://www.israelaece.com/servicos/IContrato/Debitar“]</add>
      </filters>
    </messageLogging>
  </diagnostics>
</system.serviceModel>

Modificando o arquivo de configuração do serviço, estamos acrescentando um filtro que utilizaremos para catalogar as mensagens somente se a Action (que representa a operação) for igual a Debitar, descartando assim todas as mensagens que chegam para as outras operações e, consequentemente, eventuais dados gerados por elas.