web-dev-qa-db-fra.com

Activer la journalisation des instructions SQL lors de l'utilisation de JDBC

J'essaie d'activer les journaux à l'aide de mon programme JDBC en me connectant à la base de données Oracle dans Eclipse IDE.

J'ai parcouru ce SO post connexion JDBC au fichier puis j'ai créé ci-dessous Java programme et l'exécuter à partir de mon IDE Eclipse , mais je n'ai pas pu voir les journaux générés par les classes de pilotes JDBC.

import Java.io.File;
import Java.io.FileInputStream;
import Java.io.PrintWriter;
import Java.sql.Connection;
import Java.sql.DriverManager;
import Java.sql.SQLException;
import Java.util.Properties;
import Java.util.logging.LogManager;
import Java.util.logging.Logger;

public class Logging {

    static Logger log = Logger.getLogger(Logging.class.toString());
    static Connection con = null;

    public static void main(String[] args) throws SQLException,
            ClassNotFoundException {
        System.setProperty("Oracle.jdbc.Trace", Boolean.TRUE.toString());
        System.setProperty("Java.util.logging.config.file",
                "OracleLog.properties");
        log.info("Test Message");
        enableLogging(false);
        getConnection();
        closeConnection();
    }

    static private void enableLogging(boolean logDriver) {
        try {
            Oracle.jdbc.driver.OracleLog.setTrace(true);

            // compute the ObjectName
            String loader = Thread.currentThread().getContextClassLoader()
                    .toString().replaceAll("[,=:\"]+", "");
            javax.management.ObjectName name = new javax.management.ObjectName(
                    "com.Oracle.jdbc:type=diagnosability,name=" + loader);

            // get the MBean server
            javax.management.MBeanServer mbs = Java.lang.management.ManagementFactory
                    .getPlatformMBeanServer();

            // find out if logging is enabled or not
            System.out.println("LoggingEnabled = "
                    + mbs.getAttribute(name, "LoggingEnabled"));

            // enable logging
            mbs.setAttribute(name, new javax.management.Attribute(
                    "LoggingEnabled", true));

            File propFile = new File("path/to/properties");
            LogManager logManager = LogManager.getLogManager();
            logManager.readConfiguration(new FileInputStream(propFile));

            if (logDriver) {
                DriverManager.setLogWriter(new PrintWriter(System.err));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection() throws SQLException,
            ClassNotFoundException {
        Properties connectionProps = new Properties();
        connectionProps.put("user", "test_app");
        connectionProps.put("password", "test");

        Class.forName("Oracle.jdbc.driver.OracleDriver");
        con = DriverManager.getConnection(
                "jdbc:Oracle:thin:@"+Host_IP+":1521:"+SID,
                connectionProps);
        System.out.println("Connected to database");
        return con;
    }

    public static void closeConnection() throws SQLException {
        if (con != null) {
            con.close();
        }
    }

}

et j'ai ci-dessous le contenu de mon fichier OracleLog.properties:

.level=SEVERE
Oracle.jdbc.level=INFO
Oracle.jdbc.handlers=Java.util.logging.ConsoleHandler
Java.util.logging.ConsoleHandler.level=INFO
Java.util.logging.ConsoleHandler.formatter=Java.util.logging.SimpleFormatter

Mais lorsque j'exécute mon programme en plaçant ojdbc6-11.2.0.3.jar dans classpath alors je reçois une exception comme:

INFO: Test Message
javax.management.InstanceNotFoundException: com.Oracle.jdbc:type=diagnosability,name=Sun.misc.Launcher$AppClassLoader@73d16e93
    at com.Sun.jmx.interceptor.DefaultMBeanServerInterceptor.getMBean(DefaultMBeanServerInterceptor.Java:1095)
    at com.Sun.jmx.interceptor.DefaultMBeanServerInterceptor.getAttribute(DefaultMBeanServerInterceptor.Java:643)
    at com.Sun.jmx.mbeanserver.JmxMBeanServer.getAttribute(JmxMBeanServer.Java:678)
    at myjdbc.Logging.enableLogging(Logging.Java:45)
    at myjdbc.Logging.main(Logging.Java:24)
Connected to database

Si j'ai ojdbc6_g.jar dans classpath, puis je reçois la même exception.

Veuillez me faire savoir comment activer la journalisation pour mon programme JDBC? fondamentalement, je m'attends à voir les journaux générés par le code JDBC interne.

Mise à jour: Maintenant, j'ai placé ojdbc6dms.jar fichier dans classpath, mon programme donne l'exception ci-dessous:

Nov 28, 2014 9:09:02 PM jdbc.chap2.Logging main
INFO: Test Message
javax.management.InstanceNotFoundException: com.Oracle.jdbc:type=diagnosability,name=Sun.misc.Launcher$AppClassLoader@73d16e93
    at com.Sun.jmx.interceptor.DefaultMBeanServerInterceptor.getMBean(DefaultMBeanServerInterceptor.Java:1095)
    at com.Sun.jmx.interceptor.DefaultMBeanServerInterceptor.getAttribute(DefaultMBeanServerInterceptor.Java:643)
    at com.Sun.jmx.mbeanserver.JmxMBeanServer.getAttribute(JmxMBeanServer.Java:678)
    at jdbc.chap2.Logging.enableLogging(Logging.Java:45)
    at jdbc.chap2.Logging.main(Logging.Java:24)
Exception in thread "main" Java.lang.NoClassDefFoundError: Oracle/dms/console/DMSConsole
    at Oracle.jdbc.driver.DMSFactory.<clinit>(DMSFactory.Java:48)
    at Oracle.jdbc.driver.PhysicalConnection.createDMSSensors(PhysicalConnection.Java:2121)
    at Oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.Java:730)
    at Oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.Java:433)
    at Oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.Java:32)
    at Oracle.jdbc.driver.OracleDriver.connect(OracleDriver.Java:608)
    at Java.sql.DriverManager.getConnection(DriverManager.Java:664)
    at Java.sql.DriverManager.getConnection(DriverManager.Java:208)
    at jdbc.chap2.Logging.getConnection(Logging.Java:70)
    at jdbc.chap2.Logging.main(Logging.Java:25)
