Leistungsprotokollierung und Rückruf

JDBC-Treiber herunterladen

Ab Version 13.4 bietet der Microsoft JDBC-Treiber für SQL Server ein Framework für Leistungsmetriken zur Erfassung der zeitlichen Abläufe wichtiger Treibervorgänge. Sie können dieses Framework verwenden, um das Verhalten der Verbindungs- und Anweisungsausführung zu beobachten und zu analysieren, um Latenzengpässe in den Interaktionen Ihrer Anwendung mit SQL Server zu identifizieren.

Metriken sind über zwei Mechanismen verfügbar, die unabhängig oder gemeinsam verwendet werden können:

  • Programmgesteuerter Rückruf – Registrieren Sie ein PerformanceLogCallback, um Metriken in Ihrem Anwendungscode zu erhalten.
  • Java-Protokollierung – Abonnieren Sie dedizierte java.util.logging Logger, um Metriken in der Protokollausgabe zu erfassen.

Nachverfolgte Aktivitäten

Der Treiber verfolgt Aktivitäten auf zwei Ebenen: Verbindung und Abfrage.

Aktivitäten auf Verbindungsebene

Aktivität Beschreibung
CONNECTION Gesamtzeit für das Herstellen einer Verbindung, einschließlich aller Subaktivitäten.
PRELOGIN Zeitraum für die TDS-Login-Vorverhandlung mit dem Server.
LOGIN Zeit für den TDS-Anmelde- und Authentifizierungs-Handshake.
TOKEN_ACQUISITION Zeit zum Abrufen von Verbundauthentifizierungstoken bei Verwendung der Microsoft Entra-Authentifizierung.

Aktivitäten auf Anweisungsebene

Aktivität Beschreibung
STATEMENT_REQUEST_BUILD Clientseitige Zeit zum Erstellen der TDS-Anforderung (Parameterbindung, SQL-Verarbeitung, Paketkonstruktion). Nur Zeitmessung; Ausnahmen werden nicht nachverfolgt.
STATEMENT_FIRST_SERVER_RESPONSE Zeit vom Senden der Anforderung an den Empfang der ersten Serverantwort. Nur Zeitmessung; Ausnahmen werden nicht nachverfolgt.
STATEMENT_PREPARE Zeit für sp_prepare wenn prepareMethod=prepare.
STATEMENT_PREPEXEC Zeit für die kombinierte Vorbereitung und Ausführung über sp_prepexec.
STATEMENT_EXECUTE Zeit für die Ausführung von Anweisungen (sp_executesql, sp_execute, direktes SQL oder Batch).

Aktivieren von Leistungsmetriken

Option 1: Registrieren eines Rückrufs

Registrieren Sie eine PerformanceLogCallback, um Leistungsdaten programmgesteuert zu erhalten.

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);
    }
});

Verwenden Sie Nanosekunden-Timing und Aussagekontext

Ab Version 13.6 kann ein Rückruf auf Nanosekunden-Timing wechseln, indem er überschreibt useNanoseconds(). Der Callback kann außerdem getCurrentUserSql() und getCurrentStatementType() aufrufen, um ein Ereignis auf Anweisungsebene mit dem von der Anwendung übermittelten SQL-Text und dem Typ der ausgeführten Anweisung zu korrelieren. getCurrentStatementType() gibt PREPARED_STATEMENT, CALLABLE_STATEMENT oder STATEMENT zurück. Verwenden Sie getCurrentApplicationName() , um die Verbindung oder den Pool zu identifizieren, der ein Ereignis aus seiner applicationName Verbindungseigenschaft erzeugt hat. Wenn applicationName nicht gesetzt ist, gibt die Methode den Standard-Anwendungsnamen des Treibers zurück.

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);
    }
});

Die Zeitmessung im Nanosekundenbereich ist optional. Callbacks, die useNanoseconds() nicht überschreiben, erhalten weiterhin Zeitangaben in Millisekunden. Wenn ein registrierter Callback sich dafür entscheidet, verwendet auch die Ausgabe des dedizierten Performance-Loggers Nanosekunden und kennzeichnet Dauern mit ns; andernfalls verwendet sie Millisekunden und ms. Der Aufruf von System.nanoTime() kann auf manchen Plattformen mit mehr Overhead verbunden sein als System.currentTimeMillis().

Callback-Kontext ist nur während des entsprechenden publish() Aufrufs verfügbar. getCurrentApplicationName() ist für Verbindungs- und Anweisungsereignisse verfügbar und gibt außerhalb von publish()null zurück. Sie kann auch null zurückgeben, wenn die Verbindungseigenschaften noch nicht analysiert wurden, zum Beispiel wenn eine Verbindung fehlschlägt, bevor der Anwendungsname aufgelöst wird. Die SQL-Kontextmethoden geben publish() für Ereignisse auf Verbindungsebene, Metriken für Anweisungsunteraktivitäten ohne SQL-Kontext und Aufrufe, die außerhalb von null erfolgen, zurück.

Caution

SQL-Text kann sensible Daten in Literalen oder Kommentaren enthalten. Bereinigen Sie diese und wenden Sie die Anforderungen Ihrer Organisation für den Umgang mit Daten an, bevor Sie sie in Protokolle oder Telemetriedaten schreiben.

Option 2: Konfigurieren der Java-Protokollierung

Konfigurieren Sie java.util.logging für die Leistungsmetriken-Protokollierer auf der Ebene von FINE.

In einer logging.properties Datei:

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

Oder per Programmierung:

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

Einfluss der Methoden auf die Anweisungsaktivitäten vorbereiten

Die Aktivitäten, die nachverfolgt werden PreparedStatement, hängen von der prepareMethod Verbindungseigenschaft ab. Weitere Informationen prepareMethodfinden Sie unter Festlegen der Verbindungseigenschaften.

prepareMethod-Einstellung Erste Ausführung Zweite Ausführung Dritte erweiterte Ausführung
prepexec (Standardwert) STATEMENT_EXECUTE (sp_executesql) STATEMENT_PREPEXEC (sp_prepexec) STATEMENT_EXECUTE (sp_execute)
prepare STATEMENT_PREPARE + STATEMENT_EXECUTE STATEMENT_EXECUTE STATEMENT_EXECUTE
none STATEMENT_EXECUTE (direktes SQL) STATEMENT_EXECUTE (direktes SQL) STATEMENT_EXECUTE (direktes SQL)

Hinweis

Mit der Standardeinstellung prepexec verzögert der Treiber die Vorbereitung unter der Annahme einer einzelnen Verwendung. Die zweite Ausführung verwendet sp_prepexec (kombinierte Vorbereitung und Ausführung). Ab der dritten Ausführung wird der zwischengespeicherte Handle über sp_execute verwendet. Um sp_prepexec beim ersten Aufruf zu erzwingen, legen Sie die Verbindungseigenschaft enablePrepareOnFirstPreparedStatementCall auf true fest.

Beispielprotokollausgabe

Die folgende Ausgabe zeigt die Aktivitäten, die in drei aufeinanderfolgenden Ausführungen einer PreparedStatement mit der Standardeinstellung prepexec nachverfolgt wurden:

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