{"id":1338,"date":"2017-08-08T11:17:11","date_gmt":"2017-08-08T14:17:11","guid":{"rendered":"http:\/\/gianfratti.com\/?p=1338"},"modified":"2017-08-10T15:21:35","modified_gmt":"2017-08-10T18:21:35","slug":"tracing-em-servicos-wcf","status":"publish","type":"post","link":"http:\/\/gianfratti.com\/index.php\/tracing-em-servicos-wcf\/","title":{"rendered":"Tracing em servi\u00e7os WCF"},"content":{"rendered":"<p><span class=\"artigo\">Toda e qualquer tipo de aplica\u00e7\u00e3o sempre exige uma forma de armazenar poss\u00edveis erros que possam acontecer durante a sua execu\u00e7\u00e3o. Isso ir\u00e1 ajudar imensamente para diagnosticarmos problemas que ocorrem e, conseq\u00fcentemente, facilitar na sua solu\u00e7\u00e3o. Isso n\u00e3o \u00e9 diferente em servi\u00e7os WCF. Esse artigo tem a finalidade de demonstrar a integra\u00e7\u00e3o que os servi\u00e7os WCF possibilitam para a captura e persist\u00eancia dos erros para uma posterior an\u00e1lise.<br \/>\n<!--more--><\/span><\/p>\n<p>Felizmente, o WCF j\u00e1 t\u00eam embutido em sua infraestrutura uma integra\u00e7\u00e3o muito forte com o namespace <i>System.Diagnostics<\/i> que, por sua vez, fornece toda a parte de monitoramento da &#8220;sa\u00fade&#8221; das aplica\u00e7\u00f5es constru\u00eddas sob a plataforma .NET. O monitoramento n\u00e3o est\u00e1 habilitado por padr\u00e3o e, para isso, basta configurarmos algumas informa\u00e7\u00f5es necess\u00e1rias para o funcionamento do mesmo dentro do arquivo <i>*.config<\/i>.<\/p>\n<p>\u00c9 bom informar que, como pr\u00e9-requisito para este artigo, voc\u00ea precisa conhecer as principais funcionalidades que s\u00e3o disponibilizadas pelo <i>System.Diagnostics<\/i>. O WCF j\u00e1 define alguns <i>trace sources<\/i> que voc\u00ea pode estar utilizando para efetuar os <i>logs<\/i>. Entre os <i>trace sources<\/i> dispon\u00edveis temos um chamado <i>System.ServiceModel<\/i>. Este <i>trace source<\/i> loga todos os est\u00e1gios de um processamento de um servi\u00e7o WCF, que vai desde a cria\u00e7\u00e3o do mesmo, passando pela autentica\u00e7\u00e3o e transporte da mensagem, at\u00e9 o retorno do m\u00e9todo. O c\u00f3digo abaixo trata-se de um trecho do arquivo <i>App.Config<\/i>, que foi extra\u00eddo de uma aplica\u00e7\u00e3o que consome o servi\u00e7o WCF:<\/p>\n<p><!--more--><!--more--><!--more--><\/p>\n<table width=\"100%\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"code\" colspan=\"4\">\n<pre id=\"code_ctl1\">&lt;system.diagnostics&gt;\r\n  &lt;sources&gt;\r\n    &lt;source\r\n      name=\"System.ServiceModel\"\r\n      switchValue=\"All\"\r\n      propagateActivity=\"true\"&gt;\r\n      &lt;listeners&gt;\r\n        &lt;add\r\n            name=\"TraceInXml\"\r\n            type=\"System.Diagnostics.XmlWriterTraceListener\"\r\n            initializeData=\"C:\\AppLog.svclog\" \/&gt;\r\n      &lt;\/listeners&gt;\r\n    &lt;\/source&gt;\r\n  &lt;\/sources&gt;\r\n  &lt;trace autoflush=\"true\" \/&gt;\r\n&lt;\/system.diagnostics&gt;<\/pre>\n<\/td>\n<\/tr>\n<tr>\n<td id=\"tab_ctl1\" class=\"backtab\"><b>App.Config<\/b><\/td>\n<td class=\"space\"><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span class=\"artigo\"><br \/>\nAnalisando o trecho de c\u00f3digo acima, especificamos o <i>source<\/i> como sendo <i>System.ServiceModel<\/i> para ser capaz de capturar todos os est\u00e1gios do processamento do WCF. O elemento <i>source<\/i> possui dois outros atributos, chamados: <i>switchValue<\/i> e <i>propagateActivity<\/i>. O primeiro deles, <i>switchValue<\/i>, recebe uma combina\u00e7\u00e3o de valores (separados por v\u00edrgula) que especifica quais ser\u00e3o os tipos de informa\u00e7\u00f5es que ser\u00e3o capturadas, ou seja, uma esp\u00e9cie de filtro. Como h\u00e1 v\u00e1rias possibilidades, a tabela abaixo descreve cada uma delas:<\/span><\/p>\n<p>&nbsp;<\/p>\n<table width=\"100%\" cellpadding=\"0\" align=\"center\" bgcolor=\"#cccccc\">\n<tbody>\n<tr>\n<td>\n<table width=\"100%\" cellspacing=\"2\" cellpadding=\"3\" align=\"center\" bgcolor=\"#efefef\">\n<tbody>\n<tr>\n<td width=\"20%\"><span style=\"font-family: arial; font-size: small;\"><b>N\u00edvel<\/b><\/span><\/td>\n<td><span style=\"font-family: arial; font-size: small;\"><b>Descri\u00e7\u00e3o<\/b><\/span><\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" bgcolor=\"#ffffff\"><span style=\"font-family: arial; font-size: small;\">Off<\/span><\/td>\n<td valign=\"top\" bgcolor=\"#ffffff\">\n<p align=\"justify\"><span style=\"font-family: arial; font-size: small;\">Nenhum tipo de informa\u00e7\u00e3o \u00e9 capturada.<\/span><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" bgcolor=\"#ffffff\"><span style=\"font-family: arial; font-size: small;\">Critical<\/span><\/td>\n<td valign=\"top\" bgcolor=\"#ffffff\">\n<p align=\"justify\"><span style=\"font-family: arial; font-size: small;\">Somente eventos considerados &#8220;negativos&#8221; s\u00e3o capturados, ou seja, eventos que indicam um processamento inesperado ou um erro condicional. Neste cen\u00e1rio, algumas exce\u00e7\u00f5es n\u00e3o tratadas s\u00e3o capturadas e devidamente logadas. Entre essas exce\u00e7\u00f5es temos: <i>OutOfMemoryException<\/i>, <i>ThreadAbortException<\/i>, <i>StackOverflowException<\/i>, entre algumas outras.<\/span><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" bgcolor=\"#ffffff\"><span style=\"font-family: arial; font-size: small;\">Error<\/span><\/td>\n<td valign=\"top\" bgcolor=\"#ffffff\">\n<p align=\"justify\"><span style=\"font-family: arial; font-size: small;\">Somente eventos considerados &#8220;negativos&#8221; s\u00e3o capturados, ou seja, eventos que indicam um processamento inesperado ou um erro condicional. Neste cen\u00e1rio, todo e qualquer tipo de exce\u00e7\u00e3o n\u00e3o tratada \u00e9 capturada e devidamente logada.<\/span><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" bgcolor=\"#ffffff\"><span style=\"font-family: arial; font-size: small;\">Warning<\/span><\/td>\n<td valign=\"top\" bgcolor=\"#ffffff\">\n<p align=\"justify\"><span style=\"font-family: arial; font-size: small;\">Somente eventos considerados &#8220;negativos&#8221; s\u00e3o capturados, ou seja, eventos que indicam um processamento inesperado ou um erro condicional. Refere-se a problemas que acontecem na sua aplica\u00e7\u00e3o, mas ela \u00e9 capaz de continuar trabalhando.<\/span><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" bgcolor=\"#ffffff\"><span style=\"font-family: arial; font-size: small;\">Information<\/span><\/td>\n<td valign=\"top\" bgcolor=\"#ffffff\">\n<p align=\"justify\"><span style=\"font-family: arial; font-size: small;\">Somente eventos considerados &#8220;positivos&#8221; s\u00e3o capturados, ou seja, eventos que indicam o sucesso de uma determinada tarefa.<\/span><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" bgcolor=\"#ffffff\"><span style=\"font-family: arial; font-size: small;\">Verbose<\/span><\/td>\n<td valign=\"top\" bgcolor=\"#ffffff\">\n<p align=\"justify\"><span style=\"font-family: arial; font-size: small;\">Somente eventos considerados &#8220;positivos&#8221; s\u00e3o capturados, mas com a diferen\u00e7a em rela\u00e7\u00e3o ao <i>Information<\/i>, de que estes eventos s\u00e3o considerados de &#8220;baixo n\u00edvel&#8221;, \u00fateis em procedimento de <i>debugging<\/i> ou otimiza\u00e7\u00e3o.<\/span><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" bgcolor=\"#ffffff\"><span style=\"font-family: arial; font-size: small;\">ActivityTracing<\/span><\/td>\n<td valign=\"top\" bgcolor=\"#ffffff\">\n<p align=\"justify\"><span style=\"font-family: arial; font-size: small;\">Permite capturar eventos que est\u00e3o contidos dentro uma determinada atividade. As atividades s\u00e3o abordadas de forma mais detalhada logo abaixo.<\/span><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" bgcolor=\"#ffffff\"><span style=\"font-family: arial; font-size: small;\">All<\/span><\/td>\n<td valign=\"top\" bgcolor=\"#ffffff\">\n<p align=\"justify\"><span style=\"font-family: arial; font-size: small;\">Todo e qualquer tipo de evento (que vimos acima) s\u00e3o capturados e devidamente logados.<\/span><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p align=\"justify\"><b>Observa\u00e7\u00e3o:<\/b> Atente-se aos tipos de evento (filtro) que se aplica ao <i>tracing<\/i>. Utilize isso com uma restri\u00e7\u00e3o muito grande, definindo somente o que voc\u00ea precisa realmente capturar em sua aplica\u00e7\u00e3o\/servi\u00e7o. Dependendo, voc\u00ea pode estar for\u00e7ando o <i>runtime<\/i> a salvar informa\u00e7\u00f5es desnecess\u00e1rias, comprometendo a performance da aplica\u00e7\u00e3o.<\/p>\n<p>O segundo atributo \u00e9 o <i>propagateActivity<\/i>. Ele \u00e9 utilizado quando o atributo <i>switchValue<\/i> estiver definido como <i>ActivityTracing<\/i>, e recebe um valor booleano indicando se a atividade deve ou n\u00e3o ser propagada para os <i>endpoints<\/i> que participam do processo. Veremos mais detalhes sobre atividades e propaga\u00e7\u00f5es a seguir. E, finalmente, depois do <i>source<\/i> configurado, devemos definir um <i>listener<\/i> (ou v\u00e1rios) que ser\u00e1 respons\u00e1vel por persistir as informa\u00e7\u00f5es em formato XML (quando utilizar o <i>XmlWriterTraceListener<\/i>) mas, como o WCF se utiliza dos <i>listeners<\/i> contidos dentro do <i>namespace System.Diagnostics<\/i>, nada impede de utilizar o <i>TextWriterTraceListener<\/i> e gerar o <i>output<\/i> em formato texto.<\/p>\n<p><b>Atividades<\/b><\/p>\n<p>As atividades s\u00e3o unidades de processamento que nos ajudam no processo de identifica\u00e7\u00e3o de uma poss\u00edvel falha. Essas atividades agrupam todos os <i>traces<\/i> para cada unidade de processamento, facilitando o rastreamento de poss\u00edveis falhas que possam vir a ocorrer durante a execu\u00e7\u00e3o de um determinado servi\u00e7o WCF. As atividades est\u00e3o sempre relacionadas e com o aux\u00edlio de uma ferramenta chamada <i>Service Trace Viewer<\/i> (mais abaixo falaremos sobre ela) poderemos visualizar o processo de forma gr\u00e1fica.<\/p>\n<p>Quando falamos de atividades, \u00e9 importante saber que elas podem acontecer tanto no cliente quanto no servidor. Sendo assim, \u00e9 importante que as atividades entre cliente e servidor tamb\u00e9m estejam relacionadas para conseguirmos mescl\u00e1-las e, conseq\u00fcentemente, termos uma visualiza\u00e7\u00e3o completa do processo. Para que isso seja poss\u00edvel, h\u00e1 uma t\u00e9cnica chamada <i>propaga\u00e7\u00e3o de atividade<\/i>. Quando esse recurso \u00e9 habilitado, uma esp\u00e9cie de ID \u00e9 gerado e enviado no <i>header<\/i> da mensagem, justamente para correlacionar as atividades atrav\u00e9s das aplica\u00e7\u00f5es. Como vimos no exemplo acima, para habilitarmos a propaga\u00e7\u00e3o, definimos como <i>True<\/i> o atributo <i>propagateActivity<\/i> do elemento <i>source<\/i>.<\/p>\n<p><b>Service Trace Viewer Tool (SvcTraceViewer.exe)<\/b><\/p>\n<p>Este utilit\u00e1rio nos ajuda a analisar e dignosticar os <i>traces<\/i> que s\u00e3o gerados pelos servi\u00e7os WCF disponibilizando, de uma forma bastante simples e intuitiva, a visualiza\u00e7\u00e3o de todo o processo da requisi\u00e7\u00e3o, dividida em v\u00e1rias atividades. Al\u00e9m disso, ele permite selecionarmos v\u00e1rios arquivos, o que permite escolhermos o <i>trace<\/i> gerado pelo cliente e servidor, e a pr\u00f3pria ferramenta mescla as informa\u00e7\u00f5es dos arquivos, apresentando-os da forma que elas realmente acontecem.<\/p>\n<p>\u00c9 importante dizer que essa ferramenta n\u00e3o \u00e9 disponibilizada apenas com a instala\u00e7\u00e3o do .NET Framework 3.0. Para poder obt\u00ea-la, \u00e9 necess\u00e1rio que voc\u00ea fa\u00e7a o download e instale o <i>Microsoft SDK for .NET Framework 3.0<\/i>, que pode ser encontrado <a href=\"http:\/\/www.microsoft.com\/downloads\/details.aspx?familyid=117ecfd3-98ad-4d67-87d2-e95a8407fa86&amp;displaylang=en\" target=\"_blank\" rel=\"noopener\">neste endere\u00e7o<\/a>.<\/p>\n<table width=\"100%\" align=\"center\">\n<tbody>\n<tr>\n<td align=\"center\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-1339 size-full aligncenter\" src=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/WCFtracing.png\" alt=\"\" width=\"538\" height=\"361\" srcset=\"http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/WCFtracing.png 538w, http:\/\/gianfratti.com\/wp-content\/uploads\/2017\/08\/WCFtracing-300x201.png 300w\" sizes=\"auto, (max-width: 538px) 100vw, 538px\" \/><\/td>\n<\/tr>\n<tr>\n<td align=\"center\"><span style=\"font-family: verdana; font-size: xx-small;\"><b>Figura 1<\/b> &#8211; Utilizando o utilit\u00e1rio <i>SvcTraceViewer.exe<\/i> para analisar um <i>tracing<\/i> gerado pelo cliente e servidor.<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span id=\"ContentPlaceHolder1_lblTexto\" class=\"artigo\"><br \/>\nSe analisarmos a figura acima, podemos reparar que eu optei por mostrar de forma gr\u00e1fica todo o processo. Logo na parte superior do gr\u00e1fico \u00e9 poss\u00edvel visualizar os processos (cliente e servidor) que fizeram parte da requisi\u00e7\u00e3o para o servi\u00e7o. Neste mesmo gr\u00e1fico ainda \u00e9 poss\u00edvel analisarmos exatamente o momento da cria\u00e7\u00e3o do <i>proxy<\/i>, do <i>host<\/i> e, o principal, do momento onde a exce\u00e7\u00e3o ocorre, que \u00e9 onde o cursor est\u00e1 posicionado. Ainda a respeito do gr\u00e1fico, cada um dos \u00edcones que ali consta representa uma determinada a\u00e7\u00e3o e, para maiores detalhes sobre cada um deles, <a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/ms732023.aspx\" target=\"_blank\" rel=\"noopener\">consulte este documento<\/a>.<\/span><\/p>\n<p>Esse utilit\u00e1rio permite a cria\u00e7\u00e3o de projetos (<i>*.stvproj<\/i>) de forma que podemos agrupar todos os <i>traces<\/i> relacionados a alguma aplica\u00e7\u00e3o\/servi\u00e7o. Al\u00e9m das v\u00e1rias funcionalidades fornecidas por este utilit\u00e1rio, h\u00e1 uma outra que merece uma aten\u00e7\u00e3o, que \u00e9 o <i>Step Forward<\/i> (F10) ou <i>Step Backward<\/i> (F9). O primeiro permite voc\u00ea avan\u00e7ar para o pr\u00f3ximo <i>trace<\/i> e o segundo permite voltar para o <i>trace<\/i> anterior. \u00c9 bem semelhante ao <i>Step Into<\/i> e <i>Step Over<\/i> do <i>debugger<\/i> do Visual Studio .NET.<\/p>\n<p><b>Conclus\u00e3o: <\/b>Que o <i>trace<\/i> \u00e9 essencial em qualquer tipo de aplica\u00e7\u00e3o, isso j\u00e1 n\u00e3o \u00e9 novidade. Felizmente, como pudemos notar neste artigo, o WCF sabe dessa import\u00e2ncia e j\u00e1 incorporou em sua infraestrutura todo o procedimento necess\u00e1rio para gerar os <i>logs<\/i> e disponibilizar para uma posterior an\u00e1lise. Al\u00e9m disso, a utiliza\u00e7\u00e3o da ferramenta <i>Service Trace Viewer<\/i> torna a compreens\u00e3o do processo como um todo muito mais leg\u00edvel e f\u00e1cil de encontrar uma poss\u00edvel falha.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Toda e qualquer tipo de aplica\u00e7\u00e3o sempre exige uma forma de armazenar poss\u00edveis erros que possam acontecer durante a sua execu\u00e7\u00e3o. Isso ir\u00e1 ajudar imensamente para diagnosticarmos problemas que ocorrem e, conseq\u00fcentemente, facilitar na sua solu\u00e7\u00e3o. Isso n\u00e3o \u00e9 diferente em servi\u00e7os WCF. Esse artigo tem a finalidade de demonstrar a integra\u00e7\u00e3o que os servi\u00e7os <span class=\"ellipsis\">&hellip;<\/span> <span class=\"more-link-wrap\"><a href=\"http:\/\/gianfratti.com\/index.php\/tracing-em-servicos-wcf\/\" class=\"more-link\"><span>Read More &rarr;<\/span><\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[201,200],"tags":[],"class_list":["post-1338","post","type-post","status-publish","format-standard","hentry","category-net","category-troubleshooting"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"http:\/\/gianfratti.com\/index.php\/wp-json\/wp\/v2\/posts\/1338","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/gianfratti.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/gianfratti.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/gianfratti.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/gianfratti.com\/index.php\/wp-json\/wp\/v2\/comments?post=1338"}],"version-history":[{"count":1,"href":"http:\/\/gianfratti.com\/index.php\/wp-json\/wp\/v2\/posts\/1338\/revisions"}],"predecessor-version":[{"id":1340,"href":"http:\/\/gianfratti.com\/index.php\/wp-json\/wp\/v2\/posts\/1338\/revisions\/1340"}],"wp:attachment":[{"href":"http:\/\/gianfratti.com\/index.php\/wp-json\/wp\/v2\/media?parent=1338"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/gianfratti.com\/index.php\/wp-json\/wp\/v2\/categories?post=1338"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/gianfratti.com\/index.php\/wp-json\/wp\/v2\/tags?post=1338"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}