Index: jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jmx/package-info.java =================================================================== --- jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jmx/package-info.java (revision 1754364) +++ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jmx/package-info.java (revision 1754365) @@ -18,5 +18,5 @@ /** * JMX management interfaces for JCR. */ -@aQute.bnd.annotation.Version("2.1.0") +@aQute.bnd.annotation.Version("2.2.0") package org.apache.jackrabbit.api.jmx; Index: jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jmx/EventListenerMBean.java =================================================================== --- jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jmx/EventListenerMBean.java (revision 1754364) +++ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jmx/EventListenerMBean.java (revision 1754365) @@ -71,6 +71,9 @@ /** Ratio of time spent in event processing */ double getRatioOfTimeSpentProcessingEvents(); + /** Ratio of time spent in event listener vs. the overall event processing */ + double getEventConsumerTimeRatio(); + /** Is user information accessed without checking if an event is external? */ boolean isUserInfoAccessedWithoutExternalsCheck(); @@ -84,6 +87,13 @@ boolean isDateAccessedFromExternalEvent(); /** + * The time difference between the current system time and the head (oldest) + * element in the queue in milliseconds. This method returns zero if the + * queue is empty. + */ + long getQueueBacklogMillis(); + + /** * {@link org.apache.jackrabbit.api.stats.TimeSeries time series} of the number of * items related to generating observation events that are currently queued by the * system. The exact nature of these items is implementation specific and might not Index: jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/ListenerTracker.java =================================================================== --- jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/ListenerTracker.java (revision 1754364) +++ jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/ListenerTracker.java (revision 1754365) @@ -71,6 +71,8 @@ private final AtomicLong eventDeliveryTime = new AtomicLong(); + private final AtomicLong headTimestamp = new AtomicLong(); + private final TimeSeriesMax queueLength = new TimeSeriesMax(); private final TimeSeriesRecorder eventCount = new TimeSeriesRecorder(true); @@ -142,6 +144,19 @@ } /** + * Applications should call this to report the current queue length when an + * item is removed from the queue. + * + * @param length the length of the queue after the item was removed. + * @param headTimestamp the time in milliseconds when the head item was + * created and put into the queue. + */ + public void recordQueueLength(long length, long headTimestamp) { + queueLength.recordValue(length); + this.headTimestamp.set(length == 0 ? 0 : headTimestamp); + } + + /** * Records the number of measured values over the past second and resets * the counter. This method should be scheduled to be called once per * second. @@ -279,6 +294,12 @@ / Math.max(currentTimeMillis() - startTime, 1); } @Override + public double getEventConsumerTimeRatio() { + double consumerTime = sum(eventConsumerTime.getValuePerSecond()); + double producerTime = sum(eventProducerTime.getValuePerSecond()); + return consumerTime / Math.max(consumerTime + producerTime, 1); + } + @Override public boolean isUserInfoAccessedWithoutExternalsCheck() { return userInfoAccessedWithoutExternalsCheck.get(); } @@ -295,6 +316,14 @@ return dateAccessedFromExternalEvent.get(); } @Override + public long getQueueBacklogMillis() { + long t = headTimestamp.get(); + if (t > 0) { + t = currentTimeMillis() - t; + } + return t; + } + @Override public CompositeData getQueueLength() { return asCompositeData(queueLength, "queueLength"); } @@ -361,4 +390,12 @@ } } + private static long sum(long[] values) { + long sum = 0; + for (long v : values) { + sum += v; + } + return sum; + } + }