import org.sonar.core.persistence.dialect.Dialect;
import org.sonar.core.persistence.dialect.DialectUtils;
import org.sonar.core.persistence.dialect.H2;
-import org.sonar.core.persistence.dialect.Oracle;
-import org.sonar.core.persistence.dialect.PostgreSql;
+import org.sonar.core.persistence.profiling.PersistenceProfiling;
import org.sonar.jpa.session.CustomHibernateConnectionProvider;
import javax.sql.DataSource;
datasource = (BasicDataSource) BasicDataSourceFactory.createDataSource(extractCommonsDbcpProperties(properties));
datasource.setConnectionInitSqls(dialect.getConnectionInitStatements());
datasource.setValidationQuery(dialect.getValidationQuery());
+ datasource = PersistenceProfiling.addProfilingIfNeeded(datasource, settings);
}
private void checkConnection() {
import org.sonar.core.notification.db.NotificationQueueDto;
import org.sonar.core.notification.db.NotificationQueueMapper;
import org.sonar.core.permission.*;
-import org.sonar.core.profiling.Profiling;
import org.sonar.core.properties.PropertiesMapper;
import org.sonar.core.properties.PropertyDto;
import org.sonar.core.purge.PurgeMapper;
* See http://www.mybatis.org/core/logging.html :
*/
private void configureLogback(Class<?>... mapperClasses) {
- Level level = Level.INFO;
- Profiling.Level profilingLevel = Profiling.Level.fromConfigString(settings.getString(Profiling.CONFIG_PROFILING_LEVEL));
- if (profilingLevel == Profiling.Level.FULL) {
- level = Level.TRACE;
- }
for (Class mapperClass : mapperClasses) {
- logback.setLoggerLevel(mapperClass.getName(), level);
+ logback.setLoggerLevel(mapperClass.getName(), Level.INFO);
}
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.persistence.profiling;
+
+import org.apache.commons.dbcp.BasicDataSource;
+import org.sonar.api.config.Settings;
+import org.sonar.core.profiling.Profiling;
+
+/**
+ * @since 4.2
+ */
+public final class PersistenceProfiling {
+
+ private PersistenceProfiling() {
+ // Static stuff only
+ }
+
+ public static BasicDataSource addProfilingIfNeeded(BasicDataSource datasource, Settings settings) {
+ Profiling.Level profilingLevel = Profiling.Level.fromConfigString(settings.getString(Profiling.CONFIG_PROFILING_LEVEL));
+ if (profilingLevel == Profiling.Level.FULL) {
+ return new ProfilingDataSource(datasource);
+ } else {
+ return datasource;
+ }
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.persistence.profiling;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.Statement;
+
+class ProfilingConnectionHandler implements InvocationHandler {
+
+ private final Connection connection;
+
+ ProfilingConnectionHandler(Connection connection) {
+ this.connection = connection;
+ }
+
+ @Override
+ public Object invoke(Object target, Method method, Object[] args) throws Throwable {
+ Object result = method.invoke(connection, args);
+ if ("prepareStatement".equals(method.getName())) {
+ PreparedStatement statement = (PreparedStatement) result;
+ String sql = (String) args[0];
+ return Proxy.newProxyInstance(ProfilingConnectionHandler.class.getClassLoader(), new Class[] { PreparedStatement.class }, new ProfilingPreparedStatementHandler(statement, sql));
+
+ } else if ("createStatement".equals(method.getName())) {
+ Statement statement = (Statement) result;
+ return Proxy.newProxyInstance(ProfilingConnectionHandler.class.getClassLoader(), new Class[] { Statement.class }, new ProfilingStatementHandler(statement));
+
+ } else {
+ return result;
+ }
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.persistence.profiling;
+
+import org.apache.commons.dbcp.BasicDataSource;
+
+import java.io.PrintWriter;
+import java.lang.reflect.Proxy;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Collection;
+
+class ProfilingDataSource extends BasicDataSource {
+
+ private final BasicDataSource delegate;
+
+ public ProfilingDataSource(BasicDataSource delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public boolean getDefaultAutoCommit() {
+ return delegate.getDefaultAutoCommit();
+ }
+
+ @Override
+ public void setDefaultAutoCommit(boolean defaultAutoCommit) {
+ delegate.setDefaultAutoCommit(defaultAutoCommit);
+ }
+
+ @Override
+ public boolean getDefaultReadOnly() {
+ return delegate.getDefaultReadOnly();
+ }
+
+ @Override
+ public void setDefaultReadOnly(boolean defaultReadOnly) {
+ delegate.setDefaultReadOnly(defaultReadOnly);
+ }
+
+ @Override
+ public int getDefaultTransactionIsolation() {
+ return delegate.getDefaultTransactionIsolation();
+ }
+
+ @Override
+ public void setDefaultTransactionIsolation(int defaultTransactionIsolation) {
+ delegate.setDefaultTransactionIsolation(defaultTransactionIsolation);
+ }
+
+ @Override
+ public String getDefaultCatalog() {
+ return delegate.getDefaultCatalog();
+ }
+
+ @Override
+ public void setDefaultCatalog(String defaultCatalog) {
+ delegate.setDefaultCatalog(defaultCatalog);
+ }
+
+ @Override
+ public synchronized String getDriverClassName() {
+ return delegate.getDriverClassName();
+ }
+
+ @Override
+ public synchronized void setDriverClassName(String driverClassName) {
+ delegate.setDriverClassName(driverClassName);
+ }
+
+ @Override
+ public synchronized ClassLoader getDriverClassLoader() {
+ return delegate.getDriverClassLoader();
+ }
+
+ @Override
+ public synchronized void setDriverClassLoader(ClassLoader driverClassLoader) {
+ delegate.setDriverClassLoader(driverClassLoader);
+ }
+
+ @Override
+ public synchronized int getMaxActive() {
+ return delegate.getMaxActive();
+ }
+
+ @Override
+ public synchronized void setMaxActive(int maxActive) {
+ delegate.setMaxActive(maxActive);
+ }
+
+ @Override
+ public synchronized int getMaxIdle() {
+ return delegate.getMaxIdle();
+ }
+
+ @Override
+ public synchronized void setMaxIdle(int maxIdle) {
+ delegate.setMaxIdle(maxIdle);
+ }
+
+ @Override
+ public synchronized int getMinIdle() {
+ return delegate.getMinIdle();
+ }
+
+ @Override
+ public synchronized void setMinIdle(int minIdle) {
+ delegate.setMinIdle(minIdle);
+ }
+
+ @Override
+ public synchronized int getInitialSize() {
+ return delegate.getInitialSize();
+ }
+
+ @Override
+ public synchronized void setInitialSize(int initialSize) {
+ delegate.setInitialSize(initialSize);
+ }
+
+ @Override
+ public synchronized long getMaxWait() {
+ return delegate.getMaxWait();
+ }
+
+ @Override
+ public synchronized void setMaxWait(long maxWait) {
+ delegate.setMaxWait(maxWait);
+ }
+
+ @Override
+ public synchronized boolean isPoolPreparedStatements() {
+ return delegate.isPoolPreparedStatements();
+ }
+
+ @Override
+ public synchronized void setPoolPreparedStatements(boolean poolingStatements) {
+ delegate.setPoolPreparedStatements(poolingStatements);
+ }
+
+ @Override
+ public synchronized int getMaxOpenPreparedStatements() {
+ return delegate.getMaxOpenPreparedStatements();
+ }
+
+ @Override
+ public synchronized void setMaxOpenPreparedStatements(int maxOpenStatements) {
+ delegate.setMaxOpenPreparedStatements(maxOpenStatements);
+ }
+
+ @Override
+ public synchronized boolean getTestOnBorrow() {
+ return delegate.getTestOnBorrow();
+ }
+
+ @Override
+ public synchronized void setTestOnBorrow(boolean testOnBorrow) {
+ delegate.setTestOnBorrow(testOnBorrow);
+ }
+
+ @Override
+ public synchronized boolean getTestOnReturn() {
+ return delegate.getTestOnReturn();
+ }
+
+ @Override
+ public synchronized void setTestOnReturn(boolean testOnReturn) {
+ delegate.setTestOnReturn(testOnReturn);
+ }
+
+ @Override
+ public synchronized long getTimeBetweenEvictionRunsMillis() {
+ return delegate.getTimeBetweenEvictionRunsMillis();
+ }
+
+ @Override
+ public synchronized void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
+ delegate.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
+ }
+
+ @Override
+ public synchronized int getNumTestsPerEvictionRun() {
+ return delegate.getNumTestsPerEvictionRun();
+ }
+
+ @Override
+ public synchronized void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
+ delegate.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
+ }
+
+ @Override
+ public synchronized long getMinEvictableIdleTimeMillis() {
+ return delegate.getMinEvictableIdleTimeMillis();
+ }
+
+ @Override
+ public synchronized void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
+ delegate.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
+ }
+
+ @Override
+ public synchronized boolean getTestWhileIdle() {
+ return delegate.getTestWhileIdle();
+ }
+
+ @Override
+ public synchronized void setTestWhileIdle(boolean testWhileIdle) {
+ delegate.setTestWhileIdle(testWhileIdle);
+ }
+
+ @Override
+ public synchronized int getNumActive() {
+ return delegate.getNumActive();
+ }
+
+ @Override
+ public synchronized int getNumIdle() {
+ return delegate.getNumIdle();
+ }
+
+ @Override
+ public String getPassword() {
+ return delegate.getPassword();
+ }
+
+ @Override
+ public void setPassword(String password) {
+ delegate.setPassword(password);
+ }
+
+ @Override
+ public synchronized String getUrl() {
+ return delegate.getUrl();
+ }
+
+ @Override
+ public synchronized void setUrl(String url) {
+ delegate.setUrl(url);
+ }
+
+ @Override
+ public String getUsername() {
+ return delegate.getUsername();
+ }
+
+ @Override
+ public void setUsername(String username) {
+ delegate.setUsername(username);
+ }
+
+ @Override
+ public String getValidationQuery() {
+ return delegate.getValidationQuery();
+ }
+
+ @Override
+ public void setValidationQuery(String validationQuery) {
+ delegate.setValidationQuery(validationQuery);
+ }
+
+ @Override
+ public int getValidationQueryTimeout() {
+ return delegate.getValidationQueryTimeout();
+ }
+
+ @Override
+ public void setValidationQueryTimeout(int timeout) {
+ delegate.setValidationQueryTimeout(timeout);
+ }
+
+ @Override
+ public Collection getConnectionInitSqls() {
+ return delegate.getConnectionInitSqls();
+ }
+
+ @Override
+ public void setConnectionInitSqls(Collection connectionInitSqls) {
+ delegate.setConnectionInitSqls(connectionInitSqls);
+ }
+
+ @Override
+ public synchronized boolean isAccessToUnderlyingConnectionAllowed() {
+ return delegate.isAccessToUnderlyingConnectionAllowed();
+ }
+
+ @Override
+ public synchronized void setAccessToUnderlyingConnectionAllowed(boolean allow) {
+ delegate.setAccessToUnderlyingConnectionAllowed(allow);
+ }
+
+ @Override
+ public Connection getConnection() throws SQLException {
+ return (Connection) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] { Connection.class }, new ProfilingConnectionHandler(delegate.getConnection()));
+ }
+
+ @Override
+ public Connection getConnection(String user, String pass) throws SQLException {
+ return (Connection) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] { Connection.class }, new ProfilingConnectionHandler(delegate.getConnection(user, pass)));
+ }
+
+ @Override
+ public int getLoginTimeout() throws SQLException {
+ return delegate.getLoginTimeout();
+ }
+
+ @Override
+ public PrintWriter getLogWriter() throws SQLException {
+ return delegate.getLogWriter();
+ }
+
+ @Override
+ public void setLoginTimeout(int loginTimeout) throws SQLException {
+ delegate.setLoginTimeout(loginTimeout);
+ }
+
+ @Override
+ public void setLogWriter(PrintWriter logWriter) throws SQLException {
+ delegate.setLogWriter(logWriter);
+ }
+
+ @Override
+ public boolean getRemoveAbandoned() {
+ return delegate.getRemoveAbandoned();
+ }
+
+ @Override
+ public void setRemoveAbandoned(boolean removeAbandoned) {
+ delegate.setRemoveAbandoned(removeAbandoned);
+ }
+
+ @Override
+ public int getRemoveAbandonedTimeout() {
+ return delegate.getRemoveAbandonedTimeout();
+ }
+
+ @Override
+ public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) {
+ delegate.setRemoveAbandonedTimeout(removeAbandonedTimeout);
+ }
+
+ @Override
+ public boolean getLogAbandoned() {
+ return delegate.getLogAbandoned();
+ }
+
+ @Override
+ public void setLogAbandoned(boolean logAbandoned) {
+ delegate.setLogAbandoned(logAbandoned);
+ }
+
+ @Override
+ public void addConnectionProperty(String name, String value) {
+ delegate.addConnectionProperty(name, value);
+ }
+
+ @Override
+ public void removeConnectionProperty(String name) {
+ delegate.removeConnectionProperty(name);
+ }
+
+ @Override
+ public void setConnectionProperties(String connectionProperties) {
+ delegate.setConnectionProperties(connectionProperties);
+ }
+
+ @Override
+ public synchronized void close() throws SQLException {
+ delegate.close();
+ }
+
+ @Override
+ public synchronized boolean isClosed() {
+ return delegate.isClosed();
+ }
+
+ @Override
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+ return delegate.isWrapperFor(iface);
+ }
+
+ @Override
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ return delegate.unwrap(iface);
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.persistence.profiling;
+
+import org.sonar.core.profiling.StopWatch;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.sql.PreparedStatement;
+
+class ProfilingPreparedStatementHandler implements InvocationHandler {
+
+ private static final SqlProfiling profiling = new SqlProfiling();
+ private final PreparedStatement statement;
+ private final String sql;
+
+ ProfilingPreparedStatementHandler(PreparedStatement statement, String sql) {
+ this.statement = statement;
+ this.sql = sql;
+ }
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if (method.getName().startsWith("execute")) {
+ StopWatch watch = profiling.start();
+ Object result = method.invoke(statement, args);
+ profiling.stop(watch, sql);
+ return result;
+ } else {
+ return method.invoke(statement, args);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.persistence.profiling;
+
+import org.sonar.core.profiling.StopWatch;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.sql.Statement;
+
+class ProfilingStatementHandler implements InvocationHandler {
+
+ private static final SqlProfiling profiling = new SqlProfiling();
+ private final Statement statement;
+
+ ProfilingStatementHandler(Statement statement) {
+ this.statement = statement;
+ }
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if (method.getName().startsWith("execute")) {
+ StopWatch watch = profiling.start();
+ Object result = method.invoke(statement, args);
+ profiling.stop(watch, (String) args[0]);
+ return result;
+ } else {
+ return method.invoke(statement, args);
+ }
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.persistence.profiling;
+
+import org.sonar.api.config.Settings;
+import org.sonar.core.profiling.Profiling;
+import org.sonar.core.profiling.Profiling.Level;
+import org.sonar.core.profiling.StopWatch;
+
+class SqlProfiling {
+
+ private final Profiling profiling;
+
+ SqlProfiling() {
+ Settings settings = new Settings();
+ settings.setProperty(Profiling.CONFIG_PROFILING_LEVEL, Profiling.Level.FULL.toString());
+ profiling = new Profiling(settings);
+ }
+
+ StopWatch start() {
+ return profiling.start("sql", Level.FULL);
+ }
+
+ void stop(StopWatch watch, String sql) {
+ watch.stop(String.format("Executed SQL: %s", sql.replaceAll("\\s+", " ")));
+ }
+}
import org.apache.commons.dbcp.BasicDataSource;
import org.junit.Test;
import org.sonar.api.config.Settings;
-import org.sonar.core.persistence.dialect.Oracle;
import org.sonar.core.persistence.dialect.PostgreSql;
import java.util.Properties;
*/
package org.sonar.core.persistence;
-import ch.qos.logback.classic.Level;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.hamcrest.core.Is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
public class MyBatisTest {
private static H2Database database;
session.close();
}
}
-
- @Test
- public void log_sql_requests_and_responses() {
- Settings settings = new Settings()
- .setProperty("sonar.log.profilingLevel", "FULL");
-
- MyBatis myBatis = new MyBatis(database, settings, logback);
- myBatis.start();
-
- verify(logback).setLoggerLevel("org.sonar.core.resource.ResourceIndexerMapper", Level.TRACE);
- }
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.persistence.profiling;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.ContextBase;
+import ch.qos.logback.core.read.ListAppender;
+import org.apache.commons.dbcp.BasicDataSource;
+import org.junit.Test;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.config.Settings;
+import org.sonar.core.profiling.Profiling;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.Statement;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class PersistenceProfilingTest {
+
+ @Test
+ public void should_be_transparent_when_profiling_less_than_full() {
+ BasicDataSource datasource = mock(BasicDataSource.class);
+ assertThat(PersistenceProfiling.addProfilingIfNeeded(datasource , new Settings())).isEqualTo(datasource);
+ }
+
+ @Test
+ public void should_enable_profiling_when_profiling_is_full() throws Exception {
+ final Logger sqlLogger = (Logger) LoggerFactory.getLogger("sql");
+ ListAppender<ILoggingEvent> appender = new ListAppender<ILoggingEvent>();
+ appender.setContext(new ContextBase());
+ appender.start();
+ sqlLogger.addAppender(appender);
+
+ BasicDataSource originDataSource = mock(BasicDataSource.class);
+
+ Connection connection = mock(Connection.class);
+ when(originDataSource.getConnection()).thenReturn(connection);
+
+ String sql = "select 'polop' from dual;";
+
+ PreparedStatement preparedStatement = mock(PreparedStatement.class);
+ when(connection.prepareStatement(sql)).thenReturn(preparedStatement);
+ when(preparedStatement.execute()).thenReturn(true);
+
+ Statement statement = mock(Statement.class);
+ when(connection.createStatement()).thenReturn(statement);
+ when(statement.execute(sql)).thenReturn(true);
+
+ Settings settings = new Settings();
+ settings.setProperty(Profiling.CONFIG_PROFILING_LEVEL, Profiling.Level.FULL.toString());
+
+ BasicDataSource resultDataSource = PersistenceProfiling.addProfilingIfNeeded(originDataSource , settings);
+
+ assertThat(resultDataSource).isInstanceOf(ProfilingDataSource.class);
+ assertThat(resultDataSource.getUrl()).isNull();
+ assertThat(resultDataSource.getConnection().getClientInfo()).isNull();
+ PreparedStatement preparedStatementProxy = resultDataSource.getConnection().prepareStatement(sql);
+ assertThat(preparedStatementProxy.getConnection()).isNull();
+ assertThat(preparedStatementProxy.execute()).isTrue();
+ final Statement statementProxy = resultDataSource.getConnection().createStatement();
+ assertThat(statementProxy.getConnection()).isNull();
+ assertThat(statementProxy.execute(sql)).isTrue();
+
+ assertThat(appender.list).hasSize(2);
+ for (ILoggingEvent event: appender.list) {
+ assertThat(event.getLevel()).isEqualTo(Level.INFO);
+ assertThat(event.getFormattedMessage()).contains(sql);
+ }
+ }
+}
<!-- Display Rails warnings and errors -->
<logger name="rails">
- <level value="${RAILS_LOGGER_LEVEL}"/>
+ <level value="WARN"/>
</logger>
<logger name="org.hibernate.cache.ReadWriteCache">