package net.ttddyy.dsproxy.support; import net.ttddyy.dsproxy.listener.DataSourceQueryCountListener; import net.ttddyy.dsproxy.listener.QueryExecutionListener; import net.ttddyy.dsproxy.listener.logging.CommonsLogLevel; import net.ttddyy.dsproxy.listener.logging.CommonsQueryLoggingListener; import net.ttddyy.dsproxy.listener.logging.CommonsSlowQueryListener; import net.ttddyy.dsproxy.listener.logging.DefaultJsonQueryLogEntryCreator; import net.ttddyy.dsproxy.listener.logging.DefaultQueryLogEntryCreator; import net.ttddyy.dsproxy.listener.logging.JULQueryLoggingListener; import net.ttddyy.dsproxy.listener.logging.JULSlowQueryListener; import net.ttddyy.dsproxy.listener.logging.SLF4JLogLevel; import net.ttddyy.dsproxy.listener.logging.SLF4JQueryLoggingListener; import net.ttddyy.dsproxy.listener.logging.SLF4JSlowQueryListener; import net.ttddyy.dsproxy.listener.logging.SystemOutQueryLoggingListener; import net.ttddyy.dsproxy.listener.logging.SystemOutSlowQueryListener; import net.ttddyy.dsproxy.transform.ParameterTransformer; import net.ttddyy.dsproxy.transform.QueryTransformer; import javax.sql.DataSource; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.logging.Level; /** * Builder for {@link net.ttddyy.dsproxy.support.ProxyDataSource}. * * @author Tadaya Tsuyukubo * @since 1.3 */ public class ProxyDataSourceBuilder { private DataSource dataSource; private String dataSourceName; // for building QueryLoggingListeners // CommonsQueryLoggingListener private boolean createCommonsQueryListener; private CommonsLogLevel commonsLogLevel; private String commonsLoggerName; // for SLF4JQueryLoggingListener private boolean createSlf4jQueryListener; private SLF4JLogLevel slf4jLogLevel; private String slf4jLoggerName; // for JULQueryLoggingListener private boolean createJulQueryListener; private Level julLogLevel; private String julLoggerName; // for SystemOutQueryLoggingListener private boolean createSysOutQueryListener; // For building SlowQueryListeners private long slowQueryThreshold; private TimeUnit slowQueryTimeUnit; // for CommonsSlowQueryListener private boolean createCommonsSlowQueryListener; private CommonsLogLevel commonsSlowQueryLogLevel; private String commonsSlowQueryLogName; // for SLF4JSlowQueryListener private boolean createSlf4jSlowQueryListener; private SLF4JLogLevel slf4jSlowQueryLogLevel; private String slf4jSlowQueryLoggerName; // for JULSlowQueryListener private boolean createJulSlowQueryListener; private Level julSlowQueryLogLevel; private String julSlowQueryLoggerName; // for SystemOutSlowQueryListener private boolean createSysOutSlowQueryListener; private boolean createDataSourceQueryCountListener; private boolean jsonFormat; private boolean multiline; private List<QueryExecutionListener> queryExecutionListeners = new ArrayList<QueryExecutionListener>(); private ParameterTransformer parameterTransformer; private QueryTransformer queryTransformer; public static ProxyDataSourceBuilder create() { return new ProxyDataSourceBuilder(); } public static ProxyDataSourceBuilder create(DataSource dataSource) { return new ProxyDataSourceBuilder(dataSource); } public static ProxyDataSourceBuilder create(String dataSourceName, DataSource dataSource) { return new ProxyDataSourceBuilder(dataSource).name(dataSourceName); } public ProxyDataSourceBuilder() { } public ProxyDataSourceBuilder(DataSource dataSource) { this.dataSource = dataSource; } /** * Set actual datasource. * * @param dataSource actual datasource * @return builder */ public ProxyDataSourceBuilder dataSource(DataSource dataSource) { this.dataSource = dataSource; return this; } /** * Register {@link CommonsQueryLoggingListener}. * * @return builder */ public ProxyDataSourceBuilder logQueryByCommons() { return logQueryByCommons(null, null); } /** * Register {@link CommonsQueryLoggingListener}. * * @param logLevel log level for commons * @return builder */ public ProxyDataSourceBuilder logQueryByCommons(CommonsLogLevel logLevel) { return logQueryByCommons(logLevel, null); } /** * Register {@link CommonsQueryLoggingListener}. * * @param commonsLoggerName commons logger name * @return builder * @since 1.3.1 */ public ProxyDataSourceBuilder logQueryByCommons(String commonsLoggerName) { return logQueryByCommons(null, commonsLoggerName); } /** * Register {@link CommonsQueryLoggingListener}. * * @param logLevel log level for commons * @param commonsLoggerName commons logger name * @return builder * @since 1.3.1 */ public ProxyDataSourceBuilder logQueryByCommons(CommonsLogLevel logLevel, String commonsLoggerName) { this.createCommonsQueryListener = true; this.commonsLogLevel = logLevel; this.commonsLoggerName = commonsLoggerName; return this; } /** * Register {@link CommonsSlowQueryListener}. * * @param thresholdTime slow query threshold time * @param timeUnit slow query threshold time unit * @return builder * @since 1.4.1 */ public ProxyDataSourceBuilder logSlowQueryByCommons(long thresholdTime, TimeUnit timeUnit) { return logSlowQueryByCommons(thresholdTime, timeUnit, null, null); } /** * Register {@link CommonsSlowQueryListener}. * * @param thresholdTime slow query threshold time * @param timeUnit slow query threshold time unit * @param logLevel log level for commons * @return builder * @since 1.4.1 */ public ProxyDataSourceBuilder logSlowQueryByCommons(long thresholdTime, TimeUnit timeUnit, CommonsLogLevel logLevel) { return logSlowQueryByCommons(thresholdTime, timeUnit, logLevel, null); } /** * Register {@link CommonsSlowQueryListener}. * * @param thresholdTime slow query threshold time * @param timeUnit slow query threshold time unit * @param logName commons logger name * @return builder * @since 1.4.1 */ public ProxyDataSourceBuilder logSlowQueryByCommons(long thresholdTime, TimeUnit timeUnit, String logName) { return logSlowQueryByCommons(thresholdTime, timeUnit, null, logName); } /** * Register {@link CommonsSlowQueryListener}. * * @param thresholdTime slow query threshold time * @param timeUnit slow query threshold time unit * @param logLevel log level for commons * @param logName commons logger name * @return builder * @since 1.4.1 */ public ProxyDataSourceBuilder logSlowQueryByCommons(long thresholdTime, TimeUnit timeUnit, CommonsLogLevel logLevel, String logName) { this.createCommonsSlowQueryListener = true; this.slowQueryThreshold = thresholdTime; this.slowQueryTimeUnit = timeUnit; this.commonsSlowQueryLogLevel = logLevel; this.commonsSlowQueryLogName = logName; return this; } /** * Register {@link SLF4JQueryLoggingListener}. * * @return builder */ public ProxyDataSourceBuilder logQueryBySlf4j() { return logQueryBySlf4j(null, null); } /** * Register {@link SLF4JQueryLoggingListener}. * * @param logLevel log level for slf4j * @return builder */ public ProxyDataSourceBuilder logQueryBySlf4j(SLF4JLogLevel logLevel) { return logQueryBySlf4j(logLevel, null); } /** * Register {@link SLF4JQueryLoggingListener}. * * @param slf4jLoggerName slf4j logger name * @return builder * @since 1.3.1 */ public ProxyDataSourceBuilder logQueryBySlf4j(String slf4jLoggerName) { return logQueryBySlf4j(null, slf4jLoggerName); } /** * Register {@link SLF4JQueryLoggingListener}. * * @param logLevel log level for slf4j * @param slf4jLoggerName slf4j logger name * @return builder * @since 1.3.1 */ public ProxyDataSourceBuilder logQueryBySlf4j(SLF4JLogLevel logLevel, String slf4jLoggerName) { this.createSlf4jQueryListener = true; this.slf4jLogLevel = logLevel; this.slf4jLoggerName = slf4jLoggerName; return this; } /** * Register {@link SLF4JSlowQueryListener}. * * @param thresholdTime slow query threshold time * @param timeUnit slow query threshold time unit * @return builder * @since 1.4.1 */ public ProxyDataSourceBuilder logSlowQueryBySlf4j(long thresholdTime, TimeUnit timeUnit) { return logSlowQueryBySlf4j(thresholdTime, timeUnit, null, null); } /** * Register {@link SLF4JSlowQueryListener}. * * @param thresholdTime slow query threshold time * @param timeUnit slow query threshold time unit * @param logLevel log level for slf4j * @return builder * @since 1.4.1 */ public ProxyDataSourceBuilder logSlowQueryBySlf4j(long thresholdTime, TimeUnit timeUnit, SLF4JLogLevel logLevel) { return logSlowQueryBySlf4j(thresholdTime, timeUnit, logLevel, null); } /** * Register {@link SLF4JSlowQueryListener}. * * @param thresholdTime slow query threshold time * @param timeUnit slow query threshold time unit * @param loggerName slf4j logger name * @return builder * @since 1.4.1 */ public ProxyDataSourceBuilder logSlowQueryBySlf4j(long thresholdTime, TimeUnit timeUnit, String loggerName) { return logSlowQueryBySlf4j(thresholdTime, timeUnit, null, loggerName); } /** * Register {@link SLF4JSlowQueryListener}. * * @param thresholdTime slow query threshold time * @param timeUnit slow query threshold time unit * @param logLevel log level for slf4j * @param loggerName slf4j logger name * @return builder * @since 1.4.1 */ public ProxyDataSourceBuilder logSlowQueryBySlf4j(long thresholdTime, TimeUnit timeUnit, SLF4JLogLevel logLevel, String loggerName) { this.createSlf4jSlowQueryListener = true; this.slowQueryThreshold = thresholdTime; this.slowQueryTimeUnit = timeUnit; this.slf4jSlowQueryLogLevel = logLevel; this.slf4jSlowQueryLoggerName = loggerName; return this; } /** * Register {@link JULQueryLoggingListener}. * * @return builder * @since 1.4 */ public ProxyDataSourceBuilder logQueryByJUL() { return logQueryByJUL(null, null); } /** * Register {@link JULQueryLoggingListener}. * * @param logLevel log level for JUL * @return builder * @since 1.4 */ public ProxyDataSourceBuilder logQueryByJUL(Level logLevel) { return logQueryByJUL(logLevel, null); } /** * Register {@link JULQueryLoggingListener}. * * @param julLoggerName JUL logger name * @return builder * @since 1.4 */ public ProxyDataSourceBuilder logQueryByJUL(String julLoggerName) { return logQueryByJUL(null, julLoggerName); } /** * Register {@link JULQueryLoggingListener}. * * @param logLevel log level for JUL * @param julLoggerName JUL logger name * @return builder * @since 1.4 */ public ProxyDataSourceBuilder logQueryByJUL(Level logLevel, String julLoggerName) { this.createJulQueryListener = true; this.julLogLevel = logLevel; this.julLoggerName = julLoggerName; return this; } /** * Register {@link JULSlowQueryListener}. * * @param thresholdTime slow query threshold time * @param timeUnit slow query threshold time unit * @return builder * @since 1.4.1 */ public ProxyDataSourceBuilder logSlowQueryByJUL(long thresholdTime, TimeUnit timeUnit) { return logSlowQueryByJUL(thresholdTime, timeUnit, null, null); } /** * Register {@link JULSlowQueryListener}. * * @param thresholdTime slow query threshold time * @param timeUnit slow query threshold time unit * @param logLevel log level for JUL * @return builder * @since 1.4.1 */ public ProxyDataSourceBuilder logSlowQueryByJUL(long thresholdTime, TimeUnit timeUnit, Level logLevel) { return logSlowQueryByJUL(thresholdTime, timeUnit, logLevel, null); } /** * Register {@link JULSlowQueryListener}. * * @param thresholdTime slow query threshold time * @param timeUnit slow query threshold time unit * @param loggerName JUL logger name * @return builder * @since 1.4.1 */ public ProxyDataSourceBuilder logSlowQueryByJUL(long thresholdTime, TimeUnit timeUnit, String loggerName) { return logSlowQueryByJUL(thresholdTime, timeUnit, null, loggerName); } /** * Register {@link JULSlowQueryListener}. * * @param thresholdTime slow query threshold time * @param timeUnit slow query threshold time unit * @param logLevel log level for JUL * @param loggerName JUL logger name * @return builder * @since 1.4.1 */ public ProxyDataSourceBuilder logSlowQueryByJUL(long thresholdTime, TimeUnit timeUnit, Level logLevel, String loggerName) { this.createJulSlowQueryListener = true; this.slowQueryThreshold = thresholdTime; this.slowQueryTimeUnit = timeUnit; this.julSlowQueryLogLevel = logLevel; this.julSlowQueryLoggerName = loggerName; return this; } /** * Register {@link SystemOutQueryLoggingListener}. * * @return builder */ public ProxyDataSourceBuilder logQueryToSysOut() { this.createSysOutQueryListener = true; return this; } /** * Register {@link SystemOutSlowQueryListener}. * * @return builder * @since 1.4.1 */ public ProxyDataSourceBuilder logSlowQueryToSysOut(long thresholdTime, TimeUnit timeUnit) { this.createSysOutSlowQueryListener = true; this.slowQueryThreshold = thresholdTime; this.slowQueryTimeUnit = timeUnit; return this; } /** * Create {@link net.ttddyy.dsproxy.listener.DataSourceQueryCountListener}. * * @return builder */ public ProxyDataSourceBuilder countQuery() { this.createDataSourceQueryCountListener = true; return this; } /** * Register given listener. * * @param listener a listener to register * @return builder */ public ProxyDataSourceBuilder listener(QueryExecutionListener listener) { this.queryExecutionListeners.add(listener); return this; } /** * Format logging output as JSON. * * @return builder */ public ProxyDataSourceBuilder asJson() { this.jsonFormat = true; return this; } /** * Set datasource name. * * @param dataSourceName datasource name * @return builder */ public ProxyDataSourceBuilder name(String dataSourceName) { this.dataSourceName = dataSourceName; return this; } /** * Register {@link net.ttddyy.dsproxy.transform.QueryTransformer}. * * @param queryTransformer a query-transformer to register * @return builder */ public ProxyDataSourceBuilder queryTransformer(QueryTransformer queryTransformer) { this.queryTransformer = queryTransformer; return this; } /** * Register {@link net.ttddyy.dsproxy.transform.ParameterTransformer}. * * @param parameterTransformer a query-parameter-transformer to register * @return builder */ public ProxyDataSourceBuilder parameterTransformer(ParameterTransformer parameterTransformer) { this.parameterTransformer = parameterTransformer; return this; } /** * Use multiline output for logging query. * * @return builder * @since 1.4.1 */ public ProxyDataSourceBuilder multiline() { this.multiline = true; return this; } public ProxyDataSource build() { ProxyDataSource proxyDataSource = new ProxyDataSource(); if (this.dataSource != null) { proxyDataSource.setDataSource(dataSource); } // DataSource Name if (this.dataSourceName != null) { proxyDataSource.setDataSourceName(dataSourceName); } // Query Logging Listeners List<QueryExecutionListener> listeners = new ArrayList<QueryExecutionListener>(); // query logging listeners if (this.createCommonsQueryListener) { listeners.add(buildCommonsQueryListener()); } if (this.createSlf4jQueryListener) { listeners.add(buildSlf4jQueryListener()); } if (this.createJulQueryListener) { listeners.add(buildJulQueryListener()); } if (this.createSysOutQueryListener) { listeners.add(buildSysOutQueryListener()); } // slow query logging listeners if (this.createCommonsSlowQueryListener) { listeners.add(buildCommonsSlowQueryListener()); } if (this.createSlf4jSlowQueryListener) { listeners.add(buildSlf4jSlowQueryListener()); } if (this.createJulSlowQueryListener) { listeners.add(buildJulSlowQueryListener()); } if (this.createSysOutSlowQueryListener) { listeners.add(buildSysOutSlowQueryListener()); } // countQuery listener if (this.createDataSourceQueryCountListener) { listeners.add(new DataSourceQueryCountListener()); } // explicitly added listeners listeners.addAll(this.queryExecutionListeners); for (QueryExecutionListener listener : listeners) { proxyDataSource.addListener(listener); } if (this.queryTransformer != null) { proxyDataSource.getInterceptorHolder().setQueryTransformer(this.queryTransformer); } if (this.parameterTransformer != null) { proxyDataSource.getInterceptorHolder().setParameterTransformer(this.parameterTransformer); } return proxyDataSource; } private CommonsQueryLoggingListener buildCommonsQueryListener() { CommonsQueryLoggingListener listener = new CommonsQueryLoggingListener(); if (this.commonsLogLevel != null) { listener.setLogLevel(this.commonsLogLevel); } if (this.commonsLoggerName != null && !this.commonsLoggerName.isEmpty()) { listener.setLog(this.commonsLoggerName); } if (this.jsonFormat) { listener.setQueryLogEntryCreator(new DefaultJsonQueryLogEntryCreator()); } if (this.multiline) { listener.setQueryLogEntryCreator(buildMultilineQueryLogEntryCreator()); } return listener; } private CommonsSlowQueryListener buildCommonsSlowQueryListener() { CommonsSlowQueryListener listener = new CommonsSlowQueryListener(this.slowQueryThreshold, this.slowQueryTimeUnit); if (this.commonsSlowQueryLogLevel != null) { listener.setLogLevel(this.commonsSlowQueryLogLevel); } if (this.commonsSlowQueryLogName != null) { listener.setLog(this.commonsSlowQueryLogName); } if (this.multiline) { listener.setQueryLogEntryCreator(buildMultilineQueryLogEntryCreator()); } return listener; } private SLF4JQueryLoggingListener buildSlf4jQueryListener() { SLF4JQueryLoggingListener listener = new SLF4JQueryLoggingListener(); if (this.slf4jLogLevel != null) { listener.setLogLevel(this.slf4jLogLevel); } if (this.slf4jLoggerName != null && !this.slf4jLoggerName.isEmpty()) { listener.setLogger(this.slf4jLoggerName); } if (this.jsonFormat) { listener.setQueryLogEntryCreator(new DefaultJsonQueryLogEntryCreator()); } if (this.multiline) { listener.setQueryLogEntryCreator(buildMultilineQueryLogEntryCreator()); } return listener; } private SLF4JSlowQueryListener buildSlf4jSlowQueryListener() { SLF4JSlowQueryListener listener = new SLF4JSlowQueryListener(this.slowQueryThreshold, this.slowQueryTimeUnit); if (this.slf4jSlowQueryLogLevel != null) { listener.setLogLevel(this.slf4jSlowQueryLogLevel); } if (this.slf4jSlowQueryLoggerName != null) { listener.setLogger(this.slf4jSlowQueryLoggerName); } if (this.multiline) { listener.setQueryLogEntryCreator(buildMultilineQueryLogEntryCreator()); } return listener; } private JULQueryLoggingListener buildJulQueryListener() { JULQueryLoggingListener listener = new JULQueryLoggingListener(); if (this.julLogLevel != null) { listener.setLogLevel(this.julLogLevel); } if (this.julLoggerName != null && !this.julLoggerName.isEmpty()) { listener.setLogger(this.julLoggerName); } if (this.jsonFormat) { listener.setQueryLogEntryCreator(new DefaultJsonQueryLogEntryCreator()); } if (this.multiline) { listener.setQueryLogEntryCreator(buildMultilineQueryLogEntryCreator()); } return listener; } private JULSlowQueryListener buildJulSlowQueryListener() { JULSlowQueryListener listener = new JULSlowQueryListener(this.slowQueryThreshold, this.slowQueryTimeUnit); if (this.julSlowQueryLogLevel != null) { listener.setLogLevel(this.julSlowQueryLogLevel); } if (this.julSlowQueryLoggerName != null) { listener.setLogger(this.julSlowQueryLoggerName); } if (this.multiline) { listener.setQueryLogEntryCreator(buildMultilineQueryLogEntryCreator()); } return listener; } private SystemOutQueryLoggingListener buildSysOutQueryListener() { SystemOutQueryLoggingListener listener = new SystemOutQueryLoggingListener(); if (this.jsonFormat) { listener.setQueryLogEntryCreator(new DefaultJsonQueryLogEntryCreator()); } if (this.multiline) { listener.setQueryLogEntryCreator(buildMultilineQueryLogEntryCreator()); } return listener; } private SystemOutSlowQueryListener buildSysOutSlowQueryListener() { SystemOutSlowQueryListener listener = new SystemOutSlowQueryListener(this.slowQueryThreshold, this.slowQueryTimeUnit); if (this.multiline) { listener.setQueryLogEntryCreator(buildMultilineQueryLogEntryCreator()); } return listener; } private DefaultQueryLogEntryCreator buildMultilineQueryLogEntryCreator() { DefaultQueryLogEntryCreator entryCreator = new DefaultQueryLogEntryCreator(); entryCreator.setMultiline(true); return entryCreator; } }