jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ju...@apache.org
Subject svn commit: r1493643 - in /jackrabbit/trunk: jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jmx/ jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/
Date Mon, 17 Jun 2013 05:14:29 GMT
Author: jukka
Date: Mon Jun 17 05:14:29 2013
New Revision: 1493643

URL: http://svn.apache.org/r1493643
Log:
JCR-3608: MBeans for tracking event listeners

Initial EventListenerMBean insterface and a ListenerTracker class for collecting and exposing
the information

Added:
    jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jmx/EventListenerMBean.java
  (with props)
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/EventTracker.java
  (with props)
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/JackrabbitEventTracker.java
  (with props)
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/ListenerTracker.java
  (with props)
Modified:
    jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jmx/package-info.java

Added: jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jmx/EventListenerMBean.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jmx/EventListenerMBean.java?rev=1493643&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jmx/EventListenerMBean.java
(added)
+++ jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jmx/EventListenerMBean.java
Mon Jun 17 05:14:29 2013
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.api.jmx;
+
+/**
+ * MBean interface for exposing information about a registered observation
+ * listener.
+ *
+ * @see <a href="https://issues.apache.org/jira/browse/JCR-3608">JCR-3608</a>
+ */
+public interface EventListenerMBean {
+
+    /** Class name of the event listener */
+    String getClassName();
+
+    /** Stack trace of where the listener was registered */
+    String getInitStackTrace();
+
+    /** Event types of the listener registration */
+    int getEventTypes();
+
+    /** Absolute path of the listener registration */
+    String getAbsPath();
+
+    /** Whether the listener registration is deep */
+    boolean isDeep();
+
+    /** UUIDs of the listener registration */
+    String[] getUuid();
+
+    /** Node types of the listener registration */
+    String[] getNodeTypeName();
+
+    /** Whether the listener registration is non-local */
+    boolean isNoLocal();
+
+    /** Number of {@code onEvent()} calls made on the listener */
+    long getEventDeliveries();
+
+    /** Average number of {@code onEvent()} calls per hour */
+    long getEventDeliveriesPerHour();
+
+    /** Average time (in microseconds) taken per {@code onEvent()} call */
+    long getMicrosecondsPerEventDelivery();
+
+    /** Number of individual events delivered to the listener */
+    long getEventsDelivered();
+
+    /** Average number of individual events delivered per hour */
+    long getEventsDeliveredPerHour();
+
+    /** Average time (in microseconds) taken per event delivered */
+    long getMicrosecondsPerEventDelivered();
+
+    /** Ratio of time spent in event processing */
+    double getRatioOfTimeSpentProcessingEvents();
+
+    /** Is user information accessed without checking if an event is external? */
+    boolean isUserInfoAccessedWithoutExternalsCheck();
+
+    /** Is user information accessed from an external event? */
+    boolean isUserInfoAccessedFromExternalEvent();
+
+    /** Is date information accessed without checking if an event is external? */
+    boolean isDateAccessedWithoutExternalsCheck();
+
+    /** Is date information accessed from an external event? */
+    boolean isDateAccessedFromExternalEvent();
+
+}

Propchange: jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jmx/EventListenerMBean.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jmx/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jmx/package-info.java?rev=1493643&r1=1493642&r2=1493643&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jmx/package-info.java
(original)
+++ jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jmx/package-info.java
Mon Jun 17 05:14:29 2013
@@ -18,5 +18,5 @@
 /**
  * JMX management interfaces for JCR.
  */
-@aQute.bnd.annotation.Version("2.0.0")
+@aQute.bnd.annotation.Version("2.1.0")
 package org.apache.jackrabbit.api.jmx;

