Depuração

De DTI Wiki

Ir para: navegação, pesquisa

Para depuração de códigos PL/SQL NÃO use DBMS_OUTPUT, utilize as ferramentas do LOG4PLSQL instalado no esquema DLOG. Nenhum código que contenha instruções DBMS_OUTPUT será passado para a base de homologação (TEST) ou produção (SUN) mesmo que o código esteja comentado.


Tabela de conteúdo

LOG4PLSQL - Oracle Database Logging Tools

LOG4PLSQL is developed by the LOG4PLSQL project team, see http://log4plsql.sourceforge.net.

Destino dos logs

O destino padrão dos logs gerados pela ferramenta é a tabela TLOG (DLOG.TLOG), opcionalmente podem ser direcionados também para a saída padrão (DBMS_OUTPUT), porém isso só poderá ser feito na base de desenvolvimento (LNX).

Os registros podem ser consultados na tabela TLOG (DLOG.TLOG) ou na view VLOG (DLOG.VLOG) e ficarão armazenados por 7 dias.


Procedimentos

A ferramenta disponibiliza alguns procedimentos para depuração dependendo do tipo de mensagem.

Nas bases de desenvolvimento e homologação todas as mensagens serão gravadas, na base de produção somente serão gravadas as mensagens a partir de warnig.

Uso básico

Os procedimentos podem ser chamados sem passagem de parâmetros, neste caso a mensagem padrão será SQLCODE SQLERRM, como mostrado no exemplo abaixo.

    PROCEDURE prc_basico IS
    BEGIN
        dlog.plog.debug;
        dlog.plog.info;
        dlog.plog.warn;
        dlog.plog.error;
        dlog.plog.fatal;
    END prc_basico;


Neste caso o resultado é gravado na tabela TLOG. O resultado mostrado abaixo é uma consulta a view VLOG.

[Ago 12, 16:22:22:89][DEBUG][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][SQLCODE:0 SQLERRM:ORA-0000: normal, successful completion]
[Ago 12, 16:22:22:89][INFO][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][SQLCODE:0 SQLERRM:ORA-0000: normal, successful completion]
[Ago 12, 16:22:22:89][WARN][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][SQLCODE:0 SQLERRM:ORA-0000: normal, successful completion]
[Ago 12, 16:22:22:89][ERROR][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][SQLCODE:0 SQLERRM:ORA-0000: normal, successful completion]
[Ago 12, 16:22:22:89][FATAL][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][SQLCODE:0 SQLERRM:ORA-0000: normal, successful completion]


A mensagem pode ser passada por parâmetro, como mostrado abaixo.

    PROCEDURE prc_basico IS
    BEGIN
        dlog.plog.debug('Mensagem de depuração');
        dlog.plog.info('Mensagem de informação');
        dlog.plog.warn('Mensagem de atenção');
        dlog.plog.error('Mensagem de erro');
        dlog.plog.fatal('Mensagem de erro fatal');
    END prc_basico;


Desta forma o resultado obtido será como mostrado abaixo. Consulta a view VLOG.

[Ago 12, 16:22:22:89][DEBUG][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][Mensagem de depuração]
[Ago 12, 16:22:22:89][INFO][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][Mensagem de informação]
[Ago 12, 16:22:22:89][WARN][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][Mensagem de atenção]
[Ago 12, 16:22:22:89][ERROR][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][Mensagem de erro]
[Ago 12, 16:22:22:89][FATAL][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][Mensagem de erro fatal]

Assertings

O uso de assert pode ser útil para verificar os valores de variáveis ou parâmetros da aplicação. Os parâmetros para assert são:

A mensagem do assert só é gravada se a condição passada por parâemtro for falsa, veja exemplos abaixo.

    PROCEDURE prc_asserts(in_dtinicial IN DATE,
                          in_dtfinal   IN DATE,
                          in_coderro   IN NUMBER DEFAULT -20999,
                          in_raise     IN BOOLEAN DEFAULT FALSE) IS
    BEGIN
        dlog.plog.assert(in_dtinicial <= in_dtfinal);
        dlog.plog.assert(in_dtinicial <= in_dtfinal, 'Data inicial maior que data final');
        dlog.plog.assert(in_dtinicial <= in_dtfinal, 'Data inicial maior que data final', in_coderro, in_raise);
    END prc_asserts;
 
    -- Chamando o procedimento.
    BEGIN
        pkg_log4plsql.prc_asserts(SYSDATE, SYSDATE - 1, -20199);
    END;


