So protokollieren Sie SQL-Anweisungen in Grails

85

Ich möchte mich in der Konsole oder in einer Datei anmelden, alle Abfragen, die Grails ausführt, um die Leistung zu überprüfen.

Ich hatte dies ohne Erfolg konfiguriert .

Jede Idee würde helfen.

user2427
quelle
Keine der angebotenen Lösungen funktioniert für mich. Ich schreibe das nur, um alle wissen zu lassen, wie verzweifelt ich bin.
Andrea

Antworten:

130

Rahmen

datasource {
...
logSql = true
}

in DataSource.groovy (gemäß diesen Anweisungen) war genug, um es in meiner Umgebung zum Laufen zu bringen. Es scheint, dass Teile der FAQ veraltet sind (z. B. die Frage "Viele-zu-Viele-Spalten rückwärts"), sodass sich dies möglicherweise auch in der Zwischenzeit geändert hat.

Tomislav Nakic-Alfirevic
quelle
6
logSql=trueallein reicht nicht aus. Die Protokollierung im Ruhezustand muss ebenfalls aktiviert sein. Siehe @ Petes Antwort.
Jason
2
Ich habe festgestellt, dass dies nicht die Werte enthält, die in den SQL-Anweisungen enthalten sind, in denen sich die "?" S befinden.
Jason
1
Dies funktioniert, aber für alle Abfragen. Ist es auch möglich, die generierte SQL für ein bestimmtes Kriterium zu drucken, ohne logSql = true setzen zu müssen?
Guus
@Guus Wie kann ich die generierte SQL für ein bestimmtes Kriterium drucken?
Biniam
@biniam_Ethiopia Soweit ich weiß, ist dies nicht möglich. Ich möchte dies ebenso wie es ärgerlich ist, bestimmte Klassen zu debuggen und andere Abfragen nicht zu sehen.
Guus
91

Ich finde es nützlicher, Folgendes zu tun, nämlich die Protokollierung von Hibernate zu aktivieren, um das SQL zusammen mit Bindungsvariablen zu protokollieren (damit Sie die an Ihre Aufrufe übergebenen Werte sehen und das SQL einfach in Ihrem Editor oder auf andere Weise replizieren können).

In Ihrem Config.groovy, fügen Sie folgendes zu Ihrem log4j Block:

log4j = {

    // Enable Hibernate SQL logging with param values
    trace 'org.hibernate.type'
    debug 'org.hibernate.SQL'
    //the rest of your logging config
    // ...
    }
Peter
quelle
8
Ich habe das schon oft benutzt. Eines ist zu beachten: Die Ausgabe der Parameter ist sehr teuer. Ich würde empfehlen, dies nur auf Ihrer Entwicklungsbox zu tun.
John Gordon
2
Sie können auch format_sql = truein den hibernateBlock Ihres hinzufügen, DataSource.groovyum eine schön formatierte Ausgabe zu erhalten.
Gregor Petrin
1
Hinweis: Hiermit werden sowohl Klauselparameter als auch Spaltenwerte protokolliert, die aus Abfrageergebnismengen extrahiert wurden. Verwenden Sietrace 'org.hibernate.type.BasicBinder'
GreenGiant
Kennt jemand das Äquivalent für Grails 3.3.8?
John Little
Aus irgendeinem Grund werden syntaktisch ungültige Abfragen (leider von Hibernate selbst generiert!) Nicht protokolliert - alle anderen Abfragen werden protokolliert ... Möglicherweise ein Problem mit Hibernate selbst?
Janaka Bandara
31

Für Grale 3. *

Option 1 fügt logback.groovy Folgendes hinzu

logger("org.hibernate.SQL", DEBUG, ["STDOUT"], false)
logger("org.hibernate.type.descriptor.sql.BasicBinder", TRACE, ["STDOUT"], false)

oder

