Registo de desempenho e função de retorno

Baixar driver JDBC

A partir da versão 13.4, o Microsoft JDBC Driver for SQL Server fornece uma estrutura de métricas de desempenho para acompanhar o timing das operações críticas dos drivers. Pode usar esta estrutura para observar e analisar o comportamento de execução de ligação e de sentenças, ajudando a identificar gargalos de latência nas interações da sua aplicação com o SQL Server.

As métricas estão disponíveis através de dois mecanismos que podem ser usados independentemente ou em conjunto:

  • Chamada de retorno programática - Registe um PerformanceLogCallback para receber métricas no seu código de aplicação.
  • Registo Java - Subscreva loggers dedicados java.util.logging para capturar métricas na saída do log.

Atividades monitorizadas

O condutor acompanha as atividades em dois níveis: ligação e declaração.

Atividades ao nível de ligação

Activity Descrição
CONNECTION Tempo total para estabelecer uma ligação, incluindo todas as subatividades.
PRELOGIN Hora da negociação pré-login do TDS com o servidor.
LOGIN Está na hora do aperto de mão de login e autenticação do TDS.
TOKEN_ACQUISITION Está na altura de adquirir tokens de autenticação federada utilizando a autenticação da Microsoft Entra.

Atividades ao nível de instrução

Activity Descrição
STATEMENT_REQUEST_BUILD Tempo do lado do cliente para construir o pedido TDS (ligação de parâmetros, processamento SQL, construção de pacotes). Apenas cronometragem, não regista exceções.
STATEMENT_FIRST_SERVER_RESPONSE Tempo desde o envio do pedido até receber a primeira resposta do servidor. Apenas cronometragem, não regista exceções.
STATEMENT_PREPARE Hora de sp_prepare quando prepareMethod=prepare.
STATEMENT_PREPEXEC Tempo para a preparação e execução combinados via sp_prepexec.
STATEMENT_EXECUTE Tempo para execução de instruções (sp_executesql, sp_execute, SQL direto ou batch).

Ativar métricas de desempenho

Opção 1: Registar uma chamada de retorno

Registe a PerformanceLogCallback para receber dados de desempenho programaticamente:

SQLServerDriver.registerPerformanceLogCallback(new PerformanceLogCallback() {
    @Override
    public void publish(PerformanceActivity activity, int connectionId,
            long durationMs, Exception exception) {
        // Connection-level metrics
        System.out.printf("Activity: %s, Connection: %d, Duration: %d ms%n",
                activity, connectionId, durationMs);
    }

    @Override
    public void publish(PerformanceActivity activity, int connectionId,
            int statementId, long durationMs, Exception exception) {
        // Statement-level metrics
        System.out.printf("Activity: %s, Connection: %d, Statement: %d, Duration: %d ms%n",
                activity, connectionId, statementId, durationMs);
    }
});

Usar o tempo de nanossegundos e o contexto da afirmação

A partir da versão 13.6, um callback pode optar por temporização em nanosegundos ao sobrepor useNanoseconds(). O callback também pode chamar getCurrentUserSql() e getCurrentStatementType() para correlacionar um evento ao nível de instrução com o texto SQL submetido pela aplicação e o tipo de instrução executada. getCurrentStatementType() devolve STATEMENT, PREPARED_STATEMENT, ou CALLABLE_STATEMENT. Utilize getCurrentApplicationName() para identificar a ligação ou pool que produziu um evento através da sua propriedade de ligação applicationName. Se applicationName não estiver definido, o método devolve o nome padrão da aplicação do driver.

SQLServerDriver.registerPerformanceLogCallback(new PerformanceLogCallback() {
    @Override
    public boolean useNanoseconds() {
        return true;
    }

    @Override
    public void publish(PerformanceActivity activity, int connectionId,
            long durationNs, Exception exception) {
        // Connection-level metrics don't have SQL statement context.
        System.out.printf("Application: %s, Activity: %s, Connection: %d, Duration: %d ns%n",
            getCurrentApplicationName(), activity, connectionId, durationNs);
    }

    @Override
    public void publish(PerformanceActivity activity, int connectionId,
            int statementId, long durationNs, Exception exception) {
        String applicationName = getCurrentApplicationName();
        String userSql = getCurrentUserSql();
        StatementType statementType = getCurrentStatementType();

        System.out.printf("Application: %s, Type: %s, Activity: %s, SQL: %s, Duration: %d ns%n",
            applicationName, statementType, activity, userSql, durationNs);
    }
});

