Jak rejestrować instrukcje SQL w Grails

86

Chcę zalogować się do konsoli lub do pliku, wszystkie zapytania, które robi Grails, aby sprawdzić wydajność.

Skonfigurowałem to bez powodzenia.

Każdy pomysł by pomógł.

user2427
źródło
Żadne z przedstawionych rozwiązań nie działa dla mnie. Piszę to, żeby wszyscy wiedzieli, jak bardzo jestem zdesperowany.
Andrea

Odpowiedzi:

131

Oprawa

datasource {
...
logSql = true
}

w DataSource.groovy (zgodnie z tymi instrukcjami) wystarczyło, aby dostać pracę w moim otoczeniu. Wygląda na to, że części FAQ są nieaktualne (np. Pytanie „wiele do wielu kolumn wstecz”), więc może to też się zmienić w międzyczasie.

Tomislav Nakic-Alfirevic
źródło
6
logSql=truesam nie wystarczy. Rejestrowanie hibernacji również musi być włączone. Zobacz odpowiedź @ Pete'a.
Jason
2
Zauważyłem, że nie obejmuje to wartości, które pojawiają się w instrukcjach SQL, w których znajdują się znaki „?”.
Jason
1
To działa, ale w przypadku wszystkich zapytań. Czy można również wydrukować wygenerowany plik sql dla określonych kryteriów bez konieczności ustawiania logSql = true?
sierpień
@Guus, jak mogę wydrukować wygenerowany plik sql dla określonych kryteriów?
biniam
@biniam_Ethiopia O ile wiem, nie jest to możliwe. Chcę tego, ponieważ jest to denerwujące w przypadku debugowania niektórych klas i nie chce widzieć również innych zapytań.
sierpnia
91

Uważam, że bardziej przydatne jest wykonanie następujących czynności, które polegają na umożliwieniu rejestrowania przez Hibernate rejestrowania kodu SQL wraz ze zmiennymi powiązanymi (aby można było zobaczyć wartości przekazywane do wywołań i łatwo replikować kod SQL w edytorze lub w inny sposób).

W swoim Config.groovy, dodaj do swojego bloku log4j:

log4j = {

    // Enable Hibernate SQL logging with param values
    trace 'org.hibernate.type'
    debug 'org.hibernate.SQL'
    //the rest of your logging config
    // ...
    }
Piotr
źródło
8
Używałem tego wiele razy. Jedna uwaga: wyprowadzanie parametrów jest bardzo kosztowne. Zalecałbym zrobienie tego tylko na twoim dev boxie.
John Gordon
2
Możesz również dodać format_sql = truedo hibernatebloku swojego, DataSource.groovyaby uzyskać ładnie sformatowane wyjście.
Gregor Petrin
1
Uwaga: spowoduje to zarejestrowanie zarówno parametrów klauzuli where, jak i wartości kolumn wyodrębnionych z zestawów wyników zapytania. Aby rejestrować tylko w przypadku parametrów klauzuli, użyjtrace 'org.hibernate.type.BasicBinder'
GreenGiant
Czy ktoś zna odpowiednik Grailsów 3.3.8?
John Little,
Z jakiegoś powodu niepoprawne składniowo zapytania (generowane przez samą Hibernate, niestety!) Nie są rejestrowane - wszystkie inne zapytania są rejestrowane ... Prawdopodobnie problem z samą Hibernate?
Janaka Bandara
32

Za Graile 3. *

Opcja nr 1: dodaj następujące elementy do logback.groovy

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

lub

Opcja nr 2 dodaj następujące elementy do dataSource w pliku application.yml. Jednak to podejście nie rejestruje wartości parametrów

environments:
  local:
    dataSource:
        logSql: true
        formatSql: true
Robert Hutto
źródło
17

Spróbuj tego:

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

Pozwala uniknąć problemów z wydajnością związanych z rejestrowaniem śledzenia typepakietu Hibernate . Działa to z Hibernate 3.6 i nowszymi wersjami. Mam to z: https://burtbeckwith.com/blog/?p=1604