Option 2 fügt der dataSource in der application.yml Folgendes hinzu. Dieser Ansatz protokolliert jedoch nicht die Parameterwerte

environments:
  local:
    dataSource:
        logSql: true
        formatSql: true
Robert Hutto
quelle
17

Versuche dies:

log4j = {
   ...
   debug 'org.hibernate.SQL'
   trace 'org.hibernate.type.descriptor.sql.BasicBinder'
}

Dadurch werden die Leistungsprobleme bei der Ablaufverfolgungsprotokollierung des Hibernate- typePakets vermieden . Dies funktioniert mit Hibernate 3.6 und höher. Ich habe dies von: https://burtbeckwith.com/blog/?p=1604

Jason
quelle
6

Die Lösung ist nur für die Entwicklung, nicht für die Produktion.

Alle obigen Antworten funktionieren und sind korrekt. Sie zeigen jedoch nicht die vollständige Abfrage auf eine gut lesbare Weise. Wenn Sie die letzte (ohne?,?) Abfrage sehen möchten, haben Sie zwei Möglichkeiten.

A) Proxy Ihrer JDBC-Verbindung mit log4jdbc oder p6Spy.

B) Betrachten Sie es auf Datenbankebene. Zum Beispiel sehr einfach mit MySQL zu tun.

Finden Sie heraus, wo sich Ihre general_log_file befindet. Aktives allgemeines Protokoll, falls noch nicht aktiviert.

mysql command line> show variables like "%general_log%";
mysql command line> set global general_log = true;

Jetzt wird alles in Ihrer Protokolldatei protokolliert. Mac / Linux-Beispiel, um einen schönen Stream Ihrer Abfragen anzuzeigen.

tail -f path_to_log_file 
Wuestenfuchs
quelle
3

Nur als Referenz, aber ich verwende p6spy, um die SQL-Abfragen zu protokollieren. Es ist ein kleiner JDBC-Zwischentreiber. Die genaue Abfrage wird so protokolliert, als würde sie an den Server gesendet (einschließlich Parameter).

Nehmen Sie es in Ihr Projekt auf:

runtime 'p6spy:p6spy:3.0.0'

Ändern Sie Ihren Datenquellentreiber:

driverClassName: com.p6spy.engine.spy.P6SpyDriver

Und deine JDBC-URL:

url: jdbc:p6spy:mysql://

Konfigurieren Sie es mit spy.properties (in grails-app / conf).

driverlist=org.h2.Driver,com.mysql.jdbc.Driver
autoflush=true
appender=com.p6spy.engine.spy.appender.StdoutLogger
databaseDialectDateFormat=yyyy-MM-dd
logMessageFormat=com.p6spy.engine.spy.appender.MultiLineFormat

Vergessen Sie nicht, dies für die Produktion zu deaktivieren!

Dennie de Lange
quelle
1

Ich weiß, dass dies vor langer Zeit gestellt und beantwortet wurde. Aber ich habe diese Frage zufällig gesehen und konnte mich nicht davon abhalten, unseren Implementierungsansatz für die SQL-Protokollierung in unserem Projekt zu beantworten oder zu teilen. Hoffe es hilft etwas.

Derzeit befindet es sich in einer Entwicklungsumgebung. Wir verwenden "log4jdbc Driver Spy", um SQL zu protokollieren.

Aufbau:

Fügen Sie in Ihrem BuildConfig.groovy die folgenden Abhängigkeiten hinzu:

dependencies {
.....
runtime 'org.lazyluke:log4jdbc-remix:0.2.7'
}

Und in Ihrer DataSource oder einer anderen konfigurationsbezogenen Konfiguration: [wo immer Sie die datenquellenbezogene Konfiguration definiert haben], Hinzufügen:

