TraceTarget – Usando a API de Log do Flex

Neste post vou explicar como usar a API de Log para mostrar os logs de execução da aplicação e também como usar o componente TraceTarget, que é muito útil para poder recuperar as informações das chamadas para o servidor, facilitando a resolução de problemas.

No Flex temos duas opções para recuperar informações ou logs de execução de uma aplicação. Uma primeira maneira e a mais utilizada, é usar a função global trace(”) para mostrar informações no console do FlashBuilder. Essa abordagem sempre requer que a aplicação esteja sendo executada em modo de debug, o que exige a instalação de um FlashPlayer versão de debug. Lógico que para o ambiente de desenvolvimento isso não é um problema, já que a instalação do FlashBuilder já inclui a versão correta do FlashPlayer versão debug. Mais e quando a aplicação está em produção, ou seja, quando não contamos com a versão de debug do FlashPlayer? Ai que entra a segunda opção.Na segunda opção vamos usar a API de Logging do Flex, que vai nos permitir delegar para uma classe a função de logar informações, seja usando o trace(”), primeira abordagem, ou até mesmo customizando a forma de apresentação. Esta abordagem também nos permite controlar o que é exibido, utilizado categorias e nível de log.

A API de Logging do Flex é muito simples de ser usada. Toda vez que queremos usa-la, estaremos envolvendo duas partes:

  1. O Logger, que possui os meios para enviar informações em diversos níveis (all, debug, info, warn, error e fatal) em uma determinada categoria para o Log Target. O Logger sempre irá implementar a interface ILogger, iremos utilizar a classe mx.logging.LogLogger, que já vem no SDK;
  2. O Log Traget, que será responsável por registrar a informação usando o trace(”) ou outra implementação. Iremos utilizar a classe mx.logging.targets.TraceTarget.

Para ficar mais fácil de entender como usar a API, vamos imaginar que queremos logar quando a aplicação é pré-inicializado, inicializado e criado.Inicialmente iremos usar a função global trace(”) e depois usar as classes de Log.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:mx="library://ns.adobe.com/flex/mx"
               preinitialize="application_preinitializeHandler(event)"
               initialize="application_initializeHandler(event)"
               creationComplete="application_creationCompleteHandler(event)">
    <fx:Script>
        <![CDATA[
            import mx.events.FlexEvent;

            protected function application_preinitializeHandler(event:FlexEvent):void
            {
                trace('A Aplicação foi pré inicializada');
            }


            protected function application_initializeHandler(event:FlexEvent):void
            {
                trace('A Aplicação foi inicializada');
            }


            protected function application_creationCompleteHandler(event:FlexEvent):void
            {
                trace('A Aplicação foi criada');
            }

        ]]>
    </fx:Script>
</s:Application>



Debugando a aplicação teremos no Console:

1
2
3
A Aplicação foi pré inicializada
A Aplicação foi inicializada
A Aplicação foi criada



