Changelog is moved to datasource-proxy User Guide(Current). (Snapshot documentation is here)
-
QueryLoggingListeners(Commons, SLF4J, JUL) added overridable
loggingConditioncallback(boolean supplier) that simply decides whether to skip entire logging logic based on the current log level set on its logger.
e.g.: whenSLF4JQueryLoggingListenerwrites SQL in DEBUG level, but the logger is set to INFO(more serious than DEBUG), then it will NOT perform logging logic including constructing log statement, etc. -
Proxying
ResultSetis refactored to align how other proxies are managed.
Also, existing resultset-proxy is renamed toRepeatableReadResultSetProxyLogic.
As part of refactoring,ResultSetProxyJdbcProxyFactoryis removed.
To enable proxyingResultSet,ProxyDataSourceBuildernow has#proxyResultSet()and#repeatableReadResultSet()methods.// before builder.jdbcProxyFactory(new ResultSetProxyJdbcProxyFactory()).build(); // new builder.repeatableReadResultSet().build(); // or builder.proxyResultSet(new RepeatableReadResultSetProxyFactory()).build();
-
ProxyConfigis added to represent all proxy related configurations (datasource name, listeners, proxy factory, connection id manager). All values onInterceptorHolderare moved toProxyConfigandInterceptorHolderclass is removed. -
MethodExecutionListeneris added.
MethodExecutionListeneris a new type of listener that intercepts JDBC API calls:Connection,Statement,PreparedStatement,CallableStatement: All methodsResultSet: All methods when result set proxy is enabled. (ProxyDataSourceBuilder#[proxyResultSet()|repeatableReadResultSet()])ProxyDataSource:getConnection()method
listeners can be registered via
ProxyDataSourceBuilder#methodListener().builder.methodListener(myMethodListener).build();
-
ProxyDataSourceBuilderhas addedbeforeMethod(),afterMethod(),beforeQuery(), andafterQuery()methods.
These methods help inlining listener definitions especially with Java8 Lambda expression.ProxyDataSourceBuilder .create(actualDataSource) .name("MyDS") .proxyResultSet() // apply listener on resultset // register MethodExecutionListener .afterMethod(executionContext -> { Method method = executionContext.getMethod(); Class<?> targetClass = executionContext.getTarget().getClass(); System.out.println(targetClass.getSimpleName() + "#" + method.getName()); }) // register QueryExecutionListener .afterQuery((execInfo, queryInfoList) -> { System.out.println("Query took " + execInfo.getElapsedTime() + "msec"); }) .build();
sample output:
# code: Connection conn = ds.getConnection(); PreparedStatement ps = conn.prepareStatement("INSERT INTO users (id, name) VALUES (?, ?)"); ps.setString(2, "FOO"); ps.setInt(1, 3); ps.addBatch(); ps.setInt(1, 4); ps.setString(2, "BAR"); ps.addBatch(); ps.executeBatch(); ps.close(); conn.close(); # output: ProxyDataSource#getConnection JDBCConnection#prepareStatement JDBCPreparedStatement#setString JDBCPreparedStatement#setInt JDBCPreparedStatement#addBatch JDBCPreparedStatement#setInt JDBCPreparedStatement#setString JDBCPreparedStatement#addBatch JDBCPreparedStatement#executeBatch Query took 1msec JDBCPreparedStatement#close JDBCConnection#close
-
Assign connection ID on each connection
When a connection is obtained from DataSource(DataSource.getConnection()), sequentially increasing unique number is assigned as its connection ID. (default implementation:DefaultConnectionIdManager)
The connection ID is printed asConnectionin logging. -
Remove methods that don't take
dataSourceNameonJdbcProxyFactory
Instead, you need to specifynull, empty String, or datasource name to thedataSourceNameparameter. Following methods are removed:Connection createConnection(Connection connection, InterceptorHolder interceptorHolder);Statement createStatement(Statement statement, InterceptorHolder interceptorHolder);PreparedStatement createPreparedStatement(PreparedStatement preparedStatement, String query, InterceptorHolder interceptorHolder);
-
DataSourceQueryCountListenernow takes a strategy to resolveQueryCount.
Default usesThreadQueryCountHolderthat uses thread local to holdQueryCount. This behaves same as before that theQueryCountholds per request counts(servlet request-response lifecycle).
SingleQueryCountHolderuses single instance to hold count values. Therefore, this holds total accumulated values from all threads. -
Update
SlowQueryListenerto use daemon threads as default. It is configurable bySlowQueryListener#setUseDaemonThreadmethod.
-
Add
setLog/setLoggerto{Commons|SLF4J|JUL}QueryLoggingListenerto allow users to set custom logger.
Also added getters as well. -
Update
~QueryCountLoggingServletFilterto allow configuring logger by name -
Add query count logging implementation for JUL(Java Util Logging)
JULQueryCountLoggingHandlerInterceptorJULQueryCountLoggingRequestListenerJULQueryCountLoggingServletFilter
-
Fix writing log with
nullin parameter set methods. (e.g:setString(1, null);) -
Add
SlowQueryListenerthat triggers callback method when query takes longer than specified threshold time.
Also, added slow query logging listeners:CommonsSlowQueryListenerJULSlowQueryListenerSLF4JSlowQueryListenerSystemOutSlowQueryListener
In
ProxyDataSourceBuilder, these methods are added:logSlowQueryByCommons()logSlowQueryByJUL()logSlowQueryBySlf4j()logSlowQueryToSysOut()
-
Add support to easily apply formatters on each query for logging.
DefaultQueryLogEntryCreator#formatQuery()method has added.
Subclass can override this method to provides formatted query.Example with
BasicFormatterImplin Hibernate.// set this instance to logging listeners public class PrettyQueryEntryCreator extends DefaultQueryLogEntryCreator { private Formatter formatter = FormatStyle.BASIC.getFormatter(); // from hibernate @Override protected String formatQuery(String query) { return this.formatter.format(query); } }
-
Add multiline output support for query logging.
DefaultQueryLogEntryCreatornow hassetMultiline()method, andProxyDataSourceBuilderalso has addedmultiline()method.
When multiline is enabled, logged query entries become multi lined.sample log output:
Name:MyDS, Time:0, Success:True Type:Prepared, Batch:True, QuerySize:1, BatchSize:2 Query:["INSERT INTO users (id, name) VALUES (?, ?)"] Params:[(1,foo),(2,bar)]set up with builder:
DataSource dataSource = ProxyDataSourceBuilder .create(actualDataSource) .logQueryByCommons(INFO) .logSlowQueryByCommons(10, TimeUnit.MINUTES) .multiline() // applies to both query logger and slow query logger .build();
-
Deprecate
{Commons|SLF4J|JUL}QueryLoggingListener#resetLogger()methods.
Use newly addedsetLog(String)orsetLogger(String)method instead.
-
Move logging related listeners to sub package
- from
net.ttddyy.dsproxy.listenertonet.ttddyy.dsproxy.listener.logging
- from
-
classes for logging entry creation has been updated
QueryLogEntryCreator#getLogEntryAsJsonhas removed.- JSON style log entry creators is pulled up to
DefaultJsonQueryLogEntryCreator - To use JSON style logging, you can set the
QueryLogEntryCreatorto[Commons|SLF4J|JUL|SystemOut]QueryLoggingListener#setQueryLogEntryCreator() OracleOutputParameterLogEntryCreatorhas been split toOutputParameterLogEntryCreatorandOutputParameterJsonLogEntryCreator
-
DefaultQueryLogEntryCreator#writeParamsForSingleEntry()has split towriteParamsEntryForSinglePreparedEntry()andwriteParamsForSingleCallableEntry() -
Do not include parameter index for logging prepared statement.
Before(v1.3.3):
..., Params:[(1=10,2=foo),(1=20,2=bar)] ..., Params:[(1=30,2=FOO),(1=40,2=BAR)]..., "params":[{"1":"10","2":"foo"},{"1":"20","2":"bar"}]} ..., "params":[{"1":"30","2":"FOO"},{"1":"40","2":"BAR"}]}
Now:
..., Params:[(10,foo),(20,bar)] ..., Params:[(30,FOO),(40,BAR)]..., "params":[["10","foo"],["20","bar"]]} ..., "params":[["30","FOO"],["40","BAR"]]}
-
Add
JULQueryLoggingListenerwhich uses JUL(Java Utils Logging) to log executed queries -
Update logging for
setNullandregisterOutParameterto include sqltype e.g.:NULL(VARCHAR),OUTPUT(VARCHAR[12]) -
ResultSetProxyJdbcProxyFactoryto create a proxyResultSetthat can be consumed more than once. Thanks Liam Williams for this contribution!! -
QueryExecutionListenerreceives same instance ofExecutionInfoinbeforeQueryandafterQuerymethods
- update
DefaultQueryLogEntryCreatorto allow subclasses to override log entry details
- add
CommonsOracleOutputParameterLoggingListener - add new listener for oracle to log output params.
CommonsOracleOutputParameterLoggingListener
- make logger name configurable in
CommonsQueryLoggingListenerandSLF4JQueryLoggingListener setNullandregisterOutParameterreceives descriptive string value inQueryInfo#getQueryArgsList(temporal implementation)ExecutionInfowill have access to the statement/prepared/callable object used by the execution
-
update minimum jdk to java6+
-
add java8 new jdbc API (JDBC 4.2)
-
new JNDI support class:
ProxyDataSourceObjectFactory -
new fluent API builder:
ProxyDataSourceBuilder -
logging:
- update log format
- add json format
- more entries: statement-type, batch, batch-size
- new logger for System.Out
-
change metric names:
call => total, elapsedTime => time, added success, failure, etc. -
rename
~QueryCountLoggingFilterto~QueryCountServletFilter -
remove deprecated methods
- fixed prepared statement getting already executed queries in listener (Issue #9)
- QueryTransformer and ParameterTransformer for query and parameter replacement