datasources{
.....
driverClassName: "net.sf.log4jdbc.DriverSpy",
url: "jdbc:log4jdbc:oracle:thin:@(DESCRIPTION =(ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = XXXXX.XX>XXX)(PORT = 1521))) (CONNECT_DATA = (SID = XXXX)(SERVER =DEDICATED)))",
....
}
log4j = {

    info 'jdbc.sqlonly' //, 'jdbc.resultsettable'

}

Aus meiner persönlichen Erfahrung fand ich es beim Debuggen sehr nützlich und hilfreich. Weitere Informationen finden Sie auf dieser Website. https://code.google.com/p/log4jdbc-remix/

König Grüße

Madhu Bose
quelle
1

Weiter funktioniert bei mir:

grails-app / conf / application.yml

# ...
hibernate:
    format_sql: true # <<<<<<< ADD THIS <<<<<<<
    cache:
        queries: false
        use_second_level_cache: true
# ...
environments:
    development:
        dataSource:
            logSql: true // <<<<<<< ADD THIS <<<<<<<
            dbCreate: create-drop
            url: jdbc:h2:mem:...
# ...

grails-app / conf / logback.groovy

// ...
appender('STDOUT', ConsoleAppender) {
    encoder(PatternLayoutEncoder) {
        pattern = "%level %logger - %msg%n"
    }
}

// >>>>>>> ADD IT >>>>>>>
logger 'org.hibernate.type.descriptor.sql.BasicBinder', TRACE, ['STDOUT']
logger 'org.hibernate.SQL', TRACE, ['STDOUT']
// <<<<<<< ADD IT <<<<<<<

root(ERROR, ['STDOUT'])

def targetDir = BuildSettings.TARGET_DIR
// ...

Quelle: http://sergiodelamo.es/log-sql-grails-3-app/

Eduardo Cuomo
quelle
0

Für einen bestimmten Codeblock können wir auch eine Methode erstellen, die einen Abschluss akzeptiert. z.B.

 static def executeBlockAndGenerateSqlLogs(Closure closure) {
    Logger sqlLogger = Logger.getLogger("org.hibernate.SQL");
    Level currentLevel = sqlLogger.level
    sqlLogger.setLevel(Level.TRACE)
    def result = closure.call()
    sqlLogger.setLevel(currentLevel)
    result }

executeBlockAndGenerateSqlLogs{DomainClazz.findByPropertyName("property value")}
Akashsethi
quelle
0

Wenn Sie das Konsolen- Plugin installiert haben, können Sie mit diesem kleinen Code-Snippet eine SQL-Protokollierung durchführen.

// grails 2.3
def logger=ctx.sessionFactory.settings.sqlStatementLogger

// grails 3.3  
def logger = ctx.sessionFactory.currentSession.jdbcCoordinator.statementPreparer.jdbcService.sqlStatementLogger

logger.logToStdout=true    
try {
   <code that will log sql queries>
}
finally {
    logToStdout = false
}

Dies ist eine Variation vieler der oben genannten Lösungen, ermöglicht es Ihnen jedoch, den Wert zur Laufzeit zu optimieren. Und genau wie bei den anderen Lösungen, die sich damit befassen logToStdout, werden nur die Abfragen und nicht die Bindungswerte angezeigt.

Die Idee wurde einem Burtbeck mit einem Post gestohlen, den ich vor einigen Jahren gelesen habe und den ich momentan nicht finden kann. Es wurde bearbeitet, um mit Grails 3.3 zu arbeiten.

Eine ähnliche Technik kann verwendet werden, um die Protokollierung für bestimmte Integrationstests zu aktivieren:

class SomeIntegrationSpec extends IntegrationSpec {

    def sessionFactory

    def setup() {
        sessionFactory.settings.sqlStatementLogger.logToStdout = true
    }

    def cleanup() {
        sessionFactory.settings.sqlStatementLogger.logToStdout = false
    }

    void "some test"() {
           ...
    }

Dadurch wird die SQL-Protokollierung nur für die Tests in dieser einen Datei aktiviert.

brennt
quelle