Agora vamos ver como ficaria se usarmos a API:

  1. A primeira coisa que devemos fazer é criar um Logger. Para fazer isso devemos utilizar o método estático getLogger da classe mx.Logging.Log, fornecendo a categoriado log. A categoria é usada para poder filtrar o que será mostrado no Log Target e por padronização usamos o nome completo da classe. Neste exemplo a aplicação está no pacote default, porém para exemplificar vou usar a categoria br.com.dclick.LogginExample.

    1
    private var log:ILogger = Log.getLogger("br.com.dclick.LogginExample");


  2. Agora é só usar os métodos de log da interface ILogger:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    {
        log.info('A Aplicação foi pré inicializada');
    }
    protected function application_initializeHandler(event:FlexEvent):void
    {
        log.warn('A Aplicação foi inicializada');
    }
    protected function application_creationCompleteHandler(event:FlexEvent):void
    {
        log.log(LogEventLevel.INFO, 'A Aplicação foi criada');
    }



    Perceba a utilização dos métodos info(), warn() e log() para registrar as informações. É possível usar tokens no log para serem trocados
    por informações. Todos os tokens devem ser representados por {} como por exemplo, {0}, {1} e etc…

    1
    2
    3
    {
        log.info('A Aplicação foi pré inicializada em: {0}', [new Date().toDateString()]);
    }



    Se debugarmos a aplicação após a implementação, podemos ver que nada é apresentado no console. Isso acontece por que ainda não informamos qual será o Log Target.

  3. Agora vamos informar quem será o responsável por logar as informações, ou seja, vamos criar o Log Target.

    Vale lembrar que só é necessário declara-lo uma vez só na aplicação inteira. Ainda podemos customizar este target como por exemplo definir quais os levels que quero mostrar e se quero apresentar informações adicionais. Antes de mais nada, se debugarmos a aplicação teremos:

    1
    2
    3
    A Aplicação foi pré inicializada em: Sat Mar 5 2011
    A Aplicação foi inicializada
    A Aplicação foi criada


  4. Customizando o TraceTarget:
    1
    <s:TraceTarget includeCategory="true" includeDate="true" includeLevel="true" includeTime="true" level="{LogEventLevel.INFO}" />



    Resultando em:

    1
    2
    3
    3/5/2011 21:27:41.840 [INFO] br.com.dclick.LogginExample A Aplicação foi pré inicializada em: Sat Mar 5 2011
    3/5/2011 21:27:41.870 [WARN] br.com.dclick.LogginExample A Aplicação foi inicializada
    3/5/2011 21:27:42.013 [INFO] br.com.dclick.LogginExample A Aplicação foi criada


  5. Se prestarmos atenção no último exemplo, definimos que o level seria info, mais então porque o level warn foi logado? A API nos permite selecionar os níveis ALL –&gt DEBUG –> INFO –> WARN –> ERROR –> FATAL. Então se selecionarmos o nível INFO, tudo o que for INFO e menos abrangente será logado. Se selecionarmos o nível ERROR, somente logs com o nível ERROR e FATAL serão apresentados.
    Para exemplificar a utilização das categorias, vamos criar um componente adicional:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    <?xml version="1.0" encoding="utf-8"?>
    <s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
             xmlns:s="library://ns.adobe.com/flex/spark"
             xmlns:mx="library://ns.adobe.com/flex/mx"
             preinitialize="group1_preinitializeHandler(event)" initialize="group1_initializeHandler(event)"
             creationComplete="group1_creationCompleteHandler(event)">
        <fx:Script>
            <![CDATA[
                import mx.events.FlexEvent;
                import mx.logging.ILogger;
                import mx.logging.Log;

                private var log:ILogger = Log.getLogger("br.com.dclick.components.MyComponent");
                protected function group1_preinitializeHandler(event:FlexEvent):void
                {
                    log.info("MyComponent preinitialized");
                }


                protected function group1_initializeHandler(event:FlexEvent):void
                {
                    log.info("MyComponent initialized");
                }


                protected function group1_creationCompleteHandler(event:FlexEvent):void
                {
                    log.info("MyComponent created");
                }

            ]]>
        </fx:Script>
        <fx:Declarations>
            <!-- Place non-visual elements (e.g., services, value objects) here -->
        </fx:Declarations>
    </s:Group>



    Vamos declarar o componente e debugar a aplicação.

    1
    <components:MyComponent />



    O resultado é:

    1
    2
    3
    4
    5
    6
    3/5/2011 21:38:56.878 [INFO] br.com.dclick.LogginExample A Aplicação foi pré inicializada em: Sat Mar 5 2011
    3/5/2011 21:38:56.909 [INFO] br.com.dclick.components.MyComponent MyComponent preinitialized
    3/5/2011 21:38:56.909 [INFO] br.com.dclick.components.MyComponent MyComponent initialized
    3/5/2011 21:38:56.910 [WARN] br.com.dclick.LogginExample A Aplicação foi inicializada
    3/5/2011 21:38:57.057 [INFO] br.com.dclick.components.MyComponent MyComponent created
    3/5/2011 21:38:57.057 [INFO] br.com.dclick.LogginExample A Aplicação foi criada



    Imagine que só queremos apresentar os logs com a categoria br.com.dclick.components.*

    1
    level="{LogEventLevel.INFO}" filters="['br.com.dclick.components.*']"/>;



    O Resultado é:

    1
    2
    3
    3/5/2011 21:59:44.240 [INFO] br.com.dclick.components.MyComponent MyComponent preinitialized
    3/5/2011 21:59:44.241 [INFO] br.com.dclick.components.MyComponent MyComponent initialized
    3/5/2011 21:59:44.387 [INFO] br.com.dclick.components.MyComponent MyComponent created



    Poderia querer imprimir os logs com a categoria br.com.dclick.components.MyComponent e br.com.dclick.LogginExample:

    1
    level="{LogEventLevel.INFO}" filters="['br.com.dclick.components.MyComponent', 'br.com.dclick.LogginExample']"/>;



    O Resultado é:

    1
    2
    3
    4
    5
    6
    3/5/2011 22:02:40.929 [INFO] br.com.dclick.LogginExample A Aplicação foi pré inicializada em: Sat Mar 5 2011
    3/5/2011 22:02:40.960 [INFO] br.com.dclick.components.MyComponent MyComponent preinitialized
    3/5/2011 22:02:40.960 [INFO] br.com.dclick.components.MyComponent MyComponent initialized
    3/5/2011 22:02:40.961 [WARN] br.com.dclick.LogginExample A Aplicação foi inicializada
    3/5/2011 22:02:41.105 [INFO] br.com.dclick.components.MyComponent MyComponent created
    3/5/2011 22:02:41.106 [INFO] br.com.dclick.LogginExample A Aplicação foi criada



    Moral da história, para poder filtrar os logs pela categoria, usamos a propriedade filter, que recebe uma lista de strings com as categorias permitidas. A API também permite a utilização do curinga *, e por padrão o filtro é igual a *, ou seja, imprime tudo.
    A última coisa que gostaria de mostrar é como usuar o TraceTarget para logar informações sobre as chamadas remotas. Irei utilizar como exemplo um HttpService consumindo o rss do Globo Esporte.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <?xml version="1.0" encoding="utf-8"?>
    <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
                   xmlns:s="library://ns.adobe.com/flex/spark"
                   xmlns:mx="library://ns.adobe.com/flex/mx"
                   creationComplete="application_creationCompleteHandler(event)">
        <fx:Script>
            <![CDATA[
                import mx.events.FlexEvent;
                protected function application_creationCompleteHandler(event:FlexEvent):void
                {
                    rss.send();
                }

            ]]>
        </fx:Script>

        <fx:Declarations>
            <s:TraceTarget />
            <s:HTTPService id="rss" url="http://globoesporte.globo.com/dynamo/rss2.xml" />
        </fx:Declarations>

    </s:Application>



    No console podemos ver a chamada feita e o resultado da chamada.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    '136ECED5-AD86-47EB-E77F-88EE4AA0EA34' producer set destination to 'DefaultHTTP'.
    'direct_http_channel' channel endpoint set to http:
    '136ECED5-AD86-47EB-E77F-88EE4AA0EA34' producer sending message 'E52C0A6D-882A-37F9-F4C9-88EE4B7DF0FC'
    'direct_http_channel' channel sending message:
    (mx.messaging.messages::HTTPRequestMessage)#0
      body = (Object)#1
      clientId = (null)
      contentType = "application/x-www-form-urlencoded"
      destination = "DefaultHTTP"
      headers = (Object)#2
      httpHeaders = (Object)#3
      messageId = "E52C0A6D-882A-37F9-F4C9-88EE4B7DF0FC"
      method = "GET"
      recordHeaders = false
      timestamp = 0
      timeToLive = 0
      url = "http://globoesporte.globo.com/dynamo/rss2.xml"
    '136ECED5-AD86-47EB-E77F-88EE4AA0EA34' producer connected.
    '136ECED5-AD86-47EB-E77F-88EE4AA0EA34' producer acknowledge of 'E52C0A6D-882A-37F9-F4C9-88EE4B7DF0FC'.
    Decoding HTTPService response
    Processing HTTPService response message:
    (mx.messaging.messages::AcknowledgeMessage)#0
      body = "<?xml version="1.0" encoding="utf-8"?>
    <rss>...</rss>"

      clientId = "DirectHTTPChannel0"
      correlationId = "E52C0A6D-882A-37F9-F4C9-88EE4B7DF0FC"
      destination = ""
      headers = (Object)#1
        DSStatusCode = 200
      messageId = "FDA3E270-BAD8-82AD-2770-88EE5BE5C3E8"
      timestamp = 0
      timeToLive = 0



    E isso é tudo o que você precisa para começar a utilizar a API, nos próximos posts irei ensinar como customizar a saída do log.


Nenhum comentário

Deixe Seu Comentário