Jason
źródło
6

Rozwiązanie służy tylko do rozwoju, a nie do produkcji.

Wszystkie powyższe odpowiedzi działają i są poprawne. Ale nie pokazują całego zapytania w sposób czytelny dla człowieka. Jeśli chcesz zobaczyć ostatnie (bez?,?) Zapytanie, masz dwie opcje.

A) proxy połączenia JDBC za pomocą log4jdbc lub p6Spy.

B) spójrz na to na poziomie bazy danych. Na przykład bardzo łatwe do zrobienia z mysql.

Dowiedz się, gdzie znajduje się plik general_log_file. Aktywny dziennik ogólny, jeśli nie został jeszcze aktywowany.

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

Teraz wszystko jest zapisywane w pliku dziennika. Przykład Mac / linux, aby pokazać ładny strumień zapytań.

tail -f path_to_log_file 
Wuestenfuchs
źródło
3

Pure tylko w celach informacyjnych, ale używam p6spy do rejestrowania zapytań SQL. To mały pośredni sterownik jdbc. Dokładne zapytanie jest rejestrowane tak, jakby było wysłane do serwera (z uwzględnieniem parametrów).

uwzględnij to w swoim projekcie:

runtime 'p6spy:p6spy:3.0.0'

Zmień sterownik źródła danych:

driverClassName: com.p6spy.engine.spy.P6SpyDriver

I Twój adres URL jdbc:

url: jdbc:p6spy:mysql://

Skonfiguruj go za pomocą spy.properties (w 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

Nie zapomnij wyłączyć tego na potrzeby produkcji!

Dennie de Lange
źródło
2

Dalej działa dla mnie:

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
// ...

Źródło: http://sergiodelamo.es/log-sql-grails-3-app/

Eduardo Cuomo
źródło
1

Wiem, że zadawano to pytanie i odpowiadałem na nie dawno temu, ale właśnie zdarzyło mi się zobaczyć to pytanie i nie mogłem się powstrzymać przed udzieleniem odpowiedzi lub udostępnieniem naszego podejścia do implementacji logowania sql w naszym projekcie. Mam nadzieję, że to pomoże.

Obecnie jest w środowisku deweloperskim. Używamy „log4jdbc Driver Spy” do logowania sql.

Konfiguracja:

W swoim BuildConfig.groovy: dodaj poniższe zależności:

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

A w swoim źródle danych lub innej konfiguracji związanej z: [gdziekolwiek zdefiniowałeś konfigurację związaną ze źródłem danych], dodaj:

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'

}

Z własnego doświadczenia wynika, że ​​jest to przydatne i pomocne podczas debugowania. Więcej informacji można znaleźć na tej stronie. https://code.google.com/p/log4jdbc-remix/

Z poważaniem

Madhu Bose
źródło
0

Dla konkretnego bloku kodu możemy również stworzyć metodę akceptującą zamknięcie. na przykład.

 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
źródło
0

Jeśli masz zainstalowaną wtyczkę konsoli , możesz uzyskać rejestrowanie sql za pomocą tego małego fragmentu kodu.

// 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 {
    logger.logToStdout = false
}

Jest to odmiana wielu z powyższych rozwiązań, ale umożliwia dostosowanie wartości w czasie wykonywania. I podobnie jak inne rozwiązania, które sobie z tym radzą logToStdout, pokazuje tylko zapytania, a nie wartości wiązania.

Pomysł został skradziony z burtbeck z wpisem, który przeczytałem kilka lat temu, którego nie mogę teraz znaleźć. Został zredagowany do pracy z Grails 3.3.

Podobnej techniki można użyć do włączenia logowania dla określonych testów integracyjnych:

class SomeIntegrationSpec extends IntegrationSpec {

    def sessionFactory

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

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

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

Spowoduje to włączenie logowania sql tylko dla testów w tym jednym pliku.

oparzenia
źródło