Como registrar instruções SQL no Grails


86

Quero registrar no console ou em um arquivo todas as consultas que o Grails faz, para verificar o desempenho.

Eu havia configurado isso sem sucesso.

Qualquer ideia ajudaria.


Nenhuma das soluções fornecidas funcionou para mim. Estou escrevendo isso apenas para que todos saibam como estou desesperado.
Andrea

Respostas:


131

Configuração

datasource {
...
logSql = true
}

em DataSource.groovy (de acordo com essas instruções) foi o suficiente para fazê-lo funcionar em meu ambiente. Parece que partes do FAQ estão desatualizadas (por exemplo, a questão "as colunas de muitos para muitos ao contrário"), então isso também pode ser algo que mudou nesse meio tempo.


6
logSql=truesozinho não é suficiente. O registro de hibernação também deve ser ativado. Veja a resposta de @Pete.
Jason

2
Percebi que isso não inclui os valores que vão nas instruções SQL onde os "?" S estão.
Jason

1
Isso funciona, mas para todas as consultas. Também é possível imprimir o sql gerado para um critério específico sem ter que definir logSql = true?
Agosto,

@Guus como posso imprimir o sql gerado para um critério específico?
biniam

@biniam_Ethiopia Pelo que eu sei, isso não é possível. Eu quero isso assim como é chato para depurar certas classes e não querer ver outras consultas também.
Agosto

91

Acho mais útil fazer o seguinte, que é permitir que o log do Hibernate registre o SQL junto com as variáveis ​​de ligação (para que você possa ver os valores passados ​​em suas chamadas e replicar facilmente o SQL em seu editor ou de outra forma).

No seu Config.groovy, adicione o seguinte ao seu bloco log4j:

log4j = {

    // Enable Hibernate SQL logging with param values
    trace 'org.hibernate.type'
    debug 'org.hibernate.SQL'
    //the rest of your logging config
    // ...
    }

8
Eu usei isso muitas vezes. Uma coisa a ser observada: a saída dos parâmetros é muito cara. Eu recomendaria fazer isso apenas na sua caixa de desenvolvimento.
John Gordon

2
Você também pode adicionar format_sql = trueno hibernatebloco do seu DataSource.groovypara uma saída bem formatada.
Gregor Petrin

1
Observação: isso registrará os parâmetros da cláusula where e os valores da coluna extraídos dos conjuntos de resultados da consulta. Para registrar apenas os parâmetros da cláusula where, usetrace 'org.hibernate.type.BasicBinder'
GreenGiant

Alguém sabe o equivalente para grails 3.3.8?
John Little

Por alguma razão, consultas sintaticamente inválidas (geradas pelo próprio Hibernate, infelizmente!) Não são registradas - todas as outras consultas são registradas ... Possivelmente um problema com o próprio Hibernate?
Janaka Bandara,

32

Para grails 3. *

Opção # 1 adicionar o seguinte a logback.groovy

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

ou

A opção 2 adiciona o seguinte ao dataSource no application.yml. No entanto, esta abordagem não registra os valores dos parâmetros

environments:
  local:
    dataSource:
        logSql: true
        formatSql: true

17

Experimente isto:

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

Ele evita os problemas de desempenho do log de rastreamento do typepacote Hibernate . Isso funciona com o Hibernate 3.6 e superior. Peguei isso em: https://burtbeckwith.com/blog/?p=1604


6

A solução é apenas para desenvolvimento, não produção.

Todas as respostas acima funcionam e estão corretas. Mas eles não mostram a consulta completa de uma forma legível por humanos. Se quiser ver a consulta final (sem nenhum?,?), Você tem duas opções.

A) proxy sua conexão jdbc com log4jdbc ou p6Spy.

B) olhe para ele no nível do banco de dados. Por exemplo, muito fácil de fazer com o mysql.

Descubra onde você está general_log_file. Registro geral ativo se não estiver ativado.

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

Agora tudo está registrado em seu arquivo de log. Exemplo de Mac / Linux para mostrar um bom fluxo de suas consultas.

tail -f path_to_log_file 

3

Puro apenas para referência, mas eu uso p6spy para registrar as consultas SQL. É um pequeno driver jdbc intermediário. A consulta exata é registrada como seria enviada ao servidor (com parâmetros incluídos).

inclua-o em seu projeto:

runtime 'p6spy:p6spy:3.0.0'

Altere o driver da fonte de dados:

driverClassName: com.p6spy.engine.spy.P6SpyDriver

E seu url jdbc:

url: jdbc:p6spy:mysql://

Configure-o usando spy.properties (em 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

Não se esqueça de desabilitar isso para produção!


2

Próximo funciona para mim:

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

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


1

Eu sei que isso foi perguntado e respondido há muito tempo. Mas aconteceu de eu ver esta pergunta e não pude deixar de responder ou compartilhar nossa abordagem de implementação de log sql em nosso projeto. Espero que seja de alguma ajuda.

Atualmente está em ambiente de desenvolvimento. Estamos usando o "log4jdbc Driver Spy" para registrar o sql.

Configuração:

Em seu BuildConfig.groovy: adicione as dependências abaixo:

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

E em seu DataSource ou outra configuração relacionada: [onde quer que você tenha definido a configuração relacionada à fonte de dados], adicione:

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'

}

Pela minha experiência pessoal, achei bastante útil e útil durante a depuração. Também mais informações você pode encontrar neste site. https://code.google.com/p/log4jdbc-remix/

Rei Atenciosamente


0

Para um determinado bloco de código, também podemos criar um método que aceite um encerramento. por exemplo.

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

0

Se você tiver o plugin do console instalado, você pode obter o registro do sql com este pequeno trecho de código.

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

Esta é uma variação de muitas das soluções acima, mas permite que você ajuste o valor em tempo de execução. E assim como as outras soluções que lidam com logToStdoutisso só mostra as consultas e não os valores de bind.

A ideia foi roubada de uma postagem burtbeckwith que li há alguns anos e não consigo encontrar agora. Ele foi editado para funcionar com grails 3.3.

Uma técnica semelhante pode ser usada para ativar o registro para testes de integração específicos:

class SomeIntegrationSpec extends IntegrationSpec {

    def sessionFactory

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

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

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

Isso ativará o log de sql apenas para os testes neste arquivo.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.