Caused by: Java.lang.ClassNotFoundException: Oracle.dms.console.DMSConsole
    at Java.net.URLClassLoader$1.run(URLClassLoader.Java:372)
    at Java.net.URLClassLoader$1.run(URLClassLoader.Java:361)
    at Java.security.AccessController.doPrivileged(Native Method)
    at Java.net.URLClassLoader.findClass(URLClassLoader.Java:360)
    at Java.lang.ClassLoader.loadClass(ClassLoader.Java:424)
    at Sun.misc.Launcher$AppClassLoader.loadClass(Launcher.Java:308)
    at Java.lang.ClassLoader.loadClass(ClassLoader.Java:357)
    ... 10 more
25
learner

Si vous utilisez le framework Spring, alors le datasource-proxy est très pratique. Vous pouvez essentiellement boucler n'importe quel DataSource et simplement ajouter le comportement de journalisation.

enter image description here

Si vous utilisez Java EE, alors P6spy est une bonne alternative:

enter image description here

Dans les coulisses, p6spy fournit l'intercepteur d'instructions au niveau Driver, ce qui est beaucoup plus pratique pour les applications Java EE car le DataSource est fourni par le serveur d'applications.

6
Vlad Mihalcea

Mise à jour 2019: log4jdbc n'a pas été maintenu depuis 2015. p6spy semble toujours être activement maintenu.

Réponse originale

Il y a beaucoup de frameworks Spy disponibles à cet effet, veuillez vérifier log4jdbc , je suis tombé c'est ce que vous recherchez.

Caractéristiques

  • Prise en charge complète de JDBC 3 et JDBC 4!
  • Facile à configurer, dans la plupart des cas, tout ce que vous avez à faire est de changer le nom de la classe de pilote en net.sf.log4jdbc.DriverSpy et d'ajouter "jdbc: log4" à votre URL jdbc existante, de configurer vos catégories de journalisation et vous êtes prêt à aller!
  • Dans la sortie consignée, pour les instructions préparées, les arguments de liaison sont automatiquement insérés dans la sortie SQL. Cela améliore considérablement la lisibilité et le débogage dans de nombreux cas.
  • Les informations de synchronisation SQL peuvent être générées pour aider à identifier le temps d'exécution des instructions SQL, ce qui permet d'identifier les instructions qui s'exécutent trop lentement et ces données peuvent être post-traitées avec un outil inclus pour produire des données de rapport de profilage pour identifier rapidement le SQL lent dans votre application .
  • Des informations sur le numéro de connexion SQL sont générées pour aider à identifier les problèmes de regroupement de connexions ou de thread. Fonctionne avec tout pilote JDBC sous-jacent, avec JDK 1.4 et supérieur, et SLF4J 1.x.
  • Logiciel open source, sous licence Apache 2.0

