jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/385348 )

Change subject: Publish minimal metrics about throttling filter.
......................................................................


Publish minimal metrics about throttling filter.

Expose the number of state entries and the number of throttled requests
as an MBean.

Bug: T178491
Change-Id: If299ac1a29d5f058549c5ed60234832dc4df5d96
---
M 
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/throttling/Throttler.java
M 
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/throttling/ThrottlingFilter.java
A 
blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/throttling/ThrottlingMXBean.java
3 files changed, 102 insertions(+), 3 deletions(-)

Approvals:
  Smalyshev: Looks good to me, approved
  jenkins-bot: Verified



diff --git 
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/throttling/Throttler.java
 
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/throttling/Throttler.java
index 065a2d1..9d19a2b 100644
--- 
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/throttling/Throttler.java
+++ 
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/throttling/Throttler.java
@@ -78,6 +78,17 @@
     }
 
     /**
+     * The size (in number of entries) of the throttling state.
+     *
+     * This correspond to the number of clients currently being tracked.
+     *
+     * @return the number of entries in state size
+     */
+    public long getStateSize() {
+        return state.size();
+    }
+
+    /**
      * Should this request be throttled.
      *
      * @param request the request to check
diff --git 
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/throttling/ThrottlingFilter.java
 
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/throttling/ThrottlingFilter.java
index ca1d8df..de2419e 100644
--- 
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/throttling/ThrottlingFilter.java
+++ 
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/throttling/ThrottlingFilter.java
@@ -9,10 +9,20 @@
 import static java.util.concurrent.TimeUnit.MINUTES;
 
 import java.io.IOException;
+import java.lang.management.ManagementFactory;
 import java.time.Duration;
 import java.util.concurrent.Callable;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
 
+import javax.annotation.Nullable;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
 import javax.servlet.FilterConfig;
@@ -85,7 +95,7 @@
  *
  * All state is limited to a single JVM, this filter is not cluster aware.
  */
-public class ThrottlingFilter implements Filter {
+public class ThrottlingFilter implements Filter, ThrottlingMXBean {
 
     private static final Logger log = 
LoggerFactory.getLogger(ThrottlingFilter.class);
 
@@ -93,6 +103,12 @@
     private boolean enabled;
     /** To delegate throttling logic. */
     private Throttler<Bucket> throttler;
+
+    /** Keeps track of the number of requests being throttled. */
+    private final AtomicLong nbThrottledRequests = new AtomicLong();
+
+    /** The object name under which the stats for this filter are exposed 
through JMX. */
+    @Nullable  private ObjectName objectName;
 
     /**
      * Initialise the filter.
@@ -132,6 +148,32 @@
                         .expireAfterAccess(stateExpirationInMinutes, 
TimeUnit.MINUTES)
                         .build(),
                 enableThrottlingIfHeader);
+
+        registerMBean(filterConfig.getFilterName());
+    }
+
+    /**
+     * Register this Filter as an MBean.
+     *
+     * On successful registration, the {@link ObjectName} used for registration
+     * will be stored into the instance field {@link 
ThrottlingFilter#objectName}.
+     *
+     * @param filterName
+     */
+    private void registerMBean(String filterName) {
+        try {
+            ObjectName objectName = new 
ObjectName(ThrottlingFilter.class.getName(), "filterName", filterName);
+            MBeanServer platformMBeanServer = 
ManagementFactory.getPlatformMBeanServer();
+            platformMBeanServer.registerMBean(this, objectName);
+            this.objectName = objectName;
+            log.info("ThrottlingFilter MBean registered as {}.", objectName);
+        } catch (MalformedObjectNameException e) {
+            log.error("filter name {} is invalid as an MBean property.", 
filterName, e);
+        } catch (InstanceAlreadyExistsException e) {
+            log.error("MBean for ThrottlingFilter has already been 
registered.", e);
+        } catch (NotCompliantMBeanException | MBeanRegistrationException e) {
+            log.error("Could not register MBean for ThrottlingFilter.", e);
+        }
     }
 
     /**
@@ -235,6 +277,7 @@
         if (throttler.isThrottled(httpRequest)) {
             log.info("A request is being throttled.");
             if (enabled) {
+                nbThrottledRequests.incrementAndGet();
                 notifyUser(httpResponse, 
throttler.getBackoffDelay(httpRequest));
                 return;
             }
@@ -270,9 +313,34 @@
         response.sendError(429, format(ENGLISH, "Too Many Requests - Please 
retry in %s seconds.", retryAfter));
     }
 
-    /** {@inheritDoc} */
+    /** Unregister MBean. */
     @Override
     public void destroy() {
-        // Nothing to destroy
+        // Don't do anything if the MBean isn't registered.
+        if (objectName == null) return;
+
+        MBeanServer platformMBeanServer = 
ManagementFactory.getPlatformMBeanServer();
+        try {
+            platformMBeanServer.unregisterMBean(objectName);
+            log.info("ThrottlingFilter MBean {} unregistered.", objectName);
+            objectName = null;
+        } catch (InstanceNotFoundException e) {
+            log.warn("MBean already unregistered.", e);
+        } catch (MBeanRegistrationException e) {
+            log.error("Could not unregister MBean.", e);
+        }
     }
+
+    /** {@inheritDoc} */
+    @Override
+    public long getStateSize() {
+        return throttler.getStateSize();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public long getNumberOfThrottledRequests() {
+        return nbThrottledRequests.get();
+    }
+
 }
diff --git 
a/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/throttling/ThrottlingMXBean.java
 
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/throttling/ThrottlingMXBean.java
new file mode 100644
index 0000000..335aba4
--- /dev/null
+++ 
b/blazegraph/src/main/java/org/wikidata/query/rdf/blazegraph/throttling/ThrottlingMXBean.java
@@ -0,0 +1,20 @@
+package org.wikidata.query.rdf.blazegraph.throttling;
+
+/**
+ * Expose statistics about throttling filter.
+ */
+public interface ThrottlingMXBean {
+
+    /**
+     * The number of entries in the state store.
+     *
+     * This represents the number of clients currently being tracked.
+     */
+    long getStateSize();
+
+    /**
+     * Monotonic increasing counter of the the number of requests that have 
been throttled.
+     */
+    long getNumberOfThrottledRequests();
+
+}

-- 
To view, visit https://gerrit.wikimedia.org/r/385348
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: If299ac1a29d5f058549c5ed60234832dc4df5d96
Gerrit-PatchSet: 3
Gerrit-Project: wikidata/query/rdf
Gerrit-Branch: master
Gerrit-Owner: Gehel <[email protected]>
Gerrit-Reviewer: Smalyshev <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to