Cada chamada a assert grava uma mensagem de erro de acordo com os parâmetros passados. Se for passado TRUE como quarto parâmetro será executado um RAISE_APPLICATION_ERROR com o código informado no terceiro parâmetro e a aplicação será abotrada.

Observe as mensagens abaixo (VLOG).

[Ago 15, 10:34:58:21][ALL][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][AAS-20000: assert condition error]
[Ago 15, 10:34:58:21][ALL][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][AAS-20000: Data inicial maior que data final]
[Ago 15, 10:34:58:21][ALL][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][AAS-20199: Data inicial maior que data final]

Usando variável de contexto

Os logs podem ser configurados por uma variável de contexto. Esta variável permite ao desenvolvedor alterar os valores default de configuração para uma seção, como por exemplo o nível de mensagens a gravar e o local de saída das mensagens.

Para utilizar vairáveis de contexto o desenvolvedor deve chamar o procedimento init() como nos exemplos abaixo.

Inicializando variável de contexto com valores padrão.

    PROCEDURE prc_contexto IS
 
        v_ctx dlog.plogparam.log_ctx := dlog.plog.init();    
 
    BEGIN
 
        dlog.plog.info('Usando variáveis de contexto');
        dlog.plog.debug(v_ctx, 'Mensagem de depuração com variável de contexto');
        dlog.plog.info(v_ctx, 'Mensagem de informação com variável de contexto');
        dlog.plog.warn(v_ctx, 'Mensagem de atenção com variável de contexto');
        dlog.plog.error(v_ctx, 'Mensagem de erro com variável de contexto');
        dlog.plog.fatal(v_ctx, 'Mensagem de erro fatal com variável de contexto');
 
    END prc_contexto;


Mensagens gravadas com inicialização padrão (VLOG).

[Ago 15, 16:11:02:49][INFO][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][Usando variáveis de contexto]
[Ago 15, 16:11:02:49][DEBUG][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][Mensagem de depuração com variável de contexto]
[Ago 15, 16:11:02:49][INFO][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][Mensagem de informação com variável de contexto]
[Ago 15, 16:11:02:49][WARN][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][Mensagem de atenção com variável de contexto]
[Ago 15, 16:11:02:49][ERROR][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][Mensagem de erro com variável de contexto]
[Ago 15, 16:11:02:49][FATAL][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][Mensagem de erro fatal com variável de contexto]


Inicializando variável de contexto com valores diferentes do padrão, onde foram alterados a seção, o nível e saída.

    PROCEDURE prc_contexto IS
 
        /* Valores default para as bases de desenvolvimento e homologação
        v_ctx dlog.plogparam.log_ctx := dlog.plog.init(psection           => NULL,             (Nome da seção)
                                                       plevel             => dlog.plog.ldebug, (Maior nível de depuração)
                                                       plog4j             => FALSE,            (Não instalado - Advanced Queue)
                                                       plogtable          => TRUE,             (Grava log na tabela de TLOG)
                                                       pout_trans         => TRUE,             (Transação autônoma)
                                                       palert             => FALSE,            (Não habilitado - alert.log)
                                                       ptrace             => FALSE,            (Não habilitado - trace file)
                                                       pdbms_output       => FALSE,            (Gera log na saída padrão DBMS_OUTPUT)
                                                       psession           => FALSE,            (Não habilitado - v$session)
                                                       pdbms_output_wrap  => 100);             (Comprimento da saída no DBMS_OUTPUT)
 
        Na base de produção a diferença está em plevel => dlog.plog.lwarn */
 
        v_ctx dlog.plogparam.log_ctx := dlog.plog.init(psection     => 'prc_contexto',
                                                       plevel       => LOG.plog.lwarn,
                                                       pdbms_output => TRUE);
 
    BEGIN
 
        dlog.plog.info('Usando variáveis de contexto');
        dlog.plog.debug(v_ctx, 'Mensagem de depuração com variável de contexto');
        dlog.plog.info(v_ctx, 'Mensagem de informação com variável de contexto');
        dlog.plog.warn(v_ctx, 'Mensagem de atenção com variável de contexto');
        dlog.plog.error(v_ctx, 'Mensagem de erro com variável de contexto');
        dlog.plog.fatal(v_ctx, 'Mensagem de erro fatal com variável de contexto');
 
    END prc_contexto;


