Class SlowQueryReport

All Implemented Interfaces:
InvocationHandler
Direct Known Subclasses:
SlowQueryReportJmx

public class SlowQueryReport extends AbstractQueryReport
Slow query report interceptor. Tracks timing of query executions.

The statistics are published under the pool name (see getPoolStats(String)), registered when a pool starts and released when the last live pool registered under that name closes. Pools configured with the same name - possible with jmxEnabled=false, which removes the JMX ObjectName clash that would otherwise catch it - therefore share one statistics map; closing one of them never takes the shared statistics away from the others.

  • Field Details

    • perPoolStats

      protected static final ConcurrentHashMap<String, SlowQueryReport.PoolStatistics> perPoolStats
      we will be keeping track of query stats on a per pool basis, keyed by pool name; pools registered under one name share the statistics
    • queries

      protected volatile ConcurrentHashMap<String, SlowQueryReport.QueryStats> queries
      the queries that are used for this interceptor.
    • maxQueries

      protected int maxQueries
      Maximum number of queries we will be storing statistics for. Eviction keeps the number of stored queries near this amount; while queries are being executed concurrently it can briefly be exceeded. This sizes the statistics store only: the slow and failed query logging is configured by setLogSlow(boolean) and setLogFailed(boolean) independently of this value.
    • logSlow

      protected boolean logSlow
      Flag to enable disable logging of slow queries
    • logFailed

      protected boolean logFailed
      Flag to enable disable logging of failed queries
    • queryStatsComparator

      protected final Comparator<SlowQueryReport.QueryStats> queryStatsComparator
      Sort QueryStats by last invocation time
    • lastPoolOfNameClosed

      protected boolean lastPoolOfNameClosed
      Whether the poolClosed(ConnectionPool) delivered to this instance deregistered the closing pool as the last live pool under its name, meaning everything else registered for that name - the interceptor's MBean and broadcaster, for instance - can and must now be released with it. The deciding releaseStatistics(ConnectionPool) call is atomic, so across concurrent closes of same-named pools and across the interceptor definitions of one close exactly one caller ever sees true.
  • Constructor Details

    • SlowQueryReport

      public SlowQueryReport()
      Creates a slow query report interceptor
  • Method Details

    • getPoolStats

      public static ConcurrentHashMap<String, SlowQueryReport.QueryStats> getPoolStats(String poolname)
      Returns the query stats for a given pool
      Parameters:
      poolname - - the name of the pool we want to retrieve stats for
      Returns:
      a hash map containing the statistics of the monitored queries, kept near maxQueries entries by eviction, or null if no live pool is registered under that name. Pools registered under one name share the map, and it is published until the last of them has closed
    • setMaxQueries

      public void setMaxQueries(int maxQueries)
      Sets the maximum number of queries to track statistics for.
      Parameters:
      maxQueries - the maximum number of queries
    • reportFailedQuery

      protected String reportFailedQuery(String query, Object[] args, String name, long start, long delta, Throwable t)
      Description copied from class: AbstractQueryReport
      Invoked when a query execution, a call to an execute method as recognised by AbstractCreateStatementInterceptor.isExecute(Method, boolean), failed.
      Overrides:
      reportFailedQuery in class AbstractQueryReport
      Parameters:
      query - the query that was executed and failed
      args - the arguments to the execution
      name - the name of the method used to execute AbstractCreateStatementInterceptor.isExecute(Method, boolean)
      start - the wall clock time the query execution started
      delta - the time the execution took before it failed, measured with the monotonic clock
      t - the exception that happened
      Returns:
      - the SQL that was executed or the string "batch" if it was a batch execution, or null if the invocation carries no SQL string
    • reportQuery

      protected String reportQuery(String query, Object[] args, String name, long start, long delta)
      Description copied from class: AbstractQueryReport
      Invoked when a query execution, a call to an execute method as recognised by AbstractCreateStatementInterceptor.isExecute(Method, boolean), succeeded and was within the timing threshold
      Overrides:
      reportQuery in class AbstractQueryReport
      Parameters:
      query - the query that was executed and failed
      args - the arguments to the execution
      name - the name of the method used to execute AbstractCreateStatementInterceptor.isExecute(Method, boolean)
      start - the wall clock time the query execution started
      delta - the time the execution took, measured with the monotonic clock
      Returns:
      - the SQL that was executed or the string "batch" if it was a batch execution, or null if the invocation carries no SQL string
    • reportSlowQuery

      protected String reportSlowQuery(String query, Object[] args, String name, long start, long delta)
      Description copied from class: AbstractQueryReport
      Invoked when a query execution, a call to an execute method as recognised by AbstractCreateStatementInterceptor.isExecute(Method, boolean), succeeded and was exceeded the timing threshold
      Overrides:
      reportSlowQuery in class AbstractQueryReport
      Parameters:
      query - the query that was executed and failed
      args - the arguments to the execution
      name - the name of the method used to execute AbstractCreateStatementInterceptor.isExecute(Method, boolean)
      start - the wall clock time the query execution started
      delta - the time the execution took, measured with the monotonic clock
      Returns:
      - the SQL that was executed or the string "batch" if it was a batch execution, or null if the invocation carries no SQL string
    • closeInvoked

      public void closeInvoked()
      invoked when the connection receives the close request Not used for now.
      Specified by:
      closeInvoked in class AbstractCreateStatementInterceptor
    • prepareStatement

      public void prepareStatement(String sql, long time)
      Tracks the preparation time for a prepared statement.
      Specified by:
      prepareStatement in class AbstractQueryReport
      Parameters:
      sql - the SQL statement
      time - the time taken to prepare the statement
    • prepareCall

      public void prepareCall(String sql, long time)
      Tracks the preparation time for a callable statement.
      Specified by:
      prepareCall in class AbstractQueryReport
      Parameters:
      sql - the SQL call
      time - the time taken to prepare the call
    • poolStarted

      public void poolStarted(ConnectionPool pool)
      Initializes the query statistics map for the given connection pool.

      The map is registered under the pool name together with the pool instance itself. If a live pool is already registered under the name, both pools share one statistics map; that merging is the pre-existing behaviour, but it is a configuration mistake worth a warning, so it is logged.

      Overrides:
      poolStarted in class JdbcInterceptor
      Parameters:
      pool - the connection pool that has started
    • poolClosed

      public void poolClosed(ConnectionPool pool)
      Releases the query statistics map for the given connection pool, unless another live pool is still registered under its name.

      The callback is delivered by ConnectionPool to a freshly instantiated interceptor (see ConnectionPool#close(boolean)), which has never held a reference to the statistics, so the map to release can only be identified through the closing pool passed here, not through this instance's own state. The statistics stay published as long as one pool registered under the name is alive.

      Overrides:
      poolClosed in class JdbcInterceptor
      Parameters:
      pool - the connection pool that has been closed
    • releaseStatistics

      protected static boolean releaseStatistics(ConnectionPool pool)
      Deregisters a closed pool from the live pools that the per-name statistics are held for, and releases the statistics once no live pool is registered under the name any more.

      The decision is taken inside a compute on the name, which atomises it against the concurrent removals of other same-named pools: exactly one of any number of concurrent poolClosed deliveries sees true returned, so the per-name entries are never released twice and never left behind.

      Parameters:
      pool - the connection pool that has been closed
      Returns:
      true if this call removed the last live pool registered under the name
    • getQueryStats

      protected SlowQueryReport.QueryStats getQueryStats(String sql)
      Retrieves or creates a QueryStats entry for the given SQL string.
      Parameters:
      sql - the SQL query string
      Returns:
      the query statistics, or null if the pool has been closed
    • removeOldest

      protected void removeOldest(ConcurrentHashMap<String, SlowQueryReport.QueryStats> queries)
      Evicts the least recently invoked query statistics until the map is back within maxQueries entries. The map is shared by all the connections of the pool, so the eviction runs concurrently with the inserts and removals of the other borrower threads and can only do as much work as its own snapshot allows; it then leaves the map above capacity for the next new query to evict further.
      Parameters:
      queries - The queries map
    • reset

      public void reset(ConnectionPool parent, PooledConnection con)
      Resets the query statistics reference when a connection is reset.
      Overrides:
      reset in class AbstractCreateStatementInterceptor
      Parameters:
      parent - the connection pool
      con - the pooled connection being reset
    • isLogSlow

      public boolean isLogSlow()
      Returns whether slow query logging is enabled.
      Returns:
      true if slow query logging is enabled
    • setLogSlow

      public void setLogSlow(boolean logSlow)
      Enables or disables slow query logging.
      Parameters:
      logSlow - true to enable slow query logging
    • isLogFailed

      public boolean isLogFailed()
      Returns whether failed query logging is enabled.
      Returns:
      true if failed query logging is enabled
    • setLogFailed

      public void setLogFailed(boolean logFailed)
      Enables or disables failed query logging.
      Parameters:
      logFailed - true to enable failed query logging
    • setProperties

      public void setProperties(Map<String, PoolProperties.InterceptorProperty> properties)
      Configures this interceptor from the given properties map, supporting threshold, maxQueries, logSlow, and logFailed settings.
      Overrides:
      setProperties in class JdbcInterceptor
      Parameters:
      properties - the interceptor properties