Utilisation

  • Placez le pot log4jdbc (basé sur la version JDK) dans le chemin de classe de votre application.
  • choisissez le système de journalisation à utiliser, log4j, logback, commons logging..etc sont pris en charge
  • Définissez votre classe de pilote JDBC sur net.sf.log4jdbc.DriverSpy dans la configuration de votre application. Le pilote sous-jacent qui est espionné dans de nombreux cas sera chargé automatiquement sans aucune configuration supplémentaire.
  • Ajoutez jdbc: log4 à l'url jdbc normale que vous utilisez.

    Par exemple, si votre URL jdbc normale est jdbc: derby: // localhost: 1527 // db-derby-10.2.2.0-bin/databases/MyDatabase alors vous la changeriez en: jdbc: log4jdbc: derby: // localhost: 1527 // db-derby-10.2.2.0-bin/databases/MyDatabase

  • Configurez vos enregistreurs.

    jdbc.sqlonly : enregistre uniquement SQL. Le SQL exécuté dans une instruction préparée est automatiquement affiché avec ses arguments de liaison remplacés par les données liées à cette position, pour une lisibilité considérablement accrue. 1.0

    jdbc.sqltiming : enregistre le SQL, la post-exécution, y compris les statistiques de synchronisation sur la durée d'exécution du SQL. 1.0

    jdbc.audit : consigne TOUS les appels JDBC à l'exception des jeux de résultats. Il s'agit d'une sortie très volumineuse et n'est normalement pas nécessaire, sauf si vous recherchez un problème JDBC spécifique. 1.0

    jdbc.resultset : Encore plus volumineux, car tous les appels aux objets ResultSet sont enregistrés. 1.0

    jdbc.connection : enregistre les événements d'ouverture et de fermeture de connexion ainsi que le vidage de tous les numéros de connexion ouverts. Ceci est très utile pour rechercher les problèmes de fuite de connexion.

11
Prince

Un sujet très ancien, je sais, mais ce qui n'a pas encore été mentionné, c'est que pour Oracle, il existe une solution qui ne nécessite aucune modification du code d'application, simplement en utilisant le pilote Oracle JDBC activé pour la trace et en activant la journalisation via les propriétés JVM au démarrage.

Oracle eux-mêmes l'ont décrit ici , et après quelques essais et erreurs, je l'ai fait fonctionner:

  1. Placez le fichier jar ojdbc à trace activée dans votre chemin de classe. Citation de la page Oracle liée: "Pour obtenir la sortie du journal, vous devez utiliser les fichiers JAR de débogage, qui sont indiqués par un" _g "dans le nom de fichier, comme ojdbc5_g.jar ou ojdbc6_g.jar." Mon installation Oracle 11g contenue

  2. Créez un fichier logging.properties comme décrit sur la page Oracle liée et ajustez les niveaux de journalisation selon vos besoins. Exemple:

    .level=SEVERE Oracle.jdbc.level=FINEST Oracle.jdbc.handlers=Java.util.logging.FileHandler Java.util.logging.FileHandler.level=FINEST Java.util.logging.FileHandler.pattern=jdbc.log Java.util.logging.FileHandler.count=1 Java.util.logging.FileHandler.formatter=Java.util.logging.SimpleFormatter

  3. Ajoutez les propriétés JVM "-Doracle.jdbc.Trace = true -Djava.util.logging.config.file = logging.properties" à la commande de démarrage Java Java pour votre application JDBC).

L'application JDBC devrait maintenant produire un fichier nommé jdbc.log qui devrait contenir les informations souhaitées. Dans certains cas, il peut être nécessaire de spécifier le chemin d'accès complet au fichier logging.properties.

8
Ralph Kirchner

Avez-vous essayé de définir la propriété système correspondante? par exemple. pour TRACE:

System.setProperty( "Oracle.jdbc.Trace", Boolean.TRUE.toString() );

(de https://docs.Oracle.com/cd/B28359_01/Java.111/b31224/diagnose.htm )

2
jo-