Mensagens gravadas com inicialização diferente do padrão.

Observe que a chamada a INFO não utiliza a variável de contexto, por este motivo foi gravada na tabela de log mas não foi apresentada no DBMS_OUTPUT.

As chamadas com utilização da variável de contexto só foram geradas a partir do nível warining e foram apresentadas também na saída padrão DBMS_OUTPUT.

Mensagens gravadas na tabela de log (VLOG).

[Ago 15, 16:48:56:16][INFO][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][Usando variáveis de contexto]
[Ago 15, 16:48:56:16][WARN][ADDESENV][prc_contexto][Mensagem de atenção com variável de contexto]
[Ago 15, 16:48:56:20][ERROR][ADDESENV][prc_contexto][Mensagem de erro com variável de contexto]
[Ago 15, 16:48:56:20][FATAL][ADDESENV][prc_contexto][Mensagem de erro fatal com variável de contexto]

Saída no DBMS_OUTPUT.

16:48:56:16-WARN-prc_contexto Mensagem de atenção com variável de contexto
16:48:56:20-ERROR-prc_contexto Mensagem de erro com variável de contexto
16:48:56:20-FATAL-prc_contexto Mensagem de erro fatal com variável de contexto

Teste de nível de depuração

A melhor maneira de codificar as chamadas de depuração é fazendo um teste antes da chamada com a função isEnabled.

Esta forma de codificação será exigida quando a depuração for em cálculos, relatórios complexos ou processamentos com laços, pois os testes feitos antes da chamada ao procedimento de depuração diminuem consideravelmente o custo e o tempo de processamento.

    PROCEDURE prc_contexto IS
 
        v_ctx dlog.plogparam.log_ctx := dlog.plog.init(psection          => 'prc_contexto',
                                                       plevel            => LOG.plog.lwarn,
                                                       pdbms_output      => TRUE,
                                                       pdbms_output_wrap => 150);
 
 
    BEGIN
 
        dlog.plog.info('Usando variáveis de contexto com teste antes da chamada');
        IF dlog.plog.isdebugenabled(v_ctx) THEN
            dlog.plog.debug(v_ctx, 'Mensagem de depuração com variável de contexto');
        END IF;
        IF dlog.plog.isinfoenabled(v_ctx) THEN
            dlog.plog.info(v_ctx, 'Mensagem de informação com variável de contexto');
        END IF;
        IF dlog.plog.iswarnenabled(v_ctx) THEN
            dlog.plog.warn(v_ctx, 'Mensagem de atenção com variável de contexto');
        END IF;
        IF dlog.plog.iserrorenabled(v_ctx) THEN
            dlog.plog.error(v_ctx, 'Mensagem de erro com variável de contexto');
        END IF;
        IF dlog.plog.isfatalenabled(v_ctx) THEN
            dlog.plog.fatal(v_ctx, 'Mensagem de erro fatalcom variável de contexto');
        END IF;
 
    END prc_contexto;


Mensagens gravadas na tabela de log (VLOG).

[Ago 15, 16:48:56:16][INFO][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][Usando variáveis de contexto com teste antes da chamada]
[Ago 15, 16:48:56:16][WARN][ADDESENV][prc_contexto][Mensagem de atenção com variável de contexto]
[Ago 15, 16:48:56:20][ERROR][ADDESENV][prc_contexto][Mensagem de erro com variável de contexto]
[Ago 15, 16:48:56:20][FATAL][ADDESENV][prc_contexto][Mensagem de erro fatal com variável de contexto]

Saída no DBMS_OUTPUT.

