You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by kr...@apache.org on 2016/11/28 17:26:33 UTC
[04/42] lucene-solr:jira/solr-8593: SOLR-8785: Use Dropwizard Metrics
library for core metrics
SOLR-8785: Use Dropwizard Metrics library for core metrics
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/ff6da666
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/ff6da666
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/ff6da666
Branch: refs/heads/jira/solr-8593
Commit: ff6da66601ca454941f6e3f0957068f5269319a6
Parents: c5aa9b9
Author: Shalin Shekhar Mangar <sh...@apache.org>
Authored: Tue Nov 22 14:37:33 2016 +0530
Committer: Shalin Shekhar Mangar <sh...@apache.org>
Committed: Tue Nov 22 14:37:33 2016 +0530
----------------------------------------------------------------------
lucene/ivy-versions.properties | 7 +-
solr/CHANGES.txt | 11 +
.../plugin/AnalyticsStatisticsCollector.java | 20 +-
solr/contrib/morphlines-core/ivy.xml | 4 +-
solr/core/ivy.xml | 1 +
.../org/apache/solr/cloud/DistributedQueue.java | 14 +-
.../java/org/apache/solr/cloud/Overseer.java | 13 +-
.../apache/solr/cloud/OverseerStatusCmd.java | 16 +-
.../solr/cloud/OverseerTaskProcessor.java | 6 +-
.../apache/solr/cloud/OverseerTaskQueue.java | 8 +-
.../solr/cloud/overseer/ZkStateWriter.java | 4 +-
.../apache/solr/handler/RequestHandlerBase.java | 21 +-
.../java/org/apache/solr/util/stats/Clock.java | 84 -------
.../java/org/apache/solr/util/stats/EWMA.java | 126 ----------
.../util/stats/ExponentiallyDecayingSample.java | 218 -----------------
.../org/apache/solr/util/stats/Histogram.java | 238 -------------------
.../java/org/apache/solr/util/stats/Meter.java | 143 -----------
.../java/org/apache/solr/util/stats/Sample.java | 52 ----
.../org/apache/solr/util/stats/Snapshot.java | 168 -------------
.../java/org/apache/solr/util/stats/Timer.java | 203 ----------------
.../apache/solr/util/stats/TimerContext.java | 55 -----
.../org/apache/solr/util/stats/TimerUtils.java | 58 +++++
.../apache/solr/util/stats/UniformSample.java | 108 ---------
.../org/apache/solr/cloud/OverseerTest.java | 24 +-
.../apache/solr/core/RequestHandlersTest.java | 4 +-
.../apache/solr/util/stats/TimerUtilsTest.java | 58 +++++
solr/licenses/metrics-core-3.0.1.jar.sha1 | 1 -
solr/licenses/metrics-core-3.1.2.jar.sha1 | 1 +
.../metrics-healthchecks-3.0.1.jar.sha1 | 1 -
.../metrics-healthchecks-3.1.2.jar.sha1 | 1 +
30 files changed, 184 insertions(+), 1484 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/lucene/ivy-versions.properties
----------------------------------------------------------------------
diff --git a/lucene/ivy-versions.properties b/lucene/ivy-versions.properties
index c4d1c11..fe66c72 100644
--- a/lucene/ivy-versions.properties
+++ b/lucene/ivy-versions.properties
@@ -13,9 +13,6 @@ com.carrotsearch.randomizedtesting.version = 2.4.0
/com.carrotsearch/hppc = 0.7.1
-com.codahale.metrics.version = 3.0.1
-/com.codahale.metrics/metrics-core = ${com.codahale.metrics.version}
-/com.codahale.metrics/metrics-healthchecks = ${com.codahale.metrics.version}
/com.cybozu.labs/langdetect = 1.1-20120112
/com.drewnoakes/metadata-extractor = 2.8.1
@@ -76,6 +73,10 @@ com.sun.jersey.version = 1.9
/hsqldb/hsqldb = 1.8.0.10
/io.airlift/slice = 0.10
+io.dropwizard.metrics.version = 3.1.2
+/io.dropwizard.metrics/metrics-core = ${io.dropwizard.metrics.version}
+/io.dropwizard.metrics/metrics-healthchecks = ${io.dropwizard.metrics.version}
+
io.netty.netty-all.version = 4.0.36.Final
/io.netty/netty-all = ${io.netty.netty-all.version}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 6c2b99c..c1ad19b 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -86,6 +86,14 @@ Upgrade Notes
consequence of this change is that you must be aware that some tuples will not have values if
there were none in the original document.
+* SOLR-8785: Metrics related classes in org.apache.solr.util.stats have been removed in favor of
+ the dropwizard metrics library. Any custom plugins using these classes should be changed to use
+ the equivalent classes from the metrics library. As part of these changes, the "totalTime" metric
+ exposed by Overseer Status API in previous versions has been removed because it is no longer supported
+ by the metrics library. Also, the metrics "75thPctlRequestTime", "95thPctlRequestTime", "99thPctlRequestTime"
+ and "999thPctlRequestTime" in Overseer Status API have been renamed to "75thPcRequestTime", "95thPcRequestTime"
+ and so on for consistency with stats output in other parts of Solr.
+
New Features
----------------------
* SOLR-9293: Solrj client support for hierarchical clusters and other topics
@@ -195,6 +203,9 @@ Other Changes
* SOLR-9609: Change hard-coded keysize from 512 to 1024 (Jeremy Martini via Erick Erickson)
+* SOLR-8785: Use Dropwizard Metrics library for core metrics. The copied over code in
+ org.apache.solr.util.stats has been removed. (Jeff Wartes, Christine Poerschke, Kelvin Wong, shalin)
+
================== 6.3.0 ==================
Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this release.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/contrib/analytics/src/java/org/apache/solr/analytics/plugin/AnalyticsStatisticsCollector.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/plugin/AnalyticsStatisticsCollector.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/plugin/AnalyticsStatisticsCollector.java
index cf5bd43..e64c950 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/plugin/AnalyticsStatisticsCollector.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/plugin/AnalyticsStatisticsCollector.java
@@ -18,11 +18,10 @@ package org.apache.solr.analytics.plugin;
import java.util.concurrent.atomic.AtomicLong;
+import com.codahale.metrics.Timer;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
-import org.apache.solr.util.stats.Snapshot;
-import org.apache.solr.util.stats.Timer;
-import org.apache.solr.util.stats.TimerContext;
+import org.apache.solr.util.stats.TimerUtils;
public class AnalyticsStatisticsCollector {
private final AtomicLong numRequests;
@@ -35,7 +34,7 @@ public class AnalyticsStatisticsCollector {
private final AtomicLong numQueries;
private final Timer requestTimes;
- public TimerContext currentTimer;
+ public Timer.Context currentTimer;
public AnalyticsStatisticsCollector() {
numRequests = new AtomicLong();
@@ -88,7 +87,6 @@ public class AnalyticsStatisticsCollector {
public NamedList<Object> getStatistics() {
NamedList<Object> lst = new SimpleOrderedMap<>();
- Snapshot snapshot = requestTimes.getSnapshot();
lst.add("requests", numRequests.longValue());
lst.add("analyticsRequests", numAnalyticsRequests.longValue());
lst.add("statsRequests", numStatsRequests.longValue());
@@ -97,17 +95,7 @@ public class AnalyticsStatisticsCollector {
lst.add("rangeFacets", numRangeFacets.longValue());
lst.add("queryFacets", numQueryFacets.longValue());
lst.add("queriesInQueryFacets", numQueries.longValue());
- lst.add("totalTime", requestTimes.getSum());
- lst.add("avgRequestsPerSecond", requestTimes.getMeanRate());
- lst.add("5minRateReqsPerSecond", requestTimes.getFiveMinuteRate());
- lst.add("15minRateReqsPerSecond", requestTimes.getFifteenMinuteRate());
- lst.add("avgTimePerRequest", requestTimes.getMean());
- lst.add("medianRequestTime", snapshot.getMedian());
- lst.add("75thPcRequestTime", snapshot.get75thPercentile());
- lst.add("95thPcRequestTime", snapshot.get95thPercentile());
- lst.add("99thPcRequestTime", snapshot.get99thPercentile());
- lst.add("999thPcRequestTime", snapshot.get999thPercentile());
+ TimerUtils.addMetrics(lst, requestTimes);
return lst;
}
-
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/contrib/morphlines-core/ivy.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/morphlines-core/ivy.xml b/solr/contrib/morphlines-core/ivy.xml
index 0b78ed5..f7fd005 100644
--- a/solr/contrib/morphlines-core/ivy.xml
+++ b/solr/contrib/morphlines-core/ivy.xml
@@ -34,8 +34,8 @@
<dependency org="org.kitesdk" name="kite-morphlines-avro" rev="${/org.kitesdk/kite-morphlines-avro}" conf="compile" />
- <dependency org="com.codahale.metrics" name="metrics-core" rev="${/com.codahale.metrics/metrics-core}" conf="compile" />
- <dependency org="com.codahale.metrics" name="metrics-healthchecks" rev="${/com.codahale.metrics/metrics-healthchecks}" conf="compile" />
+ <dependency org="io.dropwizard.metrics" name="metrics-core" rev="${/io.dropwizard.metrics/metrics-core}" conf="compile" />
+ <dependency org="io.dropwizard.metrics" name="metrics-healthchecks" rev="${/io.dropwizard.metrics/metrics-healthchecks}" conf="compile" />
<dependency org="com.typesafe" name="config" rev="${/com.typesafe/config}" conf="compile" />
<!-- Test Dependencies -->
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/ivy.xml
----------------------------------------------------------------------
diff --git a/solr/core/ivy.xml b/solr/core/ivy.xml
index 67e4379..5710da9 100644
--- a/solr/core/ivy.xml
+++ b/solr/core/ivy.xml
@@ -50,6 +50,7 @@
<dependency org="log4j" name="log4j" rev="${/log4j/log4j}" conf="compile"/>
<dependency org="org.slf4j" name="slf4j-log4j12" rev="${/org.slf4j/slf4j-log4j12}" conf="compile"/>
<dependency org="org.slf4j" name="jcl-over-slf4j" rev="${/org.slf4j/jcl-over-slf4j}" conf="compile"/>
+ <dependency org="io.dropwizard.metrics" name="metrics-core" rev="${/io.dropwizard.metrics/metrics-core}" conf="compile" />
<dependency org="org.easymock" name="easymock" rev="${/org.easymock/easymock}" conf="test"/>
<dependency org="cglib" name="cglib-nodep" rev="${/cglib/cglib-nodep}" conf="test"/>
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/src/java/org/apache/solr/cloud/DistributedQueue.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/DistributedQueue.java b/solr/core/src/java/org/apache/solr/cloud/DistributedQueue.java
index 145d236..e7ac5e5 100644
--- a/solr/core/src/java/org/apache/solr/cloud/DistributedQueue.java
+++ b/solr/core/src/java/org/apache/solr/cloud/DistributedQueue.java
@@ -27,6 +27,7 @@ import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Predicate;
+import com.codahale.metrics.Timer;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import org.apache.solr.common.SolrException;
@@ -34,7 +35,6 @@ import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.cloud.SolrZkClient;
import org.apache.solr.common.cloud.ZkCmdExecutor;
import org.apache.solr.common.util.Pair;
-import org.apache.solr.util.stats.TimerContext;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
@@ -119,7 +119,7 @@ public class DistributedQueue {
* @return data at the first element of the queue, or null.
*/
public byte[] peek() throws KeeperException, InterruptedException {
- TimerContext time = stats.time(dir + "_peek");
+ Timer.Context time = stats.time(dir + "_peek");
try {
return firstElement();
} finally {
@@ -147,7 +147,7 @@ public class DistributedQueue {
*/
public byte[] peek(long wait) throws KeeperException, InterruptedException {
Preconditions.checkArgument(wait > 0);
- TimerContext time;
+ Timer.Context time;
if (wait == Long.MAX_VALUE) {
time = stats.time(dir + "_peek_wait_forever");
} else {
@@ -177,7 +177,7 @@ public class DistributedQueue {
* @return Head of the queue or null.
*/
public byte[] poll() throws KeeperException, InterruptedException {
- TimerContext time = stats.time(dir + "_poll");
+ Timer.Context time = stats.time(dir + "_poll");
try {
return removeFirst();
} finally {
@@ -191,7 +191,7 @@ public class DistributedQueue {
* @return The former head of the queue
*/
public byte[] remove() throws NoSuchElementException, KeeperException, InterruptedException {
- TimerContext time = stats.time(dir + "_remove");
+ Timer.Context time = stats.time(dir + "_remove");
try {
byte[] result = removeFirst();
if (result == null) {
@@ -210,7 +210,7 @@ public class DistributedQueue {
*/
public byte[] take() throws KeeperException, InterruptedException {
// Same as for element. Should refactor this.
- TimerContext timer = stats.time(dir + "_take");
+ Timer.Context timer = stats.time(dir + "_take");
updateLock.lockInterruptibly();
try {
while (true) {
@@ -234,7 +234,7 @@ public class DistributedQueue {
* element to become visible.
*/
public void offer(byte[] data) throws KeeperException, InterruptedException {
- TimerContext time = stats.time(dir + "_offer");
+ Timer.Context time = stats.time(dir + "_offer");
try {
while (true) {
try {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/src/java/org/apache/solr/cloud/Overseer.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/Overseer.java b/solr/core/src/java/org/apache/solr/cloud/Overseer.java
index a3eed36..d7285fa 100644
--- a/solr/core/src/java/org/apache/solr/cloud/Overseer.java
+++ b/solr/core/src/java/org/apache/solr/cloud/Overseer.java
@@ -26,9 +26,9 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
+import com.codahale.metrics.Timer;
import org.apache.solr.client.solrj.SolrResponse;
import org.apache.solr.cloud.overseer.ClusterStateMutator;
import org.apache.solr.cloud.overseer.CollectionMutator;
@@ -49,9 +49,6 @@ import org.apache.solr.core.CloudConfig;
import org.apache.solr.handler.admin.CollectionsHandler;
import org.apache.solr.handler.component.ShardHandler;
import org.apache.solr.update.UpdateShardHandler;
-import org.apache.solr.util.stats.Clock;
-import org.apache.solr.util.stats.Timer;
-import org.apache.solr.util.stats.TimerContext;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.slf4j.Logger;
@@ -254,7 +251,7 @@ public class Overseer implements Closeable {
private ClusterState processQueueItem(ZkNodeProps message, ClusterState clusterState, ZkStateWriter zkStateWriter, boolean enableBatching, ZkStateWriter.ZkWriteCallback callback) throws Exception {
final String operation = message.getStr(QUEUE_OPERATION);
List<ZkWriteCommand> zkWriteCommands = null;
- final TimerContext timerContext = stats.time(operation);
+ final Timer.Context timerContext = stats.time(operation);
try {
zkWriteCommands = processMessage(clusterState, message, operation);
stats.success(operation);
@@ -392,7 +389,7 @@ public class Overseer implements Closeable {
}
private LeaderStatus amILeader() {
- TimerContext timerContext = stats.time("am_i_leader");
+ Timer.Context timerContext = stats.time("am_i_leader");
boolean success = true;
try {
ZkNodeProps props = ZkNodeProps.load(zkClient.getData(
@@ -795,7 +792,7 @@ public class Overseer implements Closeable {
stat.errors.incrementAndGet();
}
- public TimerContext time(String operation) {
+ public Timer.Context time(String operation) {
String op = operation.toLowerCase(Locale.ROOT);
Stat stat = stats.get(op);
if (stat == null) {
@@ -853,7 +850,7 @@ public class Overseer implements Closeable {
public Stat() {
this.success = new AtomicInteger();
this.errors = new AtomicInteger();
- this.requestTime = new Timer(TimeUnit.MILLISECONDS, TimeUnit.MINUTES, Clock.defaultClock());
+ this.requestTime = new Timer();
this.failureDetails = new LinkedList<>();
}
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/src/java/org/apache/solr/cloud/OverseerStatusCmd.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/OverseerStatusCmd.java b/solr/core/src/java/org/apache/solr/cloud/OverseerStatusCmd.java
index 22e2270..901a884 100644
--- a/solr/core/src/java/org/apache/solr/cloud/OverseerStatusCmd.java
+++ b/solr/core/src/java/org/apache/solr/cloud/OverseerStatusCmd.java
@@ -23,14 +23,14 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import com.codahale.metrics.Timer;
import org.apache.solr.cloud.OverseerCollectionMessageHandler.Cmd;
import org.apache.solr.common.cloud.ClusterState;
import org.apache.solr.common.cloud.ZkNodeProps;
import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
-import org.apache.solr.util.stats.Snapshot;
-import org.apache.solr.util.stats.Timer;
+import org.apache.solr.util.stats.TimerUtils;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -100,17 +100,7 @@ public class OverseerStatusCmd implements Cmd {
lst.add("errors", errors);
}
Timer timer = entry.getValue().requestTime;
- Snapshot snapshot = timer.getSnapshot();
- lst.add("totalTime", timer.getSum());
- lst.add("avgRequestsPerMinute", timer.getMeanRate());
- lst.add("5minRateRequestsPerMinute", timer.getFiveMinuteRate());
- lst.add("15minRateRequestsPerMinute", timer.getFifteenMinuteRate());
- lst.add("avgTimePerRequest", timer.getMean());
- lst.add("medianRequestTime", snapshot.getMedian());
- lst.add("75thPctlRequestTime", snapshot.get75thPercentile());
- lst.add("95thPctlRequestTime", snapshot.get95thPercentile());
- lst.add("99thPctlRequestTime", snapshot.get99thPercentile());
- lst.add("999thPctlRequestTime", snapshot.get999thPercentile());
+ TimerUtils.addMetrics(lst, timer);
}
results.add("overseer_operations", overseerStats);
results.add("collection_operations", collectionStats);
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/src/java/org/apache/solr/cloud/OverseerTaskProcessor.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/OverseerTaskProcessor.java b/solr/core/src/java/org/apache/solr/cloud/OverseerTaskProcessor.java
index 9a72fd5..ad53346 100644
--- a/solr/core/src/java/org/apache/solr/cloud/OverseerTaskProcessor.java
+++ b/solr/core/src/java/org/apache/solr/cloud/OverseerTaskProcessor.java
@@ -30,6 +30,7 @@ import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
+import com.codahale.metrics.Timer;
import com.google.common.collect.ImmutableSet;
import org.apache.commons.io.IOUtils;
import org.apache.solr.client.solrj.SolrResponse;
@@ -43,7 +44,6 @@ import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.common.util.StrUtils;
import org.apache.solr.common.util.Utils;
import org.apache.solr.util.DefaultSolrThreadFactory;
-import org.apache.solr.util.stats.TimerContext;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
@@ -380,7 +380,7 @@ public class OverseerTaskProcessor implements Runnable, Closeable {
protected LeaderStatus amILeader() {
String statsName = "collection_am_i_leader";
- TimerContext timerContext = stats.time(statsName);
+ Timer.Context timerContext = stats.time(statsName);
boolean success = true;
try {
ZkNodeProps props = ZkNodeProps.load(zkStateReader.getZkClient().getData(
@@ -451,7 +451,7 @@ public class OverseerTaskProcessor implements Runnable, Closeable {
public void run() {
String statsName = messageHandler.getTimerName(operation);
- final TimerContext timerContext = stats.time(statsName);
+ final Timer.Context timerContext = stats.time(statsName);
boolean success = false;
final String asyncId = message.getStr(ASYNC);
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/src/java/org/apache/solr/cloud/OverseerTaskQueue.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/OverseerTaskQueue.java b/solr/core/src/java/org/apache/solr/cloud/OverseerTaskQueue.java
index 4adb194..c7604d6 100644
--- a/solr/core/src/java/org/apache/solr/cloud/OverseerTaskQueue.java
+++ b/solr/core/src/java/org/apache/solr/cloud/OverseerTaskQueue.java
@@ -22,10 +22,10 @@ import java.util.List;
import java.util.TreeSet;
import java.util.function.Predicate;
+import com.codahale.metrics.Timer;
import org.apache.solr.common.cloud.SolrZkClient;
import org.apache.solr.common.cloud.ZkNodeProps;
import org.apache.solr.common.util.Pair;
-import org.apache.solr.util.stats.TimerContext;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
@@ -85,7 +85,7 @@ public class OverseerTaskQueue extends DistributedQueue {
*/
public void remove(QueueEvent event) throws KeeperException,
InterruptedException {
- TimerContext time = stats.time(dir + "_remove_event");
+ Timer.Context time = stats.time(dir + "_remove_event");
try {
String path = event.getId();
String responsePath = dir + "/" + response_prefix
@@ -181,7 +181,7 @@ public class OverseerTaskQueue extends DistributedQueue {
*/
public QueueEvent offer(byte[] data, long timeout) throws KeeperException,
InterruptedException {
- TimerContext time = stats.time(dir + "_offer");
+ Timer.Context time = stats.time(dir + "_offer");
try {
// Create and watch the response node before creating the request node;
// otherwise we may miss the response.
@@ -227,7 +227,7 @@ public class OverseerTaskQueue extends DistributedQueue {
ArrayList<QueueEvent> topN = new ArrayList<>();
LOG.debug("Peeking for top {} elements. ExcludeSet: {}", n, excludeSet);
- TimerContext time;
+ Timer.Context time;
if (waitMillis == Long.MAX_VALUE) time = stats.time(dir + "_peekTopN_wait_forever");
else time = stats.time(dir + "_peekTopN_wait" + waitMillis);
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/src/java/org/apache/solr/cloud/overseer/ZkStateWriter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/overseer/ZkStateWriter.java b/solr/core/src/java/org/apache/solr/cloud/overseer/ZkStateWriter.java
index 598b5b2..23fb56c 100644
--- a/solr/core/src/java/org/apache/solr/cloud/overseer/ZkStateWriter.java
+++ b/solr/core/src/java/org/apache/solr/cloud/overseer/ZkStateWriter.java
@@ -21,12 +21,12 @@ import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
+import com.codahale.metrics.Timer;
import org.apache.solr.cloud.Overseer;
import org.apache.solr.common.cloud.ClusterState;
import org.apache.solr.common.cloud.DocCollection;
import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.common.util.Utils;
-import org.apache.solr.util.stats.TimerContext;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.data.Stat;
@@ -210,7 +210,7 @@ public class ZkStateWriter {
throw new IllegalStateException("ZkStateWriter has seen a tragic error, this instance can no longer be used");
}
if (!hasPendingUpdates()) return clusterState;
- TimerContext timerContext = stats.time("update_state");
+ Timer.Context timerContext = stats.time("update_state");
boolean success = false;
try {
if (!updates.isEmpty()) {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java b/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java
index 4ecf01c..218b6de 100644
--- a/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java
+++ b/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java
@@ -20,6 +20,7 @@ import java.lang.invoke.MethodHandles;
import java.net.URL;
import java.util.concurrent.atomic.LongAdder;
+import com.codahale.metrics.Timer;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
@@ -33,9 +34,7 @@ import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.search.SyntaxError;
import org.apache.solr.util.SolrPluginUtils;
-import org.apache.solr.util.stats.Snapshot;
-import org.apache.solr.util.stats.Timer;
-import org.apache.solr.util.stats.TimerContext;
+import org.apache.solr.util.stats.TimerUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -144,7 +143,7 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
@Override
public void handleRequest(SolrQueryRequest req, SolrQueryResponse rsp) {
numRequests.increment();
- TimerContext timer = requestTimes.time();
+ Timer.Context timer = requestTimes.time();
try {
if(pluginInfo != null && pluginInfo.attributes.containsKey(USEPARAM)) req.getContext().put(USEPARAM,pluginInfo.attributes.get(USEPARAM));
SolrPluginUtils.setDefaults(this, req, defaults, appends, invariants);
@@ -268,26 +267,16 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
@Override
public NamedList<Object> getStatistics() {
NamedList<Object> lst = new SimpleOrderedMap<>();
- Snapshot snapshot = requestTimes.getSnapshot();
lst.add("handlerStart",handlerStart);
lst.add("requests", numRequests.longValue());
lst.add("errors", numServerErrors.longValue() + numClientErrors.longValue());
lst.add("serverErrors", numServerErrors.longValue());
lst.add("clientErrors", numClientErrors.longValue());
lst.add("timeouts", numTimeouts.longValue());
- lst.add("totalTime", requestTimes.getSum());
- lst.add("avgRequestsPerSecond", requestTimes.getMeanRate());
- lst.add("5minRateReqsPerSecond", requestTimes.getFiveMinuteRate());
- lst.add("15minRateReqsPerSecond", requestTimes.getFifteenMinuteRate());
- lst.add("avgTimePerRequest", requestTimes.getMean());
- lst.add("medianRequestTime", snapshot.getMedian());
- lst.add("75thPcRequestTime", snapshot.get75thPercentile());
- lst.add("95thPcRequestTime", snapshot.get95thPercentile());
- lst.add("99thPcRequestTime", snapshot.get99thPercentile());
- lst.add("999thPcRequestTime", snapshot.get999thPercentile());
+ TimerUtils.addMetrics(lst, requestTimes);
return lst;
}
-
+
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/src/java/org/apache/solr/util/stats/Clock.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/stats/Clock.java b/solr/core/src/java/org/apache/solr/util/stats/Clock.java
deleted file mode 100644
index a94c216..0000000
--- a/solr/core/src/java/org/apache/solr/util/stats/Clock.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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.
- */
-/*
- * Forked from https://github.com/codahale/metrics
- */
-
-package org.apache.solr.util.stats;
-
-import java.lang.management.ManagementFactory;
-import java.lang.management.ThreadMXBean;
-
-import org.apache.solr.common.util.SuppressForbidden;
-
-/**
- * An abstraction for how time passes. It is passed to {@link Timer} to track timing.
- */
-public abstract class Clock {
- /**
- * Returns the current time tick.
- *
- * @return time tick in nanoseconds
- */
- public abstract long getTick();
-
- /**
- * Returns the current time in milliseconds.
- *
- * @return time in milliseconds
- */
- @SuppressForbidden(reason = "Need currentTimeMillis, API used by ExponentiallyDecayingSample for suspect reasons")
- public long getTime() {
- return System.currentTimeMillis();
- }
-
- private static final Clock DEFAULT = new UserTimeClock();
-
- /**
- * The default clock to use.
- *
- * @return the default {@link Clock} instance
- *
- * @see UserTimeClock
- */
- public static Clock defaultClock() {
- return DEFAULT;
- }
-
-
- /**
- * A clock implementation which returns the current time in epoch nanoseconds.
- */
- public static class UserTimeClock extends Clock {
- @Override
- public long getTick() {
- return System.nanoTime();
- }
- }
-
- /**
- * A clock implementation which returns the current thread's CPU time.
- */
- public static class CpuTimeClock extends Clock {
- private static final ThreadMXBean THREAD_MX_BEAN = ManagementFactory.getThreadMXBean();
-
- @Override
- public long getTick() {
- return THREAD_MX_BEAN.getCurrentThreadCpuTime();
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/src/java/org/apache/solr/util/stats/EWMA.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/stats/EWMA.java b/solr/core/src/java/org/apache/solr/util/stats/EWMA.java
deleted file mode 100644
index 010d2b1..0000000
--- a/solr/core/src/java/org/apache/solr/util/stats/EWMA.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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.
- */
-/*
- * Forked from https://github.com/codahale/metrics
- */
-
-package org.apache.solr.util.stats;
-
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-
-import static java.lang.Math.exp;
-
-/**
- * An exponentially-weighted moving average.
- *
- * @see <a href="http://www.teamquest.com/pdfs/whitepaper/ldavg1.pdf">UNIX Load Average Part 1: How
- * It Works</a>
- * @see <a href="http://www.teamquest.com/pdfs/whitepaper/ldavg2.pdf">UNIX Load Average Part 2: Not
- * Your Average Average</a>
- */
-public class EWMA {
- private static final int INTERVAL = 5;
- private static final double SECONDS_PER_MINUTE = 60.0;
- private static final int ONE_MINUTE = 1;
- private static final int FIVE_MINUTES = 5;
- private static final int FIFTEEN_MINUTES = 15;
- private static final double M1_ALPHA = 1 - exp(-INTERVAL / SECONDS_PER_MINUTE / ONE_MINUTE);
- private static final double M5_ALPHA = 1 - exp(-INTERVAL / SECONDS_PER_MINUTE / FIVE_MINUTES);
- private static final double M15_ALPHA = 1 - exp(-INTERVAL / SECONDS_PER_MINUTE / FIFTEEN_MINUTES);
-
- private volatile boolean initialized = false;
- private volatile double rate = 0.0;
-
- private final AtomicLong uncounted = new AtomicLong();
- private final double alpha, interval;
-
- /**
- * Creates a new EWMA which is equivalent to the UNIX one minute load average and which expects
- * to be ticked every 5 seconds.
- *
- * @return a one-minute EWMA
- */
- public static EWMA oneMinuteEWMA() {
- return new EWMA(M1_ALPHA, INTERVAL, TimeUnit.SECONDS);
- }
-
- /**
- * Creates a new EWMA which is equivalent to the UNIX five minute load average and which expects
- * to be ticked every 5 seconds.
- *
- * @return a five-minute EWMA
- */
- public static EWMA fiveMinuteEWMA() {
- return new EWMA(M5_ALPHA, INTERVAL, TimeUnit.SECONDS);
- }
-
- /**
- * Creates a new EWMA which is equivalent to the UNIX fifteen minute load average and which
- * expects to be ticked every 5 seconds.
- *
- * @return a fifteen-minute EWMA
- */
- public static EWMA fifteenMinuteEWMA() {
- return new EWMA(M15_ALPHA, INTERVAL, TimeUnit.SECONDS);
- }
-
- /**
- * Create a new EWMA with a specific smoothing constant.
- *
- * @param alpha the smoothing constant
- * @param interval the expected tick interval
- * @param intervalUnit the time unit of the tick interval
- */
- public EWMA(double alpha, long interval, TimeUnit intervalUnit) {
- this.interval = intervalUnit.toNanos(interval);
- this.alpha = alpha;
- }
-
- /**
- * Update the moving average with a new value.
- *
- * @param n the new value
- */
- public void update(long n) {
- uncounted.addAndGet(n);
- }
-
- /**
- * Mark the passage of time and decay the current rate accordingly.
- */
- public void tick() {
- final long count = uncounted.getAndSet(0);
- final double instantRate = count / interval;
- if (initialized) {
- rate += (alpha * (instantRate - rate));
- } else {
- rate = instantRate;
- initialized = true;
- }
- }
-
- /**
- * Returns the rate in the given units of time.
- *
- * @param rateUnit the unit of time
- * @return the rate
- */
- public double getRate(TimeUnit rateUnit) {
- return rate * (double) rateUnit.toNanos(1);
- }
-}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/src/java/org/apache/solr/util/stats/ExponentiallyDecayingSample.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/stats/ExponentiallyDecayingSample.java b/solr/core/src/java/org/apache/solr/util/stats/ExponentiallyDecayingSample.java
deleted file mode 100644
index 92b72fd..0000000
--- a/solr/core/src/java/org/apache/solr/util/stats/ExponentiallyDecayingSample.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * 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.
- */
-/*
- * Forked from https://github.com/codahale/metrics
- */
-
-package org.apache.solr.util.stats;
-
-import java.util.ArrayList;
-import java.util.Random;
-import java.util.concurrent.ConcurrentSkipListMap;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-import static java.lang.Math.exp;
-import static java.lang.Math.min;
-
-/**
- * An exponentially-decaying random sample of {@code long}s. Uses Cormode et al's forward-decaying
- * priority reservoir sampling method to produce a statistically representative sample,
- * exponentially biased towards newer entries.
- *
- * See <a href="http://www.research.att.com/people/Cormode_Graham/library/publications/CormodeShkapenyukSrivastavaXu09.pdf">
- * Cormode et al. Forward Decay: A Practical Time Decay Model for Streaming Systems. ICDE '09: Proceedings of the 2009 IEEE International Conference on Data Engineering (2009)</a>
- */
-public class ExponentiallyDecayingSample implements Sample {
-
- private static final long RESCALE_THRESHOLD = TimeUnit.HOURS.toNanos(1);
- private final ConcurrentSkipListMap<Double, Long> values;
- private final ReentrantReadWriteLock lock;
- private final double alpha;
- private final int reservoirSize;
- private final AtomicLong count = new AtomicLong(0);
- private volatile long startTime;
- private final AtomicLong nextScaleTime = new AtomicLong(0);
- private final Clock clock;
- // TODO: Maybe replace this with a Mersenne Twister?
- private final Random random = new Random();
-
- /**
- * Creates a new {@link ExponentiallyDecayingSample}.
- *
- * @param reservoirSize the number of samples to keep in the sampling reservoir
- * @param alpha the exponential decay factor; the higher this is, the more biased the
- * sample will be towards newer values
- */
- public ExponentiallyDecayingSample(int reservoirSize, double alpha) {
- this(reservoirSize, alpha, Clock.defaultClock());
- }
-
- /**
- * Creates a new {@link ExponentiallyDecayingSample}.
- *
- * @param reservoirSize the number of samples to keep in the sampling reservoir
- * @param alpha the exponential decay factor; the higher this is, the more biased the
- * sample will be towards newer values
- */
- public ExponentiallyDecayingSample(int reservoirSize, double alpha, Clock clock) {
- this.values = new ConcurrentSkipListMap<>();
- this.lock = new ReentrantReadWriteLock();
- this.alpha = alpha;
- this.reservoirSize = reservoirSize;
- this.clock = clock;
- clear();
- }
-
- @Override
- public void clear() {
- lockForRescale();
- try {
- values.clear();
- count.set(0);
- this.startTime = currentTimeInSeconds();
- nextScaleTime.set(clock.getTick() + RESCALE_THRESHOLD);
- } finally {
- unlockForRescale();
- }
- }
-
- @Override
- public int size() {
- return (int) min(reservoirSize, count.get());
- }
-
- @Override
- public void update(long value) {
- update(value, currentTimeInSeconds());
- }
-
- /**
- * Adds an old value with a fixed timestamp to the sample.
- *
- * @param value the value to be added
- * @param timestamp the epoch timestamp of {@code value} in seconds
- */
- public void update(long value, long timestamp) {
-
- rescaleIfNeeded();
-
- lockForRegularUsage();
- try {
- final double priority = weight(timestamp - startTime) / random.nextDouble();
- final long newCount = count.incrementAndGet();
- if (newCount <= reservoirSize) {
- values.put(priority, value);
- } else {
- Double first = values.firstKey();
- if (first < priority) {
- if (values.putIfAbsent(priority, value) == null) {
- // ensure we always remove an item
- while (values.remove(first) == null) {
- first = values.firstKey();
- }
- }
- }
- }
- } finally {
- unlockForRegularUsage();
- }
-
-
- }
-
- private void rescaleIfNeeded() {
- final long now = clock.getTick();
- final long next = nextScaleTime.get();
- if (now >= next) {
- rescale(now, next);
- }
- }
-
- @Override
- public Snapshot getSnapshot() {
- lockForRegularUsage();
- try {
- return new Snapshot(values.values());
- } finally {
- unlockForRegularUsage();
- }
- }
-
- private long currentTimeInSeconds() {
- return TimeUnit.MILLISECONDS.toSeconds(clock.getTime());
- }
-
- private double weight(long t) {
- return exp(alpha * t);
- }
-
- /* "A common feature of the above techniques\u2014indeed, the key technique that
- * allows us to track the decayed weights efficiently\u2014is that they maintain
- * counts and other quantities based on g(ti \u2212 L), and only scale by g(t \u2212 L)
- * at query time. But while g(ti \u2212L)/g(t\u2212L) is guaranteed to lie between zero
- * and one, the intermediate values of g(ti \u2212 L) could become very large. For
- * polynomial functions, these values should not grow too large, and should be
- * effectively represented in practice by floating point values without loss of
- * precision. For exponential functions, these values could grow quite large as
- * new values of (ti \u2212 L) become large, and potentially exceed the capacity of
- * common floating point types. However, since the values stored by the
- * algorithms are linear combinations of g values (scaled sums), they can be
- * rescaled relative to a new landmark. That is, by the analysis of exponential
- * decay in Section III-A, the choice of L does not affect the final result. We
- * can therefore multiply each value based on L by a factor of exp(\u2212\u03b1(L\u2032 \u2212 L)),
- * and obtain the correct value as if we had instead computed relative to a new
- * landmark L\u2032 (and then use this new L\u2032 at query time). This can be done with
- * a linear pass over whatever data structure is being used."
- */
- private void rescale(long now, long next) {
- if (nextScaleTime.compareAndSet(next, now + RESCALE_THRESHOLD)) {
- lockForRescale();
- try {
- final long oldStartTime = startTime;
- this.startTime = currentTimeInSeconds();
- final ArrayList<Double> keys = new ArrayList<>(values.keySet());
- for (Double key : keys) {
- final Long value = values.remove(key);
- values.put(key * exp(-alpha * (startTime - oldStartTime)), value);
- }
-
- // make sure the counter is in sync with the number of stored samples.
- count.set(values.size());
- } finally {
- unlockForRescale();
- }
- }
- }
-
- private void unlockForRescale() {
- lock.writeLock().unlock();
- }
-
- private void lockForRescale() {
- lock.writeLock().lock();
- }
-
- private void lockForRegularUsage() {
- lock.readLock().lock();
- }
-
- private void unlockForRegularUsage() {
- lock.readLock().unlock();
- }
-}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/src/java/org/apache/solr/util/stats/Histogram.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/stats/Histogram.java b/solr/core/src/java/org/apache/solr/util/stats/Histogram.java
deleted file mode 100644
index eef8f35..0000000
--- a/solr/core/src/java/org/apache/solr/util/stats/Histogram.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * 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.
- */
-/*
- * Forked from https://github.com/codahale/metrics
- */
-
-package org.apache.solr.util.stats;
-
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
-
-import static java.lang.Math.sqrt;
-
-/**
- * A metric which calculates the distribution of a value.
- *
- * @see <a href="http://www.johndcook.com/standard_deviation.html">Accurately computing running
- * variance</a>
- */
-public class Histogram {
-
- private static final int DEFAULT_SAMPLE_SIZE = 1028;
- private static final double DEFAULT_ALPHA = 0.015;
-
- /**
- * The type of sampling the histogram should be performing.
- */
- enum SampleType {
- /**
- * Uses a uniform sample of 1028 elements, which offers a 99.9% confidence level with a 5%
- * margin of error assuming a normal distribution.
- */
- UNIFORM {
- @Override
- public Sample newSample() {
- return new UniformSample(DEFAULT_SAMPLE_SIZE);
- }
- },
-
- /**
- * Uses an exponentially decaying sample of 1028 elements, which offers a 99.9% confidence
- * level with a 5% margin of error assuming a normal distribution, and an alpha factor of
- * 0.015, which heavily biases the sample to the past 5 minutes of measurements.
- */
- BIASED {
- @Override
- public Sample newSample() {
- return new ExponentiallyDecayingSample(DEFAULT_SAMPLE_SIZE, DEFAULT_ALPHA);
- }
- };
-
- public abstract Sample newSample();
- }
-
- private final Sample sample;
- private final AtomicLong min = new AtomicLong();
- private final AtomicLong max = new AtomicLong();
- private final AtomicLong sum = new AtomicLong();
- // These are for the Welford algorithm for calculating running variance
- // without floating-point doom.
- private final AtomicReference<double[]> variance =
- new AtomicReference<>(new double[]{-1, 0}); // M, S
- private final AtomicLong count = new AtomicLong();
-
- /**
- * Creates a new {@link Histogram} with the given sample type.
- *
- * @param type the type of sample to use
- */
- Histogram(SampleType type) {
- this(type.newSample());
- }
-
- /**
- * Creates a new {@link Histogram} with the given sample.
- *
- * @param sample the sample to create a histogram from
- */
- Histogram(Sample sample) {
- this.sample = sample;
- clear();
- }
-
- /**
- * Clears all recorded values.
- */
- public void clear() {
- sample.clear();
- count.set(0);
- max.set(Long.MIN_VALUE);
- min.set(Long.MAX_VALUE);
- sum.set(0);
- variance.set(new double[]{ -1, 0 });
- }
-
- /**
- * Adds a recorded value.
- *
- * @param value the length of the value
- */
- public void update(int value) {
- update((long) value);
- }
-
- /**
- * Adds a recorded value.
- *
- * @param value the length of the value
- */
- public void update(long value) {
- count.incrementAndGet();
- sample.update(value);
- setMax(value);
- setMin(value);
- sum.getAndAdd(value);
- updateVariance(value);
- }
-
- /**
- * Returns the number of values recorded.
- *
- * @return the number of values recorded
- */
- public long getCount() {
- return count.get();
- }
-
- /* (non-Javadoc)
- * @see com.yammer.metrics.core.Summarizable#max()
- */
- public double getMax() {
- if (getCount() > 0) {
- return max.get();
- }
- return 0.0;
- }
-
- /* (non-Javadoc)
- * @see com.yammer.metrics.core.Summarizable#min()
- */
- public double getMin() {
- if (getCount() > 0) {
- return min.get();
- }
- return 0.0;
- }
-
- /* (non-Javadoc)
- * @see com.yammer.metrics.core.Summarizable#mean()
- */
- public double getMean() {
- if (getCount() > 0) {
- return sum.get() / (double) getCount();
- }
- return 0.0;
- }
-
- /* (non-Javadoc)
- * @see com.yammer.metrics.core.Summarizable#stdDev()
- */
- public double getStdDev() {
- if (getCount() > 0) {
- return sqrt(getVariance());
- }
- return 0.0;
- }
-
- /* (non-Javadoc)
- * @see com.yammer.metrics.core.Summarizable#sum()
- */
- public double getSum() {
- return (double) sum.get();
- }
-
- public Snapshot getSnapshot() {
- return sample.getSnapshot();
- }
-
- private double getVariance() {
- if (getCount() <= 1) {
- return 0.0;
- }
- return variance.get()[1] / (getCount() - 1);
- }
-
- private void setMax(long potentialMax) {
- boolean done = false;
- while (!done) {
- final long currentMax = max.get();
- done = currentMax >= potentialMax || max.compareAndSet(currentMax, potentialMax);
- }
- }
-
- private void setMin(long potentialMin) {
- boolean done = false;
- while (!done) {
- final long currentMin = min.get();
- done = currentMin <= potentialMin || min.compareAndSet(currentMin, potentialMin);
- }
- }
-
- private void updateVariance(long value) {
- while (true) {
- final double[] oldValues = variance.get();
- final double[] newValues = new double[2];
- if (oldValues[0] == -1) {
- newValues[0] = value;
- newValues[1] = 0;
- } else {
- final double oldM = oldValues[0];
- final double oldS = oldValues[1];
-
- final double newM = oldM + ((value - oldM) / getCount());
- final double newS = oldS + ((value - oldM) * (value - newM));
-
- newValues[0] = newM;
- newValues[1] = newS;
- }
- if (variance.compareAndSet(oldValues, newValues)) {
- return;
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/src/java/org/apache/solr/util/stats/Meter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/stats/Meter.java b/solr/core/src/java/org/apache/solr/util/stats/Meter.java
deleted file mode 100644
index 8847fc4..0000000
--- a/solr/core/src/java/org/apache/solr/util/stats/Meter.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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.
- */
-/*
- * Forked from https://github.com/codahale/metrics
- */
-
-package org.apache.solr.util.stats;
-
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * A meter metric which measures mean throughput and one-, five-, and fifteen-minute
- * exponentially-weighted moving average throughputs.
- *
- * @see <a href="http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average">EMA</a>
- */
-public class Meter {
-
- private static final long TICK_INTERVAL = TimeUnit.SECONDS.toNanos(5);
-
- private final EWMA m1Rate = EWMA.oneMinuteEWMA();
- private final EWMA m5Rate = EWMA.fiveMinuteEWMA();
- private final EWMA m15Rate = EWMA.fifteenMinuteEWMA();
-
- private final AtomicLong count = new AtomicLong();
- private final long startTime;
- private final AtomicLong lastTick;
- private final TimeUnit rateUnit;
- private final String eventType;
- private final Clock clock;
-
- /**
- * Creates a new {@link Meter}.
- *
- * @param eventType the plural name of the event the meter is measuring (e.g., {@code
- * "requests"})
- * @param rateUnit the rate unit of the new meter
- * @param clock the clock to use for the meter ticks
- */
- Meter(String eventType, TimeUnit rateUnit, Clock clock) {
- this.rateUnit = rateUnit;
- this.eventType = eventType;
- this.clock = clock;
- this.startTime = this.clock.getTick();
- this.lastTick = new AtomicLong(startTime);
- }
-
- public TimeUnit getRateUnit() {
- return rateUnit;
- }
-
- public String getEventType() {
- return eventType;
- }
-
- /**
- * Updates the moving averages.
- */
- void tick() {
- m1Rate.tick();
- m5Rate.tick();
- m15Rate.tick();
- }
-
- /**
- * Mark the occurrence of an event.
- */
- public void mark() {
- mark(1);
- }
-
- /**
- * Mark the occurrence of a given number of events.
- *
- * @param n the number of events
- */
- public void mark(long n) {
- tickIfNecessary();
- count.addAndGet(n);
- m1Rate.update(n);
- m5Rate.update(n);
- m15Rate.update(n);
- }
-
- private void tickIfNecessary() {
- final long oldTick = lastTick.get();
- final long newTick = clock.getTick();
- final long age = newTick - oldTick;
- if (age > TICK_INTERVAL && lastTick.compareAndSet(oldTick, newTick)) {
- final long requiredTicks = age / TICK_INTERVAL;
- for (long i = 0; i < requiredTicks; i++) {
- tick();
- }
- }
- }
-
- public long getCount() {
- return count.get();
- }
-
- public double getFifteenMinuteRate() {
- tickIfNecessary();
- return m15Rate.getRate(rateUnit);
- }
-
- public double getFiveMinuteRate() {
- tickIfNecessary();
- return m5Rate.getRate(rateUnit);
- }
-
- public double getMeanRate() {
- if (getCount() == 0) {
- return 0.0;
- } else {
- final long elapsed = (clock.getTick() - startTime);
- return convertNsRate(getCount() / (double) elapsed);
- }
- }
-
- public double getOneMinuteRate() {
- tickIfNecessary();
- return m1Rate.getRate(rateUnit);
- }
-
- private double convertNsRate(double ratePerNs) {
- return ratePerNs * (double) rateUnit.toNanos(1);
- }
-}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/src/java/org/apache/solr/util/stats/Sample.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/stats/Sample.java b/solr/core/src/java/org/apache/solr/util/stats/Sample.java
deleted file mode 100644
index 29c69f4..0000000
--- a/solr/core/src/java/org/apache/solr/util/stats/Sample.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.
- */
-/*
- * Forked from https://github.com/codahale/metrics
- */
-
-package org.apache.solr.util.stats;
-
-/**
- * A statistically representative sample of a data stream.
- */
-public interface Sample {
- /**
- * Clears all recorded values.
- */
- void clear();
-
- /**
- * Returns the number of values recorded.
- *
- * @return the number of values recorded
- */
- int size();
-
- /**
- * Adds a new recorded value to the sample.
- *
- * @param value a new recorded value
- */
- void update(long value);
-
- /**
- * Returns a snapshot of the sample's values.
- *
- * @return a snapshot of the sample's values
- */
- Snapshot getSnapshot();
-}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/src/java/org/apache/solr/util/stats/Snapshot.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/stats/Snapshot.java b/solr/core/src/java/org/apache/solr/util/stats/Snapshot.java
deleted file mode 100644
index 78524bf..0000000
--- a/solr/core/src/java/org/apache/solr/util/stats/Snapshot.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * 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.
- */
-/*
- * Forked from https://github.com/codahale/metrics
- */
-
-package org.apache.solr.util.stats;
-
-import java.util.Arrays;
-import java.util.Collection;
-
-import static java.lang.Math.floor;
-
-/**
- * A statistical snapshot of a {@link Snapshot}.
- */
-public class Snapshot {
- private static final double MEDIAN_Q = 0.5;
- private static final double P75_Q = 0.75;
- private static final double P95_Q = 0.95;
- private static final double P98_Q = 0.98;
- private static final double P99_Q = 0.99;
- private static final double P999_Q = 0.999;
-
- private final double[] values;
-
- /**
- * Create a new {@link Snapshot} with the given values.
- *
- * @param values an unordered set of values in the sample
- */
- public Snapshot(Collection<Long> values) {
- final Object[] copy = values.toArray();
- this.values = new double[copy.length];
- for (int i = 0; i < copy.length; i++) {
- this.values[i] = (Long) copy[i];
- }
- Arrays.sort(this.values);
- }
-
- /**
- * Create a new {@link Snapshot} with the given values.
- *
- * @param values an unordered set of values in the sample
- */
- public Snapshot(double[] values) {
- this.values = new double[values.length];
- System.arraycopy(values, 0, this.values, 0, values.length);
- Arrays.sort(this.values);
- }
-
- /**
- * Returns the value at the given quantile.
- *
- * @param quantile a given quantile, in {@code [0..1]}
- * @return the value in the distribution at {@code quantile}
- */
- public double getValue(double quantile) {
- if (quantile < 0.0 || quantile > 1.0) {
- throw new IllegalArgumentException(quantile + " is not in [0..1]");
- }
-
- if (values.length == 0) {
- return 0.0;
- }
-
- final double pos = quantile * (values.length + 1);
-
- if (pos < 1) {
- return values[0];
- }
-
- if (pos >= values.length) {
- return values[values.length - 1];
- }
-
- final double lower = values[(int) pos - 1];
- final double upper = values[(int) pos];
- return lower + (pos - floor(pos)) * (upper - lower);
- }
-
- /**
- * Returns the number of values in the snapshot.
- *
- * @return the number of values in the snapshot
- */
- public int size() {
- return values.length;
- }
-
- /**
- * Returns the median value in the distribution.
- *
- * @return the median value in the distribution
- */
- public double getMedian() {
- return getValue(MEDIAN_Q);
- }
-
- /**
- * Returns the value at the 75th percentile in the distribution.
- *
- * @return the value at the 75th percentile in the distribution
- */
- public double get75thPercentile() {
- return getValue(P75_Q);
- }
-
- /**
- * Returns the value at the 95th percentile in the distribution.
- *
- * @return the value at the 95th percentile in the distribution
- */
- public double get95thPercentile() {
- return getValue(P95_Q);
- }
-
- /**
- * Returns the value at the 98th percentile in the distribution.
- *
- * @return the value at the 98th percentile in the distribution
- */
- public double get98thPercentile() {
- return getValue(P98_Q);
- }
-
- /**
- * Returns the value at the 99th percentile in the distribution.
- *
- * @return the value at the 99th percentile in the distribution
- */
- public double get99thPercentile() {
- return getValue(P99_Q);
- }
-
- /**
- * Returns the value at the 99.9th percentile in the distribution.
- *
- * @return the value at the 99.9th percentile in the distribution
- */
- public double get999thPercentile() {
- return getValue(P999_Q);
- }
-
- /**
- * Returns the entire set of values in the snapshot.
- *
- * @return the entire set of values in the snapshot
- */
- public double[] getValues() {
- return Arrays.copyOf(values, values.length);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/src/java/org/apache/solr/util/stats/Timer.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/stats/Timer.java b/solr/core/src/java/org/apache/solr/util/stats/Timer.java
deleted file mode 100644
index de5790c..0000000
--- a/solr/core/src/java/org/apache/solr/util/stats/Timer.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * 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.
- */
-/*
- * Forked from https://github.com/codahale/metrics
- */
-
-package org.apache.solr.util.stats;
-
-import org.apache.solr.util.stats.Histogram.SampleType;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.TimeUnit;
-
-/**
- * A timer metric which aggregates timing durations and provides duration statistics, plus
- * throughput statistics via {@link Meter}.
- */
-public class Timer {
-
- private final TimeUnit durationUnit, rateUnit;
- private final Meter meter;
- private final Histogram histogram = new Histogram(SampleType.BIASED);
- private final Clock clock;
-
- public Timer() {
- this(TimeUnit.MILLISECONDS, TimeUnit.SECONDS, Clock.defaultClock());
- }
-
- /**
- * Creates a new {@link Timer}.
- *
- * @param durationUnit the scale unit for this timer's duration metrics
- * @param rateUnit the scale unit for this timer's rate metrics
- * @param clock the clock used to calculate duration
- */
- public Timer(TimeUnit durationUnit, TimeUnit rateUnit, Clock clock) {
- this.durationUnit = durationUnit;
- this.rateUnit = rateUnit;
- this.meter = new Meter("calls", rateUnit, clock);
- this.clock = clock;
- clear();
- }
-
- /**
- * Returns the timer's duration scale unit.
- *
- * @return the timer's duration scale unit
- */
- public TimeUnit getDurationUnit() {
- return durationUnit;
- }
-
- public TimeUnit getRateUnit() {
- return rateUnit;
- }
-
- /**
- * Clears all recorded durations.
- */
- public void clear() {
- histogram.clear();
- }
-
- /**
- * Adds a recorded duration.
- *
- * @param duration the length of the duration
- * @param unit the scale unit of {@code duration}
- */
- public void update(long duration, TimeUnit unit) {
- update(unit.toNanos(duration));
- }
-
- /**
- * Times and records the duration of event.
- *
- * @param event a {@link Callable} whose {@link Callable#call()} method implements a process
- * whose duration should be timed
- * @param <T> the type of the value returned by {@code event}
- * @return the value returned by {@code event}
- * @throws Exception if {@code event} throws an {@link Exception}
- */
- public <T> T time(Callable<T> event) throws Exception {
- final long startTime = clock.getTick();
- try {
- return event.call();
- } finally {
- update(clock.getTick() - startTime);
- }
- }
-
- /**
- * Returns a timing {@link TimerContext}, which measures an elapsed time in nanoseconds.
- *
- * @return a new {@link TimerContext}
- */
- public TimerContext time() {
- return new TimerContext(this, clock);
- }
-
- public long getCount() {
- return histogram.getCount();
- }
-
- public double getFifteenMinuteRate() {
- return meter.getFifteenMinuteRate();
- }
-
- public double getFiveMinuteRate() {
- return meter.getFiveMinuteRate();
- }
-
- public double getMeanRate() {
- return meter.getMeanRate();
- }
-
- public double getOneMinuteRate() {
- return meter.getOneMinuteRate();
- }
-
- /**
- * Returns the longest recorded duration.
- *
- * @return the longest recorded duration
- */
- public double getMax() {
- return convertFromNS(histogram.getMax());
- }
-
- /**
- * Returns the shortest recorded duration.
- *
- * @return the shortest recorded duration
- */
- public double getMin() {
- return convertFromNS(histogram.getMin());
- }
-
- /**
- * Returns the arithmetic mean of all recorded durations.
- *
- * @return the arithmetic mean of all recorded durations
- */
- public double getMean() {
- return convertFromNS(histogram.getMean());
- }
-
- /**
- * Returns the standard deviation of all recorded durations.
- *
- * @return the standard deviation of all recorded durations
- */
- public double getStdDev() {
- return convertFromNS(histogram.getStdDev());
- }
-
- /**
- * Returns the sum of all recorded durations.
- *
- * @return the sum of all recorded durations
- */
- public double getSum() {
- return convertFromNS(histogram.getSum());
- }
-
- public Snapshot getSnapshot() {
- final double[] values = histogram.getSnapshot().getValues();
- final double[] converted = new double[values.length];
- for (int i = 0; i < values.length; i++) {
- converted[i] = convertFromNS(values[i]);
- }
- return new Snapshot(converted);
- }
-
- public String getEventType() {
- return meter.getEventType();
- }
-
- private void update(long duration) {
- if (duration >= 0) {
- histogram.update(duration);
- meter.mark();
- }
- }
-
- private double convertFromNS(double ns) {
- return ns / TimeUnit.NANOSECONDS.convert(1, durationUnit);
- }
-}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/src/java/org/apache/solr/util/stats/TimerContext.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/stats/TimerContext.java b/solr/core/src/java/org/apache/solr/util/stats/TimerContext.java
deleted file mode 100644
index 125b982..0000000
--- a/solr/core/src/java/org/apache/solr/util/stats/TimerContext.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.
- */
-/*
- * Forked from https://github.com/codahale/metrics
- */
-
-package org.apache.solr.util.stats;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * A timing context.
- *
- * @see Timer#time()
- */
-public class TimerContext {
- private final Timer timer;
- private final Clock clock;
- private final long startTime;
-
- /**
- * Creates a new {@link TimerContext} with the current time as its starting value and with the
- * given {@link Timer}.
- *
- * @param timer the {@link Timer} to report the elapsed time to
- */
- TimerContext(Timer timer, Clock clock) {
- this.timer = timer;
- this.clock = clock;
- this.startTime = clock.getTick();
- }
-
- /**
- * Stops recording the elapsed time, updates the timer and returns the elapsed time
- */
- public long stop() {
- final long elapsedNanos = clock.getTick() - startTime;
- timer.update(elapsedNanos, TimeUnit.NANOSECONDS);
- return elapsedNanos;
- }
-}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/src/java/org/apache/solr/util/stats/TimerUtils.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/stats/TimerUtils.java b/solr/core/src/java/org/apache/solr/util/stats/TimerUtils.java
new file mode 100644
index 0000000..0195db3
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/util/stats/TimerUtils.java
@@ -0,0 +1,58 @@
+/*
+ * 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.solr.util.stats;
+
+import java.util.concurrent.TimeUnit;
+
+import com.codahale.metrics.Snapshot;
+import com.codahale.metrics.Timer;
+import org.apache.solr.common.util.NamedList;
+
+/**
+ * Solr specific {@link Timer} utility functions.
+ */
+public class TimerUtils {
+
+ /**
+ * Adds metrics from a Timer to a NamedList, using well-known names.
+ * @param lst The NamedList to add the metrics data to
+ * @param timer The Timer to extract the metrics from
+ */
+ public static void addMetrics(NamedList<Object> lst, Timer timer) {
+ Snapshot snapshot = timer.getSnapshot();
+ lst.add("avgRequestsPerMinute", timer.getMeanRate());
+ lst.add("5minRateRequestsPerMinute", timer.getFiveMinuteRate());
+ lst.add("15minRateRequestsPerMinute", timer.getFifteenMinuteRate());
+ lst.add("avgTimePerRequest", nsToMs(snapshot.getMean()));
+ lst.add("medianRequestTime", nsToMs(snapshot.getMedian()));
+ lst.add("75thPcRequestTime", nsToMs(snapshot.get75thPercentile()));
+ lst.add("95thPcRequestTime", nsToMs(snapshot.get95thPercentile()));
+ lst.add("99thPcRequestTime", nsToMs(snapshot.get99thPercentile()));
+ lst.add("999thPcRequestTime", nsToMs(snapshot.get999thPercentile()));
+ }
+
+ /**
+ * Converts a double representing nanoseconds to a double representing milliseconds.
+ *
+ * @param ns the amount of time in nanoseconds
+ * @return the amount of time in milliseconds
+ */
+ static double nsToMs(double ns) {
+ return ns / TimeUnit.MILLISECONDS.toNanos(1);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/src/java/org/apache/solr/util/stats/UniformSample.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/stats/UniformSample.java b/solr/core/src/java/org/apache/solr/util/stats/UniformSample.java
deleted file mode 100644
index 81c8ed1..0000000
--- a/solr/core/src/java/org/apache/solr/util/stats/UniformSample.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * 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.
- */
-/*
- * Forked from https://github.com/codahale/metrics
- */
-
-package org.apache.solr.util.stats;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicLongArray;
-
-/**
- * A random sample of a stream of {@code long}s. Uses Vitter's Algorithm R to produce a
- * statistically representative sample.
- *
- * @see <a href="http://www.cs.umd.edu/~samir/498/vitter.pdf">Random Sampling with a Reservoir</a>
- */
-public class UniformSample implements Sample {
-
- private static final int BITS_PER_LONG = 63;
- private final AtomicLong count = new AtomicLong();
- private final AtomicLongArray values;
- //TODO: Maybe replace with a Mersenne twister for better distribution
- private static final Random random = new Random();
-
- /**
- * Creates a new {@link UniformSample}.
- *
- * @param reservoirSize the number of samples to keep in the sampling reservoir
- */
- public UniformSample(int reservoirSize) {
- this.values = new AtomicLongArray(reservoirSize);
- clear();
- }
-
- @Override
- public void clear() {
- for (int i = 0; i < values.length(); i++) {
- values.set(i, 0);
- }
- count.set(0);
- }
-
- @Override
- public int size() {
- final long c = count.get();
- if (c > values.length()) {
- return values.length();
- }
- return (int) c;
- }
-
- @Override
- public void update(long value) {
- final long c = count.incrementAndGet();
- if (c <= values.length()) {
- values.set((int) c - 1, value);
- } else {
- final long r = nextLong(c);
- if (r < values.length()) {
- values.set((int) r, value);
- }
- }
- }
-
- /**
- * Get a pseudo-random long uniformly between 0 and n-1. Stolen from
- * {@link java.util.Random#nextInt()}.
- *
- * @param n the bound
- * @return a value select randomly from the range {@code [0..n)}.
- */
- private static long nextLong(long n) {
- long bits, val;
- do {
- bits = random.nextLong() & (~(1L << BITS_PER_LONG));
- val = bits % n;
- } while (bits - val + (n - 1) < 0L);
- return val;
- }
-
- @Override
- public Snapshot getSnapshot() {
- final int s = size();
- final List<Long> copy = new ArrayList<>(s);
- for (int i = 0; i < s; i++) {
- copy.add(values.get(i));
- }
- return new Snapshot(copy);
- }
-}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/src/test/org/apache/solr/cloud/OverseerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/OverseerTest.java b/solr/core/src/test/org/apache/solr/cloud/OverseerTest.java
index ea833e5..48b53d1 100644
--- a/solr/core/src/test/org/apache/solr/cloud/OverseerTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/OverseerTest.java
@@ -34,6 +34,8 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
+import com.codahale.metrics.Snapshot;
+import com.codahale.metrics.Timer;
import org.apache.lucene.util.LuceneTestCase.Slow;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.cloud.overseer.OverseerAction;
@@ -52,9 +54,6 @@ import org.apache.solr.handler.component.HttpShardHandlerFactory;
import org.apache.solr.update.UpdateShardHandler;
import org.apache.solr.update.UpdateShardHandlerConfig;
import org.apache.solr.util.DefaultSolrThreadFactory;
-import org.apache.solr.util.stats.Snapshot;
-import org.apache.solr.util.stats.Timer;
-import org.apache.solr.util.stats.TimerContext;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.KeeperException.NoNodeException;
@@ -1027,7 +1026,7 @@ public class OverseerTest extends SolrTestCaseJ4 {
q.offer(Utils.toJSON(m));
Timer t = new Timer();
- TimerContext context = t.time();
+ Timer.Context context = t.time();
try {
overseerClient = electNewOverseer(server.getZkAddress());
assertTrue(overseers.size() > 0);
@@ -1072,16 +1071,19 @@ public class OverseerTest extends SolrTestCaseJ4 {
private void printTimingStats(Timer timer) {
Snapshot snapshot = timer.getSnapshot();
- log.info("\t totalTime: {}", timer.getSum());
log.info("\t avgRequestsPerMinute: {}", timer.getMeanRate());
log.info("\t 5minRateRequestsPerMinute: {}", timer.getFiveMinuteRate());
log.info("\t 15minRateRequestsPerMinute: {}", timer.getFifteenMinuteRate());
- log.info("\t avgTimePerRequest: {}", timer.getMean());
- log.info("\t medianRequestTime: {}", snapshot.getMedian());
- log.info("\t 75thPctlRequestTime: {}", snapshot.get75thPercentile());
- log.info("\t 95thPctlRequestTime: {}", snapshot.get95thPercentile());
- log.info("\t 99thPctlRequestTime: {}", snapshot.get99thPercentile());
- log.info("\t 999thPctlRequestTime: {}", snapshot.get999thPercentile());
+ log.info("\t avgTimePerRequest: {}", nsToMs(snapshot.getMean()));
+ log.info("\t medianRequestTime: {}", nsToMs(snapshot.getMedian()));
+ log.info("\t 75thPcRequestTime: {}", nsToMs(snapshot.get75thPercentile()));
+ log.info("\t 95thPcRequestTime: {}", nsToMs(snapshot.get95thPercentile()));
+ log.info("\t 99thPcRequestTime: {}", nsToMs(snapshot.get99thPercentile()));
+ log.info("\t 999thPcRequestTime: {}", nsToMs(snapshot.get999thPercentile()));
+ }
+
+ private static long nsToMs(double ns) {
+ return TimeUnit.NANOSECONDS.convert((long)ns, TimeUnit.MILLISECONDS);
}
private void close(MockZKController mockController) {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/src/test/org/apache/solr/core/RequestHandlersTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/RequestHandlersTest.java b/solr/core/src/test/org/apache/solr/core/RequestHandlersTest.java
index ca45f7c..9a953e1 100644
--- a/solr/core/src/test/org/apache/solr/core/RequestHandlersTest.java
+++ b/solr/core/src/test/org/apache/solr/core/RequestHandlersTest.java
@@ -108,8 +108,8 @@ public class RequestHandlersTest extends SolrTestCaseJ4 {
NamedList updateStats = updateHandler.getStatistics();
NamedList termStats = termHandler.getStatistics();
- Double updateTime = (Double) updateStats.get("totalTime");
- Double termTime = (Double) termStats.get("totalTime");
+ Double updateTime = (Double) updateStats.get("avgTimePerRequest");
+ Double termTime = (Double) termStats.get("avgTimePerRequest");
assertFalse("RequestHandlers should not share statistics!", updateTime.equals(termTime));
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/core/src/test/org/apache/solr/util/stats/TimerUtilsTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/util/stats/TimerUtilsTest.java b/solr/core/src/test/org/apache/solr/util/stats/TimerUtilsTest.java
new file mode 100644
index 0000000..c051293
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/util/stats/TimerUtilsTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.solr.util.stats;
+
+import java.util.concurrent.TimeUnit;
+
+import com.codahale.metrics.Snapshot;
+import com.codahale.metrics.Timer;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.common.util.SimpleOrderedMap;
+import org.junit.Test;
+
+public class TimerUtilsTest extends SolrTestCaseJ4 {
+
+ @Test
+ public void testSolrTimerGetSnapshot() {
+ // create a timer with up to 100 data points
+ final Timer timer = new Timer();
+ final int iterations = random().nextInt(100);
+ for (int i = 0; i < iterations; ++i) {
+ timer.update(random().nextInt(), TimeUnit.NANOSECONDS);
+ }
+ // obtain timer metrics
+ final NamedList<Object> lst = new SimpleOrderedMap<>();
+ TimerUtils.addMetrics(lst, timer);
+ // check that expected metrics were obtained
+ assertEquals(lst.size(), 9);
+ final Snapshot snapshot = timer.getSnapshot();
+ // cannot test avgRequestsPerMinute directly because mean rate changes as time increases!
+ // assertEquals(lst.get("avgRequestsPerMinute"), timer.getMeanRate());
+ assertEquals(lst.get("5minRateRequestsPerMinute"), timer.getFiveMinuteRate());
+ assertEquals(lst.get("15minRateRequestsPerMinute"), timer.getFifteenMinuteRate());
+ assertEquals(lst.get("avgTimePerRequest"), TimerUtils.nsToMs(snapshot.getMean()));
+ assertEquals(lst.get("medianRequestTime"), TimerUtils.nsToMs(snapshot.getMedian()));
+ assertEquals(lst.get("75thPcRequestTime"), TimerUtils.nsToMs(snapshot.get75thPercentile()));
+ assertEquals(lst.get("95thPcRequestTime"), TimerUtils.nsToMs(snapshot.get95thPercentile()));
+ assertEquals(lst.get("99thPcRequestTime"), TimerUtils.nsToMs(snapshot.get99thPercentile()));
+ assertEquals(lst.get("999thPcRequestTime"), TimerUtils.nsToMs(snapshot.get999thPercentile()));
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/licenses/metrics-core-3.0.1.jar.sha1
----------------------------------------------------------------------
diff --git a/solr/licenses/metrics-core-3.0.1.jar.sha1 b/solr/licenses/metrics-core-3.0.1.jar.sha1
deleted file mode 100644
index 1d42f50..0000000
--- a/solr/licenses/metrics-core-3.0.1.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-1e98427c7f6e53363b598e2943e50903ce4f3657
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/licenses/metrics-core-3.1.2.jar.sha1
----------------------------------------------------------------------
diff --git a/solr/licenses/metrics-core-3.1.2.jar.sha1 b/solr/licenses/metrics-core-3.1.2.jar.sha1
new file mode 100644
index 0000000..ca9ac38
--- /dev/null
+++ b/solr/licenses/metrics-core-3.1.2.jar.sha1
@@ -0,0 +1 @@
+224f03afd2521c6c94632f566beb1bb5ee32cf07
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/licenses/metrics-healthchecks-3.0.1.jar.sha1
----------------------------------------------------------------------
diff --git a/solr/licenses/metrics-healthchecks-3.0.1.jar.sha1 b/solr/licenses/metrics-healthchecks-3.0.1.jar.sha1
deleted file mode 100644
index 4c1055f..0000000
--- a/solr/licenses/metrics-healthchecks-3.0.1.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-bec37e61ebe40bf0f52f3fc8b7df57b5c1773682
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ff6da666/solr/licenses/metrics-healthchecks-3.1.2.jar.sha1
----------------------------------------------------------------------
diff --git a/solr/licenses/metrics-healthchecks-3.1.2.jar.sha1 b/solr/licenses/metrics-healthchecks-3.1.2.jar.sha1
new file mode 100644
index 0000000..946c8d8
--- /dev/null
+++ b/solr/licenses/metrics-healthchecks-3.1.2.jar.sha1
@@ -0,0 +1 @@
+e32a01aa7ca4070676e22e707272422baa0f7ecd