Added: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/EventTracker.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/EventTracker.java?rev=1493643&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/EventTracker.java
(added)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/EventTracker.java
Mon Jun 17 05:14:29 2013
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.jackrabbit.commons.observation;
+
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.observation.Event;
+
+/**
+ * Event decorator that tracks whether user and date information is being
+ * accessed from external events or without checking for externality.
+ *
+ * @see ListenerTracker
+ */
+class EventTracker implements Event {
+
+    /** The enclosing listener tracker */
+    private final ListenerTracker listener;
+
+    protected final Event event;
+
+    protected final AtomicBoolean externalAccessed =
+            new AtomicBoolean();
+
+    public EventTracker(ListenerTracker listenerTracker, Event event) {
+        listener = listenerTracker;
+        this.event = event;
+    }
+
+    private void userInfoAccessed() {
+        if (!externalAccessed.get()
+                && !listener.userInfoAccessedWithoutExternalsCheck.getAndSet(true))
{
+            listener.warn("Event listener " + listener + " is trying"
+                    + " to access user information of event " + event
+                    + " without checking whether the event is external.");
+        }
+        if (eventIsExternal()
+                && !listener.userInfoAccessedFromExternalEvent.getAndSet(true)) {
+            listener.warn("Event listener " + listener + " is trying"
+                    + " to access user information of external event "
+                    + event + ".");
+        }
+    }
+
+    private void dateInfoAccessed() {
+        if (!externalAccessed.get()
+                && !listener.dateAccessedWithoutExternalsCheck.getAndSet(true)) {
+            listener.warn("Event listener " + listener + " is trying"
+                    + " to access date information of event " + event
+                    + " without checking whether the event is external.");
+        }
+        if (eventIsExternal()
+                && !listener.dateAccessedFromExternalEvent.getAndSet(true)) {
+            listener.warn("Event listener " + listener + " is trying"
+                    + " to access date information of external event "
+                    + event + ".");
+        }
+    }
+
+    protected boolean eventIsExternal() {
+        return false;
+    }
+
+    //---------------------------------------------------------< Event >--
+
+    @Override
+    public int getType() {
+        return event.getType();
+    }
+
+    @Override
+    public String getPath() throws RepositoryException {
+        return event.getPath();
+    }
+
+    @Override
+    public String getUserID() {
+        userInfoAccessed();
+        return event.getUserID();
+    }
+
+    @Override
+    public String getIdentifier() throws RepositoryException {
+        return event.getIdentifier();
+    }
+
+    @Override
+    public Map<?, ?> getInfo() throws RepositoryException {
+        return event.getInfo();
+    }
+
+    @Override
+    public String getUserData() throws RepositoryException {
+        userInfoAccessed();
+        return event.getUserData();
+    }
+
+    @Override
+    public long getDate() throws RepositoryException {
+        dateInfoAccessed();
+        return event.getDate();
+    }
+
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/EventTracker.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/JackrabbitEventTracker.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/JackrabbitEventTracker.java?rev=1493643&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/JackrabbitEventTracker.java
(added)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/JackrabbitEventTracker.java
Mon Jun 17 05:14:29 2013
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.jackrabbit.commons.observation;
+
+import javax.jcr.observation.Event;
+
+import org.apache.jackrabbit.api.observation.JackrabbitEvent;
+
+class JackrabbitEventTracker extends EventTracker
+        implements JackrabbitEvent {
+
+    public JackrabbitEventTracker(ListenerTracker listener, Event event) {
+        super(listener, event);
+    }
+
+    @Override
+    protected boolean eventIsExternal() {
+        return ((JackrabbitEvent) event).isExternal();
+    }
+
+    //----------------------------------------------------< JackrabbitEvent>--
+
+    @Override
+    public boolean isExternal() {
+        externalAccessed.set(true);
+        return eventIsExternal();
+    }
+
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/JackrabbitEventTracker.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/ListenerTracker.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/ListenerTracker.java?rev=1493643&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/ListenerTracker.java
(added)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/ListenerTracker.java
Mon Jun 17 05:14:29 2013
@@ -0,0 +1,248 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.jackrabbit.commons.observation;
+
+import static java.lang.System.currentTimeMillis;
+import static java.lang.System.nanoTime;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.EventListener;
+
+import org.apache.jackrabbit.api.jmx.EventListenerMBean;
+import org.apache.jackrabbit.api.observation.JackrabbitEvent;
+import org.apache.jackrabbit.commons.iterator.EventIteratorAdapter;
+
+/**
+ * Tracks event deliveries to an event listener and the way the listener
+ * processes the events. The collected information is made available through
+ * the {@link EventListenerMBean} interface.
+ */
+public class ListenerTracker {
+
+    private final EventListener listener;
+
+    private final int eventTypes;
+
+    private final String absPath;
+
+    private final boolean isDeep;
+
+    private final String[] uuid;
+
+    private final String[] nodeTypeName;
+
+    private final boolean noLocal;
+
+    protected final Exception initStackTrace =
+            new Exception("The event listener was registered here:");
+
+    private final long startTime = currentTimeMillis();
+
+    private final AtomicLong eventDeliveries = new AtomicLong();
+
+    private final AtomicLong eventsDelivered = new AtomicLong();
+
+    private final AtomicLong eventDeliveryTime = new AtomicLong();
+
+    final AtomicBoolean userInfoAccessedWithoutExternalsCheck =
+            new AtomicBoolean();
+
+    final AtomicBoolean userInfoAccessedFromExternalEvent =
+            new AtomicBoolean();
+
+    final AtomicBoolean dateAccessedWithoutExternalsCheck =
+            new AtomicBoolean();
+
+    final AtomicBoolean dateAccessedFromExternalEvent =
+            new AtomicBoolean();
+
+    public ListenerTracker(
+            EventListener listener,
+            int eventTypes, String absPath, boolean isDeep,
+            String[] uuid, String[] nodeTypeName, boolean noLocal) {
+        this.listener = listener;
+
+        this.eventTypes = eventTypes;
+        this.absPath = absPath;
+        this.isDeep = isDeep;
+        this.uuid = copy(uuid);
+        this.nodeTypeName = copy(nodeTypeName);
+        this.noLocal = noLocal;
+    }
+
+    /**
+     * Called to log a deprecation warning about the detected behavior of
+     * the decorated listener. Subclasses should override this method that
+     * by default does nothing.
+     *
+     * @param message warning message
+     */
+    protected void warn(String message) {
+        // do nothing
+    }
+
+    public EventListener getTrackedListener() {
+        return new EventListener() {
+            @Override
+            public void onEvent(EventIterator events) {
+                eventDeliveries.incrementAndGet();
+                long start = nanoTime();
+                try {
+                    listener.onEvent(new EventIteratorAdapter(events) {
+                        @Override
+                        public Object next() {
+                            eventsDelivered.incrementAndGet();
+                            Object object = super.next();
+                            if (object instanceof JackrabbitEvent) {
+                                object = new JackrabbitEventTracker(
+                                        ListenerTracker.this,
+                                        (JackrabbitEvent) object);
+                            } else if (object instanceof Event) {
+                                object = new EventTracker(
+                                        ListenerTracker.this, (Event) object);
+                            }
+                            return object;
+                        }
+                    });
+                } finally {
+                    eventDeliveryTime.addAndGet(nanoTime() - start);
+                }
+            }
+        };
+    }
+
+    public EventListenerMBean getListenerMBean() {
+        return new EventListenerMBean() {
+            @Override
+            public String getClassName() {
+                return listener.getClass().getName();
+            }
+            @Override
+            public String getInitStackTrace() {
+                StringWriter writer = new StringWriter();
+                initStackTrace.printStackTrace(new PrintWriter(writer));
+                return writer.toString();
+            }
+            @Override
+            public int getEventTypes() {
+                return eventTypes;
+            }
+            @Override
+            public String getAbsPath() {
+                return absPath;
+            }
+            @Override
+            public boolean isDeep() {
+                return isDeep;
+            }
+            @Override
+            public String[] getUuid() {
+                return copy(uuid);
+            }
+            @Override
+            public String[] getNodeTypeName() {
+                return copy(nodeTypeName);
+            }
+            @Override
+            public boolean isNoLocal() {
+                return noLocal;
+            }
+            @Override
+            public long getEventDeliveries() {
+                return eventDeliveries.get();
+            }
+            @Override
+            public long getEventDeliveriesPerHour() {
+                long hours = TimeUnit.MILLISECONDS.toHours(
+                        currentTimeMillis() - startTime);
+                return getEventDeliveries() / Math.max(hours, 1);
+            }
+            @Override
+            public long getMicrosecondsPerEventDelivery() {
+                return TimeUnit.NANOSECONDS.toMicros(eventDeliveryTime.get())
+                        / Math.max(getEventDeliveries(), 1);
+            }
+            @Override
+            public long getEventsDelivered() {
+                return eventsDelivered.get();
+            }
+            @Override
+            public long getEventsDeliveredPerHour() {
+                long hours = TimeUnit.MILLISECONDS.toHours(
+                        currentTimeMillis() - startTime);
+                return getEventsDelivered() / Math.max(hours, 1);
+            }
+            @Override
+            public long getMicrosecondsPerEventDelivered() {
+                return TimeUnit.NANOSECONDS.toMicros(eventDeliveryTime.get())
+                        / Math.max(getEventsDelivered(), 1);
+            }
+            @Override
+            public double getRatioOfTimeSpentProcessingEvents() {
+                double timeSpentProcessingEvents =
+                        TimeUnit.NANOSECONDS.toMillis(eventDeliveryTime.get());
+                return timeSpentProcessingEvents
+                        / Math.max(currentTimeMillis() - startTime, 1);
+            }
+            @Override
+            public boolean isUserInfoAccessedWithoutExternalsCheck() {
+                return userInfoAccessedWithoutExternalsCheck.get();
+            }
+            @Override
+            public synchronized boolean isUserInfoAccessedFromExternalEvent() {
+                return userInfoAccessedFromExternalEvent.get();
+            }
+            @Override
+            public synchronized boolean isDateAccessedWithoutExternalsCheck() {
+                return dateAccessedWithoutExternalsCheck.get();
+            }
+            @Override
+            public synchronized boolean isDateAccessedFromExternalEvent() {
+                return dateAccessedFromExternalEvent.get();
+            }
+        };
+    }
+
+    //------------------------------------------------------------< Object >--
+
+    @Override
+    public String toString() {
+        return listener.getClass().getSimpleName();
+    }
+
+    //-----------------------------------------------------------< private >--
+
+    private static String[] copy(String[] array) {
+        if (array != null && array.length > 0) {
+            String[] copy = new String[array.length];
+            System.arraycopy(array, 0, copy, 0, array.length);
+            return copy;
+        } else {
+            return array;
+        }
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/observation/ListenerTracker.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message