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