16:48:56:16-WARN-prc_contexto Mensagem de atenção com variável de contexto
16:48:56:20-ERROR-prc_contexto Mensagem de erro com variável de contexto
16:48:56:20-FATAL-prc_contexto Mensagem de erro fatal com variável de contexto

Concatenando mensagem de erro

Também podem ser criadas mensagens concantenando os retornos de erro do banco de dados.

    PROCEDURE prc_getanomes(in_ano IN anomes.ano%TYPE,
                            in_mes IN anomes.mes%TYPE) IS
            v_ctx dlog.plogparam.log_ctx := dlog.plog.init(psection          => 'prc_contexto',
                                                           plevel            => dlog.plog.lwarn,
                                                           pdbms_output      => TRUE,
                                                           pdbms_output_wrap => 150);
            v_encctb anomes.enccontabil%TYPE;
    BEGIN
        SELECT am.enccontabil
        INTO   v_encctb
        FROM   anomes am
        WHERE  am.ano = in_ano
        AND    am.mes = in_mes;
    EXCEPTION
        WHEN NO_DATA_FOUND THEN
            dlog.plog.error(v_ctx,
                            'Ano informado não cadastrado. Esta mensagem tem mais de 150 caracteres e ' ||
                            'está concatenada com a mensagem de erro do banco de dados. ' || SQLERRM);
    END prc_getanomes;
 
    -- Chamando o procedimento
    BEGIN
        pkg_log4plsql.prc_getanomes(2011, 15);
    END;


Mensagens gravadas na tabela de log (VLOG).

[Ago 16, 10:29:46:24][ERROR][ADDESENV][prc_contexto][Ano informado não cadastrado. Esta mensagem tem mais de 150 caracteres e está concatenada com a mensagem de erro do banco de dados. ORA-01403: dados não encontrados]

Saída no DBMS_OUTPUT.

10:14:49:30-ERROR-prc_contexto   Ano informado não cadastrado. Esta mensagem tem mais de 150 caracteres e está concatenada com a mensagem de erro do ba
                                                    nco de dados. ORA-01403: dados não encontrados

Criando mensagens com hierarquia

É possível criar mensagens com hierarquia.


    PROCEDURE prc_hierarquia IS
            v_ctx dlog.plogparam.log_ctx := dlog.plog.init(psection => 'prc_hierarquia');
    BEGIN
        dlog.plog.debug(v_ctx, 'Usando log hierárquico');
 
        dlog.plog.debug(v_ctx, 'Seção: ' || dlog.plog.getsection(v_ctx));
 
        dlog.plog.setbeginsection(v_ctx, 'Nível 0');
        dlog.plog.debug(v_ctx, 'Mensagem 1');
 
        dlog.plog.setbeginsection(v_ctx, 'Nível 1');
        dlog.plog.debug(v_ctx, 'Mensagem 2');
 
        dlog.plog.setbeginsection(v_ctx, 'Nível 2');
        dlog.plog.debug(v_ctx, 'Mensagem 3');
        dlog.plog.debug(v_ctx, 'Mensagem 4');
 
        dlog.plog.setendsection(v_ctx, 'Nível 2');
        dlog.plog.debug(v_ctx, 'Mensagem 5');
 
        dlog.plog.setendsection(v_ctx);
 
        dlog.plog.debug(v_ctx, 'Mensagem 6');
    END prc_hierarquia;


Mensagens gravadas na tabela de log (VLOG).

[Ago 16, 10:35:58:02][DEBUG][ADDESENV][prc_hierarquia][Usando log hierárquico]
[Ago 16, 10:35:58:02][DEBUG][ADDESENV][prc_hierarquia][Seção: prc_hierarquia]
[Ago 16, 10:35:58:02][DEBUG][ADDESENV][prc_hierarquia.Nível 0][Mensagem 1]
[Ago 16, 10:35:58:02][DEBUG][ADDESENV][prc_hierarquia.Nível 0.Nível 1][Mensagem 2]
[Ago 16, 10:35:58:02][DEBUG][ADDESENV][prc_hierarquia.Nível 0.Nível 1.Nível 2][Mensagem 3]
[Ago 16, 10:35:58:02][DEBUG][ADDESENV][prc_hierarquia.Nível 0.Nível 1.Nível 2][Mensagem 4]
[Ago 16, 10:35:58:02][DEBUG][ADDESENV][prc_hierarquia.Nível 0.Nível 1][Mensagem 5]
[Ago 16, 10:35:58:02][DEBUG][ADDESENV][prc_hierarquia][Mensagem 6]

