Repository: tomee Updated Branches: refs/heads/tomee-1.7.x d0b7ae237 -> a0e6ad472
TOMEE-1528 LogSqlPackages config Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/a0e6ad47 Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/a0e6ad47 Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/a0e6ad47 Branch: refs/heads/tomee-1.7.x Commit: a0e6ad472009bcc5f2fdb8500a312e29a3d79e79 Parents: d0b7ae2 Author: Romain Manni-Bucau <[email protected]> Authored: Wed Mar 18 17:43:38 2015 +0100 Committer: Romain Manni-Bucau <[email protected]> Committed: Wed Mar 18 17:43:38 2015 +0100 ---------------------------------------------------------------------- .../resource/jdbc/DataSourceFactory.java | 31 +++--- .../logging/LoggingCallableSqlStatement.java | 4 +- .../logging/LoggingPreparedSqlStatement.java | 6 +- .../jdbc/logging/LoggingSqlConnection.java | 12 ++- .../jdbc/logging/LoggingSqlDataSource.java | 8 +- .../jdbc/logging/LoggingSqlStatement.java | 8 +- .../jdbc/logging/TimeWatcherExecutor.java | 21 ++++ .../managed/JTADataSourceWrapperFactory.java | 7 +- .../resource/jdbc/logging/LoggingSqlTest.java | 103 +++++++++++++++++++ 9 files changed, 171 insertions(+), 29 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/a0e6ad47/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java index e68c2c1..6f4f113 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java @@ -42,6 +42,7 @@ import javax.sql.DataSource; import javax.sql.XADataSource; import java.io.Flushable; import java.io.IOException; +import java.io.Serializable; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.sql.Driver; @@ -62,8 +63,10 @@ public class DataSourceFactory { private static final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB, DataSourceFactory.class); public static final String LOG_SQL_PROPERTY = "LogSql"; + public static final String LOG_SQL_PACKAGE_PROPERTY = "LogSqlPackages"; public static final String FLUSHABLE_PROPERTY = "Flushable"; public static final String GLOBAL_LOG_SQL_PROPERTY = "openejb.jdbc.log"; + public static final String GLOBAL_LOG_SQL_PACKAGE_PROPERTY = "openejb.jdbc.log.packages"; public static final String GLOBAL_FLUSH_PROPERTY = "openejb.jdbc.flushable"; public static final String POOL_PROPERTY = "openejb.datasource.pool"; public static final String DATA_SOURCE_CREATOR_PROP = "DataSourceCreator"; @@ -89,15 +92,15 @@ public class DataSourceFactory { final Properties properties = asProperties(definition); final boolean flushable = SystemInstance.get().getOptions().get(GLOBAL_FLUSH_PROPERTY, - "true".equalsIgnoreCase((String) properties.remove(FLUSHABLE_PROPERTY))); + "true".equalsIgnoreCase((String) properties.remove(FLUSHABLE_PROPERTY))); final FlushableDataSourceHandler.FlushConfig flushConfig; if (flushable) { properties.remove("flushable"); // don't let it wrap the delegate again flushConfig = new FlushableDataSourceHandler.FlushConfig( - name, configuredManaged, - impl, PropertiesHelper.propertiesToString(properties), - maxWaitTime, timeBetweenEvictionRuns, minEvictableIdleTime); + name, configuredManaged, + impl, PropertiesHelper.propertiesToString(properties), + maxWaitTime, timeBetweenEvictionRuns, minEvictableIdleTime); } else { flushConfig = null; } @@ -133,7 +136,8 @@ public class DataSourceFactory { } final boolean logSql = SystemInstance.get().getOptions().get(GLOBAL_LOG_SQL_PROPERTY, - "true".equalsIgnoreCase((String) properties.remove(LOG_SQL_PROPERTY))); + "true".equalsIgnoreCase((String) properties.remove(LOG_SQL_PROPERTY))); + final String logPackages = SystemInstance.get().getProperty(GLOBAL_LOG_SQL_PACKAGE_PROPERTY, (String) properties.remove(LOG_SQL_PACKAGE_PROPERTY)); final DataSourceCreator creator = creator(properties.remove(DATA_SOURCE_CREATOR_PROP), logSql); boolean useContainerLoader = "true".equalsIgnoreCase(SystemInstance.get().getProperty("openejb.resources.use-container-loader", "true")) && (impl == null || impl.getClassLoader() == DataSourceFactory.class.getClassLoader()); @@ -203,7 +207,7 @@ public class DataSourceFactory { } if (logSql) { - ds = makeItLogging(ds); + ds = makeItLogging(ds, logPackages); } if (flushable) { ds = makeFlushable(ds, flushConfig); @@ -247,18 +251,19 @@ public class DataSourceFactory { private static CommonDataSource makeFlushable(final CommonDataSource ds, final FlushableDataSourceHandler.FlushConfig flushConfig) { return (CommonDataSource) Proxy.newProxyInstance( - Thread.currentThread().getContextClassLoader(), - new Class<?>[]{DataSource.class.isInstance(ds) ? DataSource.class : XADataSource.class, Flushable.class}, - new FlushableDataSourceHandler(ds, flushConfig)); + Thread.currentThread().getContextClassLoader(), + new Class<?>[]{DataSource.class.isInstance(ds) ? DataSource.class : XADataSource.class, Flushable.class, Serializable.class}, + new FlushableDataSourceHandler(ds, flushConfig)); } public static void setCreatedWith(final DataSourceCreator creator, final CommonDataSource ds) { creatorByDataSource.put(ds, creator); } - public static DataSource makeItLogging(final CommonDataSource ds) { + public static DataSource makeItLogging(final CommonDataSource ds, final String packagesStr) { + final String[] pck = packagesStr == null ? null : packagesStr.split(" *, *"); return (DataSource) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), - new Class<?>[]{DataSource.class}, new LoggingSqlDataSource(ds)); + new Class<?>[]{DataSource.class, Serializable.class}, new LoggingSqlDataSource(ds, pck)); } private static void normalizeJdbcUrl(final Properties properties) { @@ -307,7 +312,7 @@ public class DataSourceFactory { final DataSourceCreator defaultCreator = SystemInstance.get().getComponent(DataSourceCreator.class); final ClassLoader loader = Thread.currentThread().getContextClassLoader(); if (creatorName != null && creatorName instanceof String - && (defaultCreator == null || !creatorName.equals(defaultCreator.getClass().getName()))) { + && (defaultCreator == null || !creatorName.equals(defaultCreator.getClass().getName()))) { String clazz = KNOWN_CREATORS.get(creatorName); if (clazz == null) { clazz = (String) creatorName; @@ -340,7 +345,7 @@ public class DataSourceFactory { final String initialPoolSize = properties.getProperty("initialPoolSize"); final String maxPoolSize = properties.getProperty("maxPoolSize"); if ((null == initialPoolSize || "-1".equals(initialPoolSize)) - && ("-1".equals(maxPoolSize) || maxPoolSize == null)) { + && ("-1".equals(maxPoolSize) || maxPoolSize == null)) { property = "false"; } } http://git-wip-us.apache.org/repos/asf/tomee/blob/a0e6ad47/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingCallableSqlStatement.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingCallableSqlStatement.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingCallableSqlStatement.java index 6945a66..4bc42ad 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingCallableSqlStatement.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingCallableSqlStatement.java @@ -20,8 +20,8 @@ package org.apache.openejb.resource.jdbc.logging; import java.sql.PreparedStatement; public class LoggingCallableSqlStatement extends LoggingPreparedSqlStatement { - public LoggingCallableSqlStatement(final PreparedStatement result, final String query) { - super(result, query); + public LoggingCallableSqlStatement(final PreparedStatement result, final String query, final String[] debugPackages) { + super(result, query, debugPackages); } // TODO: manage in/out parameters http://git-wip-us.apache.org/repos/asf/tomee/blob/a0e6ad47/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingPreparedSqlStatement.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingPreparedSqlStatement.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingPreparedSqlStatement.java index 3731684..9500366 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingPreparedSqlStatement.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingPreparedSqlStatement.java @@ -36,12 +36,14 @@ public class LoggingPreparedSqlStatement implements InvocationHandler { private final PreparedStatement delegate; private final String sql; private final List<Parameter> parameters = new ArrayList<Parameter>(); + private final String[] packages; private int parameterIndex; - public LoggingPreparedSqlStatement(final PreparedStatement result, final String query) { + public LoggingPreparedSqlStatement(final PreparedStatement result, final String query, final String[] debugPackages) { delegate = result; sql = query; parameterIndex = 0; + packages = debugPackages; } @Override @@ -112,7 +114,7 @@ public class LoggingPreparedSqlStatement implements InvocationHandler { } } } - LOGGER.info(result.format(str)); + LOGGER.info(result.format(str) + (packages != null ? " - stack:" + TimeWatcherExecutor.inlineStack(packages) : "")); } else if ("clearParameters".equals(mtdName)) { parameters.clear(); parameterIndex = 0; http://git-wip-us.apache.org/repos/asf/tomee/blob/a0e6ad47/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlConnection.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlConnection.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlConnection.java index 3c33c24..74ad1d6 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlConnection.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlConnection.java @@ -32,9 +32,11 @@ public class LoggingSqlConnection implements InvocationHandler { private static final Class<?>[] INTERFACES_CALLABLE = new Class<?>[]{CallableStatement.class}; private final Connection delegate; + private final String[] packages; - public LoggingSqlConnection(final Connection connection) { - delegate = connection; + public LoggingSqlConnection(final Connection connection, final String[] debugPackages) { + this.delegate = connection; + this.packages = debugPackages; } @Override @@ -50,17 +52,17 @@ public class LoggingSqlConnection implements InvocationHandler { if ("createStatement".equals(mtd)) { return Proxy.newProxyInstance(delegate.getClass().getClassLoader(), INTERFACES_STATEMENT, - new LoggingSqlStatement((Statement) result)); + new LoggingSqlStatement((Statement) result, packages)); } if ("prepareStatement".equals(mtd)) { return Proxy.newProxyInstance(delegate.getClass().getClassLoader(), INTERFACES_PREPARED, - new LoggingPreparedSqlStatement((PreparedStatement) result, (String) args[0])); + new LoggingPreparedSqlStatement((PreparedStatement) result, (String) args[0], packages)); } if ("prepareCall".equals(mtd)) { return Proxy.newProxyInstance(delegate.getClass().getClassLoader(), INTERFACES_CALLABLE, - new LoggingCallableSqlStatement((CallableStatement) result, (String) args[0])); + new LoggingCallableSqlStatement((CallableStatement) result, (String) args[0], packages)); } return result; http://git-wip-us.apache.org/repos/asf/tomee/blob/a0e6ad47/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlDataSource.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlDataSource.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlDataSource.java index 18a8ac0..8dbc3d7 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlDataSource.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlDataSource.java @@ -27,10 +27,12 @@ import java.sql.Connection; public class LoggingSqlDataSource implements InvocationHandler { private static final Class<?>[] INTERFACES = new Class<?>[]{Connection.class}; - private CommonDataSource delegate; + private final CommonDataSource delegate; + private final String[] packages; - public LoggingSqlDataSource(final CommonDataSource ds) { + public LoggingSqlDataSource(final CommonDataSource ds, final String[] debugPackages) { delegate = ds; + packages = debugPackages; } @Override @@ -44,7 +46,7 @@ public class LoggingSqlDataSource implements InvocationHandler { if ("getConnection".equals(method.getName())) { return Proxy.newProxyInstance(delegate.getClass().getClassLoader(), - INTERFACES, new LoggingSqlConnection((Connection) result)); + INTERFACES, new LoggingSqlConnection((Connection) result, packages)); } return result; } http://git-wip-us.apache.org/repos/asf/tomee/blob/a0e6ad47/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlStatement.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlStatement.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlStatement.java index 4a6d3a7..1c6b513 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlStatement.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlStatement.java @@ -28,9 +28,11 @@ public class LoggingSqlStatement implements InvocationHandler { private static final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB_SQL, LoggingSqlStatement.class); private final Statement delegate; + private final String[] packages; - public LoggingSqlStatement(final Statement result) { - delegate = result; + public LoggingSqlStatement(final Statement result, final String[] debugPackages) { + this.delegate = result; + this.packages = debugPackages; } @Override @@ -40,7 +42,7 @@ public class LoggingSqlStatement implements InvocationHandler { final TimeWatcherExecutor.TimerWatcherResult result = TimeWatcherExecutor.execute(method, delegate, args, execute); if (execute) { - LOGGER.info(result.format((String) args[0])); + LOGGER.info(result.format((String) args[0]) + (packages != null ? " - stack:" + TimeWatcherExecutor.inlineStack(packages) : "")); } if (result.getThrowable() != null) { http://git-wip-us.apache.org/repos/asf/tomee/blob/a0e6ad47/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/TimeWatcherExecutor.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/TimeWatcherExecutor.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/TimeWatcherExecutor.java index 2de1317..5bfea65 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/TimeWatcherExecutor.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/logging/TimeWatcherExecutor.java @@ -26,6 +26,27 @@ public final class TimeWatcherExecutor { // no-op } + public static String inlineStack(final String[] acceptedPackages) { + if (acceptedPackages == null) { + return ""; + } + + final Throwable t = new Exception().fillInStackTrace(); + final StringBuilder inlinedStack = new StringBuilder(); + for (final StackTraceElement elt : t.getStackTrace()) { + final String className = elt.getClassName(); + for (final String p : acceptedPackages) { + if (className.startsWith(p)) { + inlinedStack.append(" -> ") + .append(className).append('.') + .append(elt.getMethodName()).append(':').append(elt.getLineNumber()); + break; + } + } + } + return inlinedStack.toString(); + } + public static TimerWatcherResult execute(final Method mtd, final Object instance, final Object[] args, final boolean watch) { final long start = (watch) ? System.nanoTime() : 0; http://git-wip-us.apache.org/repos/asf/tomee/blob/a0e6ad47/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/JTADataSourceWrapperFactory.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/JTADataSourceWrapperFactory.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/JTADataSourceWrapperFactory.java index 4a849d5..48e29fc 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/JTADataSourceWrapperFactory.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/JTADataSourceWrapperFactory.java @@ -34,6 +34,7 @@ import javax.transaction.TransactionManager; public class JTADataSourceWrapperFactory { private String delegate = "datasource"; private boolean logSql; + private String logPackages; public CommonDataSource create() { final TransactionManager transactionManager = OpenEJB.getTransactionManager(); @@ -46,7 +47,7 @@ public class JTADataSourceWrapperFactory { } if (logSql) { - cds = DataSourceFactory.makeItLogging(cds); + cds = DataSourceFactory.makeItLogging(cds, logPackages); } return cds; } @@ -67,4 +68,8 @@ public class JTADataSourceWrapperFactory { public void setLogSql(final boolean logSql) { this.logSql = logSql; } + + public void setLogPackages(final String logPackages) { + this.logPackages = logPackages; + } } http://git-wip-us.apache.org/repos/asf/tomee/blob/a0e6ad47/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlTest.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlTest.java b/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlTest.java new file mode 100644 index 0000000..27a5e7f --- /dev/null +++ b/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/logging/LoggingSqlTest.java @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.openejb.resource.jdbc.logging; + +import org.apache.openejb.jee.WebApp; +import org.apache.openejb.junit.ApplicationComposer; +import org.apache.openejb.log.LoggerCreator; +import org.apache.openejb.testing.Configuration; +import org.apache.openejb.testing.Module; +import org.apache.openejb.testng.PropertiesBuilder; +import org.apache.openejb.util.JuliLogStream; +import org.apache.openejb.util.LogCategory; +import org.apache.openejb.util.Logger; +import org.apache.openejb.util.reflection.Reflections; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.util.Collection; +import java.util.LinkedList; +import java.util.Properties; +import java.util.logging.Handler; +import java.util.logging.LogRecord; +import javax.annotation.Resource; +import javax.sql.DataSource; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +@RunWith(ApplicationComposer.class) +public class LoggingSqlTest { + @Resource + private DataSource ds; + + @Module + public WebApp war() { + return new WebApp(); + } + + @Configuration + public Properties config() { + return new PropertiesBuilder() + .p("openejb.log.async", "false") + .p("db", "new://Resource?type=DataSource") + .p("db.LogSql", "true") + .p("db.LogSqlPackages", "org.apache.openejb.resource.jdbc.logging.LoggingSqlTest") + .build(); + } + + @Test + public void checkOutput() throws Exception { + final Logger logger = Logger.getInstance(LogCategory.OPENEJB_SQL, LoggingPreparedSqlStatement.class); + final JuliLogStream stream = JuliLogStream.class.cast(Reflections.get(logger, "logStream")); + final LoggerCreator julCreator = LoggerCreator.class.cast(Reflections.get(stream, "logger")); + final java.util.logging.Logger actualLogger = julCreator.call(); + final Collection<String> msgs = new LinkedList<String>(); + final Handler handler = new Handler() { + @Override + public void publish(final LogRecord record) { + msgs.add(record.getMessage()); + } + + @Override + public void flush() { + // no-op + } + + @Override + public void close() throws SecurityException { + // no-op + } + }; + actualLogger.addHandler(handler); + + final Connection c = ds.getConnection(); + final PreparedStatement preparedStatement = c.prepareStatement("select 1 from INFORMATION_SCHEMA.SYSTEM_USERS"); + preparedStatement.execute(); + preparedStatement.close(); + c.close(); + + actualLogger.removeHandler(handler); + assertEquals(1, msgs.size()); + + final String msg = msgs.iterator().next(); + assertTrue(msg.contains("select 1 from INFORMATION_SCHEMA.SYSTEM_USERS")); + assertTrue(msg.contains("stack: -> org.apache.openejb.resource.jdbc.logging.LoggingSqlTest.checkOutput:")); + } +}
