Class SlowQueryReportJmx

All Implemented Interfaces:
InvocationHandler, NotificationBroadcaster, NotificationEmitter, SlowQueryReportJmxMBean

public class SlowQueryReportJmx extends SlowQueryReport implements NotificationEmitter, SlowQueryReportJmxMBean
JMX-enabled slow query report interceptor. Publishes slow and failed query statistics to JMX and provides notifications when slow or failed queries are detected.

With notifyPool=false this interceptor registers its own MBean and broadcaster. In the default notifyPool=true mode it registers nothing and raises notifications on the pool's own MBean instead. The MBean belongs to a pool and is published by the first borrow under the name the pool started with; the publication is attempted once and given up by the pool's close. Names must be unique among live pools.

The published resource is a SlowQueryReportJmx.Registration holding the pool name, the statistics store and the pool's JMX state, but not the pool itself, so an abandoned pool is not pinned by the MBean server. Listener subscriptions belong to the registration they were added through and must be re-attached after a pool closes.

  • Field Details

    • SLOW_QUERY_NOTIFICATION

      public static final String SLOW_QUERY_NOTIFICATION
      Notification type for slow query events. The pool's own MBean reports the same event under the same type when this interceptor is configured with notifyPool=true, so this is that very type and not a copy of its text: a client filters notifications on the type, and the two channels have to answer to one string.
      See Also:
    • FAILED_QUERY_NOTIFICATION

      public static final String FAILED_QUERY_NOTIFICATION
      Notification type for failed query events, shared with the pool's own MBean for the same reason as SLOW_QUERY_NOTIFICATION.
      See Also:
    • objectNameAttribute

      public static final String objectNameAttribute
      Property key for overriding the JMX object name.
      See Also:
    • NOTIFY_POOL

      protected static final String NOTIFY_POOL
      The name of the property that configures setNotifyPool(boolean). Spelled once, here, because setProperties(java.util.Map) applies it and isKnownProperty(String) reports the names it does not read.
      See Also:
    • SLOW_QUERY_TYPE

      protected static volatile CompositeType SLOW_QUERY_TYPE
      Composite type used for JMX query statistics data.
    • notifier

      protected volatile NotificationBroadcasterSupport notifier
      Notification broadcaster used while this instance serves no pool, and the one a notification of a pool that has already come down is sent through; while it serves a live pool, getNotifier() returns the broadcaster shared by all interceptor instances of that pool. Like the shared broadcasters, it is built with NOTIFICATION_INFO, so every handle's emitter surface advertises the types it sends.
    • poolName

      protected String poolName
      The name of the connection pool.
    • notifySequence

      protected static final AtomicLong notifySequence
      Atomic sequence counter for notifications.
    • notifyPool

      protected boolean notifyPool
      Whether to send notifications to the pool.
    • pool

      protected ConnectionPool pool
      The connection pool reference.
  • Constructor Details

    • SlowQueryReportJmx

      public SlowQueryReportJmx()
      Creates a new SlowQueryReportJmx instance.
  • Method Details

    • addNotificationListener

      public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws IllegalArgumentException
      Adds a notification listener.
      Specified by:
      addNotificationListener in interface NotificationBroadcaster
      Parameters:
      listener - the listener to add
      filter - the notification filter
      handback - the handback object
      Throws:
      IllegalArgumentException - if the listener is null
    • getNotificationInfo

      public MBeanNotificationInfo[] getNotificationInfo()
      Returns information about the notifications this MBean can send.
      Specified by:
      getNotificationInfo in interface NotificationBroadcaster
      Returns:
      an array of MBeanNotificationInfo objects
    • removeNotificationListener

      public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException
      Removes a notification listener.
      Specified by:
      removeNotificationListener in interface NotificationBroadcaster
      Parameters:
      listener - the listener to remove
      Throws:
      ListenerNotFoundException - if the listener was not previously added
    • removeNotificationListener

      public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException
      Removes a notification listener with the given filter and handback.
      Specified by:
      removeNotificationListener in interface NotificationEmitter
      Parameters:
      listener - the listener to remove
      filter - the notification filter
      handback - the handback object
      Throws:
      ListenerNotFoundException - if the listener was not previously added
    • getCompositeType

      protected static CompositeType getCompositeType()
      Returns the composite type used for JMX query statistics.
      Returns:
      the composite type, or null if initialization failed
    • jmxStateFor

      protected static SlowQueryReportJmx.PoolJmx jmxStateFor(ConnectionPool pool)
      Returns the JMX state published for the given pool.
      Parameters:
      pool - the pool whose published state is wanted
      Returns:
      what has been published for that pool, or null while nothing has been - because the pool has no statistics store, because no borrow of it has needed the state yet, or because its close has given the state up along with the store
    • reset

      public void reset(ConnectionPool parent, PooledConnection con)
      Resets this interceptor for a new connection, registering JMX if applicable.
      Overrides:
      reset in class SlowQueryReport
      Parameters:
      parent - the connection pool
      con - the pooled connection
    • poolStarted

      public void poolStarted(ConnectionPool pool)
      Called when the connection pool is started.
      Overrides:
      poolStarted in class SlowQueryReport
      Parameters:
      pool - the connection pool being started
    • reportFailedQuery

      protected String reportFailedQuery(String query, Object[] args, String name, long start, long delta, Throwable t)
      Reports a failed query and sends a JMX notification if logging is enabled.
      Overrides:
      reportFailedQuery in class SlowQueryReport
      Parameters:
      query - the SQL query
      args - the query arguments
      name - the name of the method used to execute
      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 throwable that caused the failure
      Returns:
      the formatted query string
    • notifyJmx

      protected void notifyJmx(String query, String type)
      Sends a JMX notification for the given query and notification type.
      Parameters:
      query - the SQL query string
      type - the notification type (slow or failed query)
    • getNotifier

      protected NotificationBroadcasterSupport getNotifier()
      Returns the notification broadcaster shared by all interceptor instances of the current pool, so that notifications raised on any connection reach the listeners registered with the pool's MBean.
      Returns:
      the shared broadcaster for this interceptor's pool
    • getNotificationSource

      protected Object getNotificationSource()
      Returns the source this MBean's notifications are sent with.

      Notification marshals its source, so a listener outside this JVM - one reached through a JMX connector, or one that hands the notification on to another process - only receives the notification at all if the source is serializable. This MBean is not, and neither is the pool it reports on, so the source is the ObjectName the MBean is registered under, which names the pool and is serializable. Interceptor instances are created per pooled connection and none of them is the published resource - that is the pool's SlowQueryReportJmx.Registration - so an instance cannot name itself: the source is the ObjectName the pool's JMX state records as published, which every instance of the pool sends alike. That includes the instances of a second definition on one pool: the two-thresholds configuration publishes one MBean, and an instance that published nothing must not stamp its notifications with the name its own properties would compute - that name is registered under nothing, and a client filtering or grouping by source reads the published one. An instance whose name cannot be formed - a malformed objectName property or a pool name that cannot be quoted into an ObjectName - was never registered at all, so no listener reached through a connector can exist for it; the source is then a string of the default name's shape, which still names the pool for the local listeners the broadcaster serves. A pool that carries no name is the same case taken to its end: it holds no registration to name itself by, and the shape its source takes is the default one with no name in it - whatever survives delivery, it cannot name a pool that never had a name to register.

      Returns:
      the ObjectName this interceptor's pool is published under, or, when nothing is published for it or the published name cannot be told, a name formed from this instance - as an ObjectName where that succeeds, and as a string of the default name's shape where it does not
    • reportSlowQuery

      protected String reportSlowQuery(String query, Object[] args, String name, long start, long delta)
      Reports a slow query and sends a JMX notification if logging is enabled.
      Overrides:
      reportSlowQuery in class SlowQueryReport
      Parameters:
      query - the SQL query
      args - the query arguments
      name - the connection pool name
      start - the start time in milliseconds
      delta - the elapsed time in milliseconds
      Returns:
      the formatted query string
    • getPoolNames

      public String[] getPoolNames()
      JMX operation - return the names of all the pools
      Specified by:
      getPoolNames in interface SlowQueryReportJmxMBean
      Returns:
      - all the names of pools that we have stored data for, which is a view of the JVM-wide statistics registry rather than of this pool alone
    • getPoolName

      public String getPoolName()
      JMX operation - return the name of the pool.
      Specified by:
      getPoolName in interface SlowQueryReportJmxMBean
      Returns:
      the registration name recorded when this instance was bound to its pool, or null before binding. The value is retained when the chain is released with reset(null, null), so it can remain non-null after that release
    • isNotifyPool

      public boolean isNotifyPool()
      Returns whether notifications are sent to the pool.
      Returns:
      true if notifications are sent to the pool
    • setNotifyPool

      public void setNotifyPool(boolean notifyPool)
      Sets whether notifications are sent to the pool. Configuration entry point only, applied to every interceptor instance of a pool by setProperties while its connection chain is built: it is not part of the JMX management interface, because writing it through the registered MBean would reach only the one instance that owns the registration and leave the pool's other connections routing as before. See SlowQueryReportJmxMBean.
      Parameters:
      notifyPool - true if notifications should be sent to the pool
    • resetStats

      public void resetStats()
      JMX operation - remove all stats for this connection pool. The statistics belong to this interceptor's pool, so what this clears is what that pool has recorded - and nothing another pool collected, however it was named. Only the recorded content goes: the statistics store stays registered with the pool, which keeps accumulating into it.
      Specified by:
      resetStats in interface SlowQueryReportJmxMBean
    • getSlowQueriesCD

      public CompositeData[] getSlowQueriesCD() throws OpenDataException
      JMX operation - returns all the queries we have collected.
      Specified by:
      getSlowQueriesCD in interface SlowQueryReportJmxMBean
      Returns:
      - the slow query report as composite data; an empty array when this interceptor's pool publishes no statistics - because it never registered a store, or because its close has released it
      Throws:
      OpenDataException - if the composite data cannot be created; a JMX client gets it wrapped in an MBeanException
    • registerJmx

      protected void registerJmx()
      Registers this pool's MBean with JMX. The publication is attempted once per pool by the first borrow that needs it; a refusal is logged and not retried. A pool with no statistics store, or whose store has been released, has nothing to publish.
    • setProperties

      public void setProperties(Map<String, PoolProperties.InterceptorProperty> properties)
      Sets the interceptor properties, including the notifyPool flag.

      The flag is read the way the inherited properties are: a value that states neither true nor false is reported and leaves the flag as it stands, rather than being read as the false the raw parser answered with - which would have moved the pool's notifications off the route its default selects without saying so.

      Overrides:
      setProperties in class SlowQueryReport
      Parameters:
      properties - the interceptor properties
    • getObjectName

      public ObjectName getObjectName(Class<?> clazz, String poolName) throws MalformedObjectNameException
      Returns the JMX ObjectName for the given class and pool name.

      A property carrying no value - which the interceptor-string grammar cannot produce, but a programmatically built PoolProperties.InterceptorDefinition can hand through - names nothing to override, and reads as if the property were absent, the way every sibling property of this family reads its null value.

      Parameters:
      clazz - the interceptor class
      poolName - the name of the connection pool
      Returns:
      the JMX ObjectName
      Throws:
      MalformedObjectNameException - if the object name is malformed
    • isKnownProperty

      protected boolean isKnownProperty(String name)
      Recognises the two names this class reads on top of the ones the base reads: notifyPool, which decides which notification channel reports a query, and objectName, which names the MBean (see getObjectName(Class, String)). Without them here, every correct configuration of this interceptor would be reported as a typo by the property check it inherits.
      Overrides:
      isKnownProperty in class SlowQueryReport
      Parameters:
      name - the property name to test
      Returns:
      true if this configuration applies that name