Class SlowQueryReport

All Implemented Interfaces:
InvocationHandler
Direct Known Subclasses:
SlowQueryReportJmx

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

Statistics belong to the pool the interceptor serves: the pool registers a store when it starts, every connection books into it, and the close releases it. The store is read by the name the pool started with. Names must be unique among live pools; a pool starting under a live pool's name is a configuration error and displaces the other pool's store. Registrations hold the pool only weakly, so an abandoned pool is not pinned by its statistics.

A reporting definition added after the pool started registers its store on first borrow. Several reporting definitions may be configured on one pool; the deepest definition that stores statistics books each execution once, while each definition's own slow and failed query logging still fires.

  • Field Details

  • 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 statistics published under the given pool name.

      The store is published under the name the pool started with and is given up with that pool's close. The one store that outlives the rule is a pool that was abandoned without closing: its bounded statistics stay published under its name until a pool starting under the name replaces it, because the close that would give them up never ran.

      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 when no store is published under that name. A null name is answered the same way as a name that holds nothing, since nothing can be registered under it. The map is the live store, not a copy: callers must not modify it
    • statisticsFor

      protected static SlowQueryReport.PoolStatistics statisticsFor(ConnectionPool pool)
      Returns the statistics store registered for the given pool.
      Parameters:
      pool - the pool whose store is wanted, possibly null
      Returns:
      the store registered for that pool, or null when the pool has none - because it never registered one, because it has closed, or because it carries no name
    • 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, as recognised by 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
      args - the arguments to the execution
      name - the name of the method used to execute, as recognised by 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 exceeded the timing threshold
      Overrides:
      reportSlowQuery in class AbstractQueryReport
      Parameters:
      query - the query that was executed
      args - the arguments to the execution
      name - the name of the method used to execute, as recognised by 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)
      Registers the statistics store of a pool that has started, under the name the pool started with. A start always begins a fresh store rather than inheriting numbers from an abandoned pool's leftover.
      Overrides:
      poolStarted in class JdbcInterceptor
      Parameters:
      pool - the connection pool that has started
      Throws:
      IllegalStateException - if the pool carries no name to publish under
    • poolClosed

      public void poolClosed(ConnectionPool pool)
      Releases the statistics store of the given connection pool.

      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 store to release can only be identified through the closing pool passed here, not through this instance's own state. The release is idempotent, and every definition of the closing pool's chain can run it.

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

      protected static SlowQueryReport.PoolStatistics releaseStatistics(ConnectionPool pool)
      Gives up the statistics store registered for the given pool: the store stops publishing its statistics and is taken out of the registry.
      Parameters:
      pool - the connection pool that has been closed
      Returns:
      the store that was registered for the pool, or null if it had registered none
    • booksSharedStats

      protected boolean booksSharedStats()
      Whether this instance books the shared statistics for its pool. Every reporting definition sees every execution, so only the deepest definition that stores statistics books; a definition with no capacity never claims the booking. The decision reads the fixed chain below this instance and nothing is remembered across executions.
      Returns:
      true if this instance must book the statistics of its pool for the executions it reports
    • getQueryStats

      protected SlowQueryReport.QueryStats getQueryStats(String sql)
      Retrieves or creates the statistics entry for the given SQL string in the store this instance books to.
      Parameters:
      sql - the SQL query string
      Returns:
      the query statistics, or null when this instance has no store to book to - the session it serves outlived the pool it was borrowed from, the chain it belongs to has been released, or its pool carries no name to publish statistics under
    • 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)
      Resolves the statistics store this instance serves, registering its pool's store when this borrow is the first component of that pool to need one.
      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 properties of its definition: the threshold, the capacity of the statistics store and the two log flags.

      The values arrive as text, and text is where typos live, so a value this interceptor cannot read is reported and left out rather than read as something else: the setting keeps the value it already carries, which for the log flags means the channel the operator meant to configure is not switched off by the typo, and for the numbers means the default threshold or capacity stays in force. A name this configuration does not read is reported the same way. The pool configures an interceptor chain per physical connection, so one misconfiguration is reported once per configuration of the bad definition rather than once per JVM.

      Overrides:
      setProperties in class JdbcInterceptor
      Parameters:
      properties - the interceptor properties
    • isKnownProperty

      protected boolean isKnownProperty(String name)
      Whether this interceptor configuration reads the named property. useEquals belongs to the JdbcInterceptor base and is reported as known beside this class's own names, since the point of the report is a mistyped name rather than a configuration that sets more than one thing. A subclass that reads properties of its own - as SlowQueryReportJmx does - recognises them in its own override, so a correct configuration of the subclass is never reported as a typo.
      Parameters:
      name - the property name to test
      Returns:
      true if this configuration applies that name
    • flagValue

      protected static Boolean flagValue(String value)
      The flag a configured text states, accepting the word in any case as the parser this reading replaces did.
      Parameters:
      value - the configured text
      Returns:
      the stated flag, or null when the text states neither true nor false and is therefore a value to report rather than to read as false