Backtrace

É possível gravar erros não tratados em procedimentos chamados usando a função full_error_backtrace.

Esta função faz o rastreamento do erro desde o procedimento onde ele ocorreu (exceção não tratada no procedimento) até o primeiro procedimento onde o erro for tratado.

O exemplo abaixo mostra que o erro ocorrido no procedimento prc_getano é propagado para o tratamento de exceção do procedimento prc_backtrace onde a função dlog.plog.full_error_backtrace é chamada.


    PROCEDURE prc_getano(in_ano ano.ano%TYPE) IS
        v_encctb ano.enccontabil%TYPE;
    BEGIN
        SELECT a.enccontabil
        INTO   v_encctb
        FROM   ano a
        WHERE  a.ano = in_ano;
    END prc_getano;
 
    PROCEDURE prc_chamagetano(in_ano ano.ano%TYPE) IS
    BEGIN
        prc_getano(in_ano);
    END prc_chamagetano;
 
    PROCEDURE prc_backtrace(in_ano ano.ano%TYPE) IS
    BEGIN
        prc_chamagetano(in_ano);
        dlog.plog.info('Procedimento executado com sucesso');
    EXCEPTION
        WHEN OTHERS THEN
            dlog.plog.full_error_backtrace;
    END prc_backtrace;
 
    -- Chamada do procedimento
    BEGIN
        pkg_log4plsql.prc_backtrace(2158);
    END;


Mensagens gravadas na tabela de log (VLOG).


"[Ago 16, 11:14:42:09][ALL][ADDESENV][block-->ADDESENV.PKG_LOG4PLSQL][SQLCODE:100 SQLERRM:ORA-01403: dados não encontrados Error back trace:
em ""ADDESENV.PKG_LOG4PLSQL"", line 193
em ""ADDESENV.PKG_LOG4PLSQL"", line 214
em ""ADDESENV.PKG_LOG4PLSQL"", line 231
]"

Padrão de utilização na DTI

O uso na DTI foi padronizado para que as alterações do contexto de depuração possam ser feitas sem a necessidade de alteração e recompilação do código PL/SQL.

As chamadas aos procedimentos de depuração serão feitas sempre utilizando uma variável de contexto que será inicializada como mostrado abaixo.


    PROCEDURE prc_contexto;
 
        /* Variável de contexto para depuração */        
        v_ctx dlog.plogparam.log_ctx := dlog.fun_getctx(dlog.plog.init(), sys.fun_whoami);
 
    BEGIN
 
        dlog.plog.debug(v_ctx, 'Exemplo de mensagem de depuração com variável de contexto');
 
        /* É recomendada esta forma de codificação porque há menor impacto na performance da aplicação */
        IF dlog.plog.isdebugenabled(v_ctx) THEN
            dlog.plog.debug(v_ctx, 'Exemplo de mensagem de depuração com variável de contexto');
        END IF;
 
    END prc_contexto;


Foi criado uma tabela para armazenar as configurações de contexto individual por objeto a ser depurado. Desta forma é possível configurar um contexto diferente do contexto padrão do servidor, para um objeto específico e por tempo determinado.

Esta configuração permite a alteração do nome da seção, nível de depuração, exibição na saída padrão, tamanho da linha na saída padrão e ainda a data e hora final do contexto.

A configuração pode ser feita para procedures, functions, triggers ou packages. Para os packages a configuração pode ser feita tanto para o package como um todo ou para procedures ou functions internas.

Os objetos que não estiverem cadastrados ou estiverem com a data limite vencida serão depurados de acordo com a configuração padrão do servidor.

A manutenção pode ser acessada somente pelos analistas e desenvolvedores da DTI e está disponível no Menu Geral dos Sistemas Informatizados em Administrativo >> Suporte >> Depuração de código Pl/Sql.

Ferramentas pessoais
Espaços nominais
Variantes
Ações
Navegação
Ferramentas