A temporização em nanossegundos é opcional. Os callbacks que não sobrescrevem useNanoseconds() continuam a receber durações em milissegundos. Quando um callback registado aceita essa opção, a saída dedicada do registo de desempenho também utiliza nanossegundos e identifica as durações com ns; caso contrário, utiliza milissegundos e ms. Chamar System.nanoTime() pode ter mais sobrecarga do que System.currentTimeMillis() em algumas plataformas.

O contexto da callback está disponível apenas durante a correspondente invocação publish(). getCurrentApplicationName() está disponível para eventos ao nível da ligação e da instrução e devolve null fora de publish(). Também pode devolver null quando as propriedades da ligação ainda não tiverem sido processadas, por exemplo, quando uma ligação falha antes de o nome da aplicação ser resolvido. Os métodos de contexto SQL devolvem null para eventos ao nível da ligação, métricas de subatividade de instruções que não têm contexto SQL e chamadas feitas fora de publish().

Caution

O texto SQL pode conter dados sensíveis em literais ou comentários. Higienize-o e aplique os requisitos de tratamento de dados da sua organização antes de o escrever em registos ou telemetria.

Opção 2: Configurar o registo Java

Configura java.util.logging para os registos de métricas de desempenho no FINE nível.

Em um logging.properties ficheiro:

com.microsoft.sqlserver.jdbc.PerformanceMetrics.Connection.level = FINE
com.microsoft.sqlserver.jdbc.PerformanceMetrics.Statement.level = FINE
handlers = java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level = FINE

Ou programaticamente:

Logger.getLogger("com.microsoft.sqlserver.jdbc.PerformanceMetrics.Connection")
      .setLevel(Level.FINE);
Logger.getLogger("com.microsoft.sqlserver.jdbc.PerformanceMetrics.Statement")
      .setLevel(Level.FINE);

Preparar o efeito do método sobre as atividades da declaração

As atividades monitorizadas PreparedStatement dependem da propriedade de ligação prepareMethod . Para mais informações sobre prepareMethod, veja Definir as propriedades de ligação.

Configuração prepareMethod Primeira execução Segunda execução Terceira execução Plus
prepexec (padrão) STATEMENT_EXECUTE (sp_executesql) STATEMENT_PREPEXEC (sp_prepexec) STATEMENT_EXECUTE (sp_execute)
prepare STATEMENT_PREPARE + STATEMENT_EXECUTE STATEMENT_EXECUTE STATEMENT_EXECUTE
none STATEMENT_EXECUTE (SQL direto) STATEMENT_EXECUTE (SQL direto) STATEMENT_EXECUTE (SQL direto)

Observação

Com a configuração padrão prepexec , o condutor adia a preparação assumindo uso único. A segunda execução utiliza sp_prepexec (preparar e executar combinado). A partir da terceira execução, o handle em cache é reutilizado via sp_execute. Para forçar sp_prepexec a primeira chamada, defina a propriedade enablePrepareOnFirstPreparedStatementCall de ligação para true.

Amostra de saída logarítmica

A saída seguinte mostra as atividades rastreadas ao longo de três execuções consecutivas de um PreparedStatement com a configuração padrão prepexec.

ConnectionID:1, StatementID:1 Request build time, duration: 8ms
ConnectionID:1, StatementID:1 First server response, duration: 17ms
ConnectionID:1, StatementID:1 Statement execute, duration: 75ms        ← 1st call: sp_executesql
ConnectionID:1, StatementID:1 Request build time, duration: 9ms
ConnectionID:1, StatementID:1 First server response, duration: 0ms
ConnectionID:1, StatementID:1 Statement prepexec, duration: 0ms        ← 2nd call: sp_prepexec
ConnectionID:1, StatementID:1 Request build time, duration: 0ms
ConnectionID:1, StatementID:1 First server response, duration: 0ms
ConnectionID:1, StatementID:1 Statement execute, duration: 0ms         ← 3rd call: sp_execute