Remove yammer/codehale dependencies and augumentations
This commit is contained in:
parent
824638594b
commit
9c2d6cec51
14
pom.xml
14
pom.xml
@ -10,8 +10,8 @@
|
||||
<name>Scylla JMX</name>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.target>1.7</maven.compiler.target>
|
||||
<maven.compiler.source>1.7</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@ -71,21 +71,11 @@
|
||||
<artifactId>guava</artifactId>
|
||||
<version>18.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.yammer.metrics</groupId>
|
||||
<artifactId>metrics-core</artifactId>
|
||||
<version>2.2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.collections</groupId>
|
||||
<artifactId>google-collections</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mx4j</groupId>
|
||||
<artifactId>mx4j</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
@ -1,315 +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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2015 Cloudius Systems
|
||||
*
|
||||
* Modified by Cloudius Systems
|
||||
*/
|
||||
|
||||
package com.scylladb.jmx.utils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicLongArray;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class EstimatedHistogram {
|
||||
/**
|
||||
* The series of values to which the counts in `buckets` correspond: 1, 2,
|
||||
* 3, 4, 5, 6, 7, 8, 10, 12, 14, 17, 20, etc. Thus, a `buckets` of [0, 0, 1,
|
||||
* 10] would mean we had seen one value of 3 and 10 values of 4.
|
||||
*
|
||||
* The series starts at 1 and grows by 1.2 each time (rounding and removing
|
||||
* duplicates). It goes from 1 to around 36M by default (creating 90+1
|
||||
* buckets), which will give us timing resolution from microseconds to 36
|
||||
* seconds, with less precision as the numbers get larger.
|
||||
*
|
||||
* Each bucket represents values from (previous bucket offset, current
|
||||
* offset].
|
||||
*/
|
||||
private final long[] bucketOffsets;
|
||||
|
||||
// buckets is one element longer than bucketOffsets -- the last element is
|
||||
// values greater than the last offset
|
||||
final AtomicLongArray buckets;
|
||||
|
||||
public EstimatedHistogram() {
|
||||
this(90);
|
||||
}
|
||||
|
||||
public EstimatedHistogram(int bucketCount) {
|
||||
bucketOffsets = newOffsets(bucketCount);
|
||||
buckets = new AtomicLongArray(bucketOffsets.length + 1);
|
||||
}
|
||||
|
||||
public EstimatedHistogram(long[] offsets, long[] bucketData) {
|
||||
assert bucketData.length == offsets.length + 1;
|
||||
bucketOffsets = offsets;
|
||||
buckets = new AtomicLongArray(bucketData);
|
||||
}
|
||||
|
||||
|
||||
public EstimatedHistogram(long[] bucketData) {
|
||||
bucketOffsets = newOffsets(bucketData.length - 1);
|
||||
buckets = new AtomicLongArray(bucketData);
|
||||
}
|
||||
|
||||
private static long[] newOffsets(int size) {
|
||||
if (size <= 0) {
|
||||
return new long[0];
|
||||
}
|
||||
long[] result = new long[size];
|
||||
long last = 1;
|
||||
result[0] = last;
|
||||
for (int i = 1; i < size; i++) {
|
||||
long next = Math.round(last * 1.2);
|
||||
if (next == last)
|
||||
next++;
|
||||
result[i] = next;
|
||||
last = next;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the histogram values corresponding to each bucket index
|
||||
*/
|
||||
public long[] getBucketOffsets() {
|
||||
return bucketOffsets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the count of the bucket closest to n, rounding UP.
|
||||
*
|
||||
* @param n
|
||||
*/
|
||||
public void add(long n) {
|
||||
int index = Arrays.binarySearch(bucketOffsets, n);
|
||||
if (index < 0) {
|
||||
// inexact match, take the first bucket higher than n
|
||||
index = -index - 1;
|
||||
}
|
||||
// else exact match; we're good
|
||||
buckets.incrementAndGet(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the count in the given bucket
|
||||
*/
|
||||
long get(int bucket) {
|
||||
return buckets.get(bucket);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param reset
|
||||
* zero out buckets afterwards if true
|
||||
* @return a long[] containing the current histogram buckets
|
||||
*/
|
||||
public long[] getBuckets(boolean reset) {
|
||||
final int len = buckets.length();
|
||||
long[] rv = new long[len];
|
||||
|
||||
if (reset)
|
||||
for (int i = 0; i < len; i++)
|
||||
rv[i] = buckets.getAndSet(i, 0L);
|
||||
else
|
||||
for (int i = 0; i < len; i++)
|
||||
rv[i] = buckets.get(i);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the smallest value that could have been added to this histogram
|
||||
*/
|
||||
public long min() {
|
||||
for (int i = 0; i < buckets.length(); i++) {
|
||||
if (buckets.get(i) > 0)
|
||||
return i == 0 ? 0 : 1 + bucketOffsets[i - 1];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the largest value that could have been added to this histogram.
|
||||
* If the histogram overflowed, returns Long.MAX_VALUE.
|
||||
*/
|
||||
public long max() {
|
||||
int lastBucket = buckets.length() - 1;
|
||||
if (buckets.get(lastBucket) > 0)
|
||||
return Long.MAX_VALUE;
|
||||
|
||||
for (int i = lastBucket - 1; i >= 0; i--) {
|
||||
if (buckets.get(i) > 0)
|
||||
return bucketOffsets[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param percentile
|
||||
* @return estimated value at given percentile
|
||||
*/
|
||||
public long percentile(double percentile) {
|
||||
assert percentile >= 0 && percentile <= 1.0;
|
||||
int lastBucket = buckets.length() - 1;
|
||||
if (buckets.get(lastBucket) > 0)
|
||||
throw new IllegalStateException(
|
||||
"Unable to compute when histogram overflowed");
|
||||
|
||||
long pcount = (long) Math.floor(count() * percentile);
|
||||
if (pcount == 0)
|
||||
return 0;
|
||||
|
||||
long elements = 0;
|
||||
for (int i = 0; i < lastBucket; i++) {
|
||||
elements += buckets.get(i);
|
||||
if (elements >= pcount)
|
||||
return bucketOffsets[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the mean histogram value (average of bucket offsets, weighted by
|
||||
* count)
|
||||
* @throws IllegalStateException
|
||||
* if any values were greater than the largest bucket threshold
|
||||
*/
|
||||
public long mean() {
|
||||
int lastBucket = buckets.length() - 1;
|
||||
if (buckets.get(lastBucket) > 0)
|
||||
throw new IllegalStateException(
|
||||
"Unable to compute ceiling for max when histogram overflowed");
|
||||
|
||||
long elements = 0;
|
||||
long sum = 0;
|
||||
for (int i = 0; i < lastBucket; i++) {
|
||||
long bCount = buckets.get(i);
|
||||
elements += bCount;
|
||||
sum += bCount * bucketOffsets[i];
|
||||
}
|
||||
|
||||
return (long) Math.ceil((double) sum / elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the total number of non-zero values
|
||||
*/
|
||||
public long count() {
|
||||
long sum = 0L;
|
||||
for (int i = 0; i < buckets.length(); i++)
|
||||
sum += buckets.get(i);
|
||||
return sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this histogram has overflowed -- that is, a value larger
|
||||
* than our largest bucket could bound was added
|
||||
*/
|
||||
public boolean isOverflowed() {
|
||||
return buckets.get(buckets.length() - 1) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* log.debug() every record in the histogram
|
||||
*
|
||||
* @param log
|
||||
*/
|
||||
public void log(Logger log) {
|
||||
// only print overflow if there is any
|
||||
int nameCount;
|
||||
if (buckets.get(buckets.length() - 1) == 0)
|
||||
nameCount = buckets.length() - 1;
|
||||
else
|
||||
nameCount = buckets.length();
|
||||
String[] names = new String[nameCount];
|
||||
|
||||
int maxNameLength = 0;
|
||||
for (int i = 0; i < nameCount; i++) {
|
||||
names[i] = nameOfRange(bucketOffsets, i);
|
||||
maxNameLength = Math.max(maxNameLength, names[i].length());
|
||||
}
|
||||
|
||||
// emit log records
|
||||
String formatstr = "%" + maxNameLength + "s: %d";
|
||||
for (int i = 0; i < nameCount; i++) {
|
||||
long count = buckets.get(i);
|
||||
// sort-of-hack to not print empty ranges at the start that are only
|
||||
// used to demarcate the
|
||||
// first populated range. for code clarity we don't omit this record
|
||||
// from the maxNameLength
|
||||
// calculation, and accept the unnecessary whitespace prefixes that
|
||||
// will occasionally occur
|
||||
if (i == 0 && count == 0)
|
||||
continue;
|
||||
log.debug(String.format(formatstr, names[i], count));
|
||||
}
|
||||
}
|
||||
|
||||
private static String nameOfRange(long[] bucketOffsets, int index) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
appendRange(sb, bucketOffsets, index);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static void appendRange(StringBuilder sb, long[] bucketOffsets,
|
||||
int index) {
|
||||
sb.append("[");
|
||||
if (index == 0)
|
||||
if (bucketOffsets[0] > 0)
|
||||
// by original definition, this histogram is for values greater
|
||||
// than zero only;
|
||||
// if values of 0 or less are required, an entry of lb-1 must be
|
||||
// inserted at the start
|
||||
sb.append("1");
|
||||
else
|
||||
sb.append("-Inf");
|
||||
else
|
||||
sb.append(bucketOffsets[index - 1] + 1);
|
||||
sb.append("..");
|
||||
if (index == bucketOffsets.length)
|
||||
sb.append("Inf");
|
||||
else
|
||||
sb.append(bucketOffsets[index]);
|
||||
sb.append("]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
|
||||
if (!(o instanceof EstimatedHistogram))
|
||||
return false;
|
||||
|
||||
EstimatedHistogram that = (EstimatedHistogram) o;
|
||||
return Arrays.equals(getBucketOffsets(), that.getBucketOffsets())
|
||||
&& Arrays.equals(getBuckets(false), that.getBuckets(false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(getBucketOffsets(), getBuckets(false));
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
package com.scylladb.jmx.utils;
|
||||
/*
|
||||
* Copyright (C) 2015 ScyllaDB
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of Scylla.
|
||||
*
|
||||
* Scylla is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Scylla is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Scylla. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* RecentEstimatedHistogram In the (deprecated) 'recent' functionality, each
|
||||
* call to get the values cleans the value.
|
||||
*
|
||||
* The RecentEstimatedHistogram support recent call to EstimatedHistogram.
|
||||
* It holds the latest total values and a call to getBuckets return the delta.
|
||||
*
|
||||
*/
|
||||
public class RecentEstimatedHistogram extends EstimatedHistogram {
|
||||
public RecentEstimatedHistogram() {
|
||||
}
|
||||
|
||||
public RecentEstimatedHistogram(int bucketCount) {
|
||||
super(bucketCount);
|
||||
}
|
||||
|
||||
public RecentEstimatedHistogram(long[] offsets, long[] bucketData) {
|
||||
super(offsets, bucketData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current buckets to new value and return the delta from the last
|
||||
* getBuckets call
|
||||
*
|
||||
* @param bucketData
|
||||
* - new bucket value
|
||||
* @return a long[] containing the current histogram difference buckets
|
||||
*/
|
||||
public long[] getBuckets(long[] bucketData) {
|
||||
if (bucketData.length == 0) {
|
||||
return new long[0];
|
||||
}
|
||||
final int len = buckets.length();
|
||||
long[] rv = new long[len];
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
rv[i] = bucketData[i];
|
||||
rv[i] -= buckets.getAndSet(i, bucketData[i]);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package com.yammer.metrics.core;
|
||||
/*
|
||||
* Copyright 2015 Cloudius Systems
|
||||
*
|
||||
* Modified by Cloudius Systems
|
||||
*/
|
||||
|
||||
import com.scylladb.jmx.api.APIClient;
|
||||
import com.yammer.metrics.core.Counter;
|
||||
|
||||
public class APICounter extends Counter {
|
||||
String url;
|
||||
private APIClient c = new APIClient();
|
||||
|
||||
public APICounter(String _url) {
|
||||
super();
|
||||
url = _url;
|
||||
}
|
||||
/**
|
||||
* Returns the counter's current value.
|
||||
*
|
||||
* @return the counter's current value
|
||||
*/
|
||||
public long count() {
|
||||
return c.getLongValue(url);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,215 +0,0 @@
|
||||
package com.yammer.metrics.core;
|
||||
|
||||
/*
|
||||
* Copyright 2015 Cloudius Systems
|
||||
*
|
||||
* Modified by Cloudius Systems
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.json.JsonObject;
|
||||
|
||||
import com.scylladb.jmx.api.APIClient;
|
||||
import com.yammer.metrics.stats.Sample;
|
||||
import com.yammer.metrics.stats.Snapshot;
|
||||
|
||||
public class APIHistogram extends Histogram {
|
||||
Field countField;
|
||||
Field minField;
|
||||
Field maxField;
|
||||
Field sumField;
|
||||
Field varianceField;
|
||||
Field sampleField;
|
||||
|
||||
long last_update = 0;
|
||||
static final long UPDATE_INTERVAL = 50;
|
||||
long updateInterval;
|
||||
String url;
|
||||
private APIClient c = new APIClient();
|
||||
|
||||
private void setFields() {
|
||||
try {
|
||||
minField = Histogram.class.getDeclaredField("min");
|
||||
minField.setAccessible(true);
|
||||
maxField = Histogram.class.getDeclaredField("max");
|
||||
maxField.setAccessible(true);
|
||||
sumField = Histogram.class.getDeclaredField("sum");
|
||||
sumField.setAccessible(true);
|
||||
varianceField = Histogram.class.getDeclaredField("variance");
|
||||
varianceField.setAccessible(true);
|
||||
sampleField = Histogram.class.getDeclaredField("sample");
|
||||
sampleField.setAccessible(true);
|
||||
countField = Histogram.class.getDeclaredField("count");
|
||||
countField.setAccessible(true);
|
||||
try {
|
||||
getCount().set(0);
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
// There's no reason to get here
|
||||
// and there's nothing we can do even if we would
|
||||
}
|
||||
} catch (NoSuchFieldException | SecurityException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public AtomicLong getMin() throws IllegalArgumentException,
|
||||
IllegalAccessException {
|
||||
return (AtomicLong) minField.get(this);
|
||||
}
|
||||
|
||||
public AtomicLong getMax() throws IllegalArgumentException,
|
||||
IllegalAccessException {
|
||||
return (AtomicLong) maxField.get(this);
|
||||
}
|
||||
|
||||
public AtomicLong getSum() throws IllegalArgumentException,
|
||||
IllegalAccessException {
|
||||
return (AtomicLong) sumField.get(this);
|
||||
}
|
||||
|
||||
public AtomicLong getCount() throws IllegalArgumentException,
|
||||
IllegalAccessException {
|
||||
return (AtomicLong) countField.get(this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public AtomicReference<double[]> getVariance()
|
||||
throws IllegalArgumentException, IllegalAccessException {
|
||||
return (AtomicReference<double[]>) varianceField.get(this);
|
||||
}
|
||||
|
||||
public Sample getSample() throws IllegalArgumentException,
|
||||
IllegalAccessException {
|
||||
return (Sample) sampleField.get(this);
|
||||
}
|
||||
|
||||
public APIHistogram(String url, Sample sample) {
|
||||
super(sample);
|
||||
setFields();
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public APIHistogram(String url, SampleType type, long updateInterval) {
|
||||
super(type);
|
||||
setFields();
|
||||
this.url = url;
|
||||
this.updateInterval = updateInterval;
|
||||
}
|
||||
|
||||
public APIHistogram(String url, SampleType type) {
|
||||
this(url, type, UPDATE_INTERVAL);
|
||||
}
|
||||
|
||||
public void updateValue(HistogramValues vals) {
|
||||
try {
|
||||
if (vals.sample != null) {
|
||||
for (long v : vals.sample) {
|
||||
getSample().update(v);
|
||||
}
|
||||
}
|
||||
getCount().set(vals.count);
|
||||
getMax().set(vals.max);
|
||||
getMin().set(vals.min);
|
||||
getSum().set(vals.sum);
|
||||
double[] newValue = new double[2];
|
||||
newValue[0] = vals.mean;
|
||||
newValue[1] = vals.variance;
|
||||
getVariance().getAndSet(newValue);
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void update() {
|
||||
if (url == null) {
|
||||
return;
|
||||
}
|
||||
long now = System.currentTimeMillis();
|
||||
if (now - last_update < UPDATE_INTERVAL) {
|
||||
return;
|
||||
}
|
||||
last_update = now;
|
||||
clear();
|
||||
JsonObject obj = c.getJsonObj(url, null);
|
||||
if (obj.containsKey("hist")) {
|
||||
updateValue(APIClient.json2histogram(obj.getJsonObject("hist")));
|
||||
} else {
|
||||
updateValue(APIClient.json2histogram(obj));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of values recorded.
|
||||
*
|
||||
* @return the number of values recorded
|
||||
*/
|
||||
public long count() {
|
||||
update();
|
||||
return super.count();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.yammer.metrics.core.Summarizable#max()
|
||||
*/
|
||||
@Override
|
||||
public double max() {
|
||||
update();
|
||||
return super.max();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.yammer.metrics.core.Summarizable#min()
|
||||
*/
|
||||
@Override
|
||||
public double min() {
|
||||
update();
|
||||
return super.min();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.yammer.metrics.core.Summarizable#mean()
|
||||
*/
|
||||
@Override
|
||||
public double mean() {
|
||||
update();
|
||||
return super.mean();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.yammer.metrics.core.Summarizable#stdDev()
|
||||
*/
|
||||
@Override
|
||||
public double stdDev() {
|
||||
update();
|
||||
return super.stdDev();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.yammer.metrics.core.Summarizable#sum()
|
||||
*/
|
||||
@Override
|
||||
public double sum() {
|
||||
update();
|
||||
return super.sum();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Snapshot getSnapshot() {
|
||||
update();
|
||||
return super.getSnapshot();
|
||||
}
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
package com.yammer.metrics.core;
|
||||
/*
|
||||
* Copyright (C) 2015 ScyllaDB
|
||||
*/
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
/*
|
||||
* This file is part of Scylla.
|
||||
*
|
||||
* Scylla is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Scylla is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Scylla. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by ScyllaDB
|
||||
*/
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.json.JsonArray;
|
||||
import javax.json.JsonObject;
|
||||
|
||||
import com.scylladb.jmx.api.APIClient;
|
||||
|
||||
public class APIMeter extends Meter {
|
||||
public final static long CACHE_DURATION = 1000;
|
||||
|
||||
String url;
|
||||
String eventType;
|
||||
TimeUnit rateUnit;
|
||||
APIClient c = new APIClient();
|
||||
long count;
|
||||
double oneMinuteRate;
|
||||
double fiveMinuteRate;
|
||||
double fifteenMinuteRate;
|
||||
double meanRate;
|
||||
|
||||
public APIMeter(String url, ScheduledExecutorService tickThread,
|
||||
String eventType, TimeUnit rateUnit) {
|
||||
super(tickThread, eventType, rateUnit, Clock.defaultClock());
|
||||
super.stop();
|
||||
this.url = url;
|
||||
this.eventType = eventType;
|
||||
this.rateUnit = rateUnit;
|
||||
}
|
||||
|
||||
public void fromJson(JsonObject obj) {
|
||||
JsonArray rates = obj.getJsonArray("rates");
|
||||
int i = 0;
|
||||
oneMinuteRate = rates.getJsonNumber(i++).doubleValue();
|
||||
fiveMinuteRate = rates.getJsonNumber(i++).doubleValue();
|
||||
fifteenMinuteRate = rates.getJsonNumber(i++).doubleValue();
|
||||
meanRate = obj.getJsonNumber("mean_rate").doubleValue();
|
||||
count = obj.getJsonNumber("count").longValue();
|
||||
}
|
||||
|
||||
public void update_fields() {
|
||||
if (url != null) {
|
||||
fromJson(c.getJsonObj(url, null, CACHE_DURATION));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeUnit rateUnit() {
|
||||
return rateUnit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String eventType() {
|
||||
return eventType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
update_fields();
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double fifteenMinuteRate() {
|
||||
update_fields();
|
||||
return fifteenMinuteRate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double fiveMinuteRate() {
|
||||
update_fields();
|
||||
return fiveMinuteRate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double meanRate() {
|
||||
update_fields();
|
||||
return meanRate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double oneMinuteRate() {
|
||||
update_fields();
|
||||
return oneMinuteRate;
|
||||
}
|
||||
|
||||
}
|
@ -1,384 +0,0 @@
|
||||
package com.yammer.metrics.core;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.yammer.metrics.core.APICounter;
|
||||
import com.yammer.metrics.core.APIMeter;
|
||||
import com.yammer.metrics.core.Clock;
|
||||
import com.yammer.metrics.core.Counter;
|
||||
import com.yammer.metrics.core.Meter;
|
||||
import com.yammer.metrics.core.Metric;
|
||||
import com.yammer.metrics.core.MetricName;
|
||||
import com.yammer.metrics.core.MetricsRegistry;
|
||||
import com.yammer.metrics.core.ThreadPools;
|
||||
import com.yammer.metrics.core.Histogram.SampleType;
|
||||
|
||||
/*
|
||||
* Copyright 2015 Cloudius Systems
|
||||
*
|
||||
* Modified by Cloudius Systems
|
||||
*/
|
||||
|
||||
public class APIMetricsRegistry extends MetricsRegistry {
|
||||
Field fieldMetrics;
|
||||
Field fieldClock;
|
||||
Field fieldThreadPool;
|
||||
|
||||
public APIMetricsRegistry() {
|
||||
try {
|
||||
fieldMetrics = MetricsRegistry.class.getDeclaredField("metrics");
|
||||
fieldMetrics.setAccessible(true);
|
||||
fieldClock = MetricsRegistry.class.getDeclaredField("clock");
|
||||
fieldClock.setAccessible(true);
|
||||
fieldThreadPool = MetricsRegistry.class
|
||||
.getDeclaredField("threadPools");
|
||||
fieldThreadPool.setAccessible(true);
|
||||
} catch (NoSuchFieldException | SecurityException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public ThreadPools getThreadPools() {
|
||||
try {
|
||||
return (ThreadPools) fieldThreadPool.get(this);
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Clock getClock() {
|
||||
try {
|
||||
return (Clock) fieldClock.get(this);
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public ConcurrentMap<MetricName, Metric> getMetrics() {
|
||||
try {
|
||||
return (ConcurrentMap<MetricName, Metric>) fieldMetrics.get(this);
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Counter} and registers it under the given class and
|
||||
* name.
|
||||
*
|
||||
* @param klass
|
||||
* the class which owns the metric
|
||||
* @param name
|
||||
* the name of the metric
|
||||
* @return a new {@link Counter}
|
||||
*/
|
||||
public Counter newCounter(String url, Class<?> klass, String name) {
|
||||
return newCounter(url, klass, name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Counter} and registers it under the given class and
|
||||
* name.
|
||||
*
|
||||
* @param klass
|
||||
* the class which owns the metric
|
||||
* @param name
|
||||
* the name of the metric
|
||||
* @param scope
|
||||
* the scope of the metric
|
||||
* @return a new {@link Counter}
|
||||
*/
|
||||
public Counter newCounter(String url, Class<?> klass, String name,
|
||||
String scope) {
|
||||
return newCounter(url, createName(klass, name, scope));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Counter} and registers it under the given metric
|
||||
* name.
|
||||
*
|
||||
* @param metricName
|
||||
* the name of the metric
|
||||
* @return a new {@link Counter}
|
||||
*/
|
||||
public Counter newCounter(String url, MetricName metricName) {
|
||||
return getOrAdd(metricName, new APICounter(url));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Meter} and registers it under the given class and
|
||||
* name.
|
||||
*
|
||||
* @param klass
|
||||
* the class which owns the metric
|
||||
* @param name
|
||||
* the name of the metric
|
||||
* @param eventType
|
||||
* the plural name of the type of events the meter is measuring
|
||||
* (e.g., {@code "requests"})
|
||||
* @param unit
|
||||
* the rate unit of the new meter
|
||||
* @return a new {@link Meter}
|
||||
*/
|
||||
public APIMeter newMeter(String url, Class<?> klass, String name,
|
||||
String eventType, TimeUnit unit) {
|
||||
return newMeter(url, klass, name, null, eventType, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Meter} and registers it under the given class, name,
|
||||
* and scope.
|
||||
*
|
||||
* @param klass
|
||||
* the class which owns the metric
|
||||
* @param name
|
||||
* the name of the metric
|
||||
* @param scope
|
||||
* the scope of the metric
|
||||
* @param eventType
|
||||
* the plural name of the type of events the meter is measuring
|
||||
* (e.g., {@code "requests"})
|
||||
* @param unit
|
||||
* the rate unit of the new meter
|
||||
* @return a new {@link Meter}
|
||||
*/
|
||||
public APIMeter newMeter(String url, Class<?> klass, String name,
|
||||
String scope, String eventType, TimeUnit unit) {
|
||||
return newMeter(url, createName(klass, name, scope), eventType, unit);
|
||||
}
|
||||
|
||||
private ScheduledExecutorService newMeterTickThreadPool() {
|
||||
return getThreadPools().newScheduledThreadPool(2, "meter-tick");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Meter} and registers it under the given metric name.
|
||||
*
|
||||
* @param metricName
|
||||
* the name of the metric
|
||||
* @param eventType
|
||||
* the plural name of the type of events the meter is measuring
|
||||
* (e.g., {@code "requests"})
|
||||
* @param unit
|
||||
* the rate unit of the new meter
|
||||
* @return a new {@link Meter}
|
||||
*/
|
||||
public APIMeter newMeter(String url, MetricName metricName, String eventType,
|
||||
TimeUnit unit) {
|
||||
final Metric existingMetric = getMetrics().get(metricName);
|
||||
if (existingMetric != null) {
|
||||
return (APIMeter) existingMetric;
|
||||
}
|
||||
return getOrAdd(metricName, new APIMeter(url, newMeterTickThreadPool(),
|
||||
eventType, unit));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link APISettableMeter} and registers it under the given metric name.
|
||||
*
|
||||
* @param metricName
|
||||
* the name of the metric
|
||||
* @param eventType
|
||||
* the plural name of the type of events the meter is measuring
|
||||
* (e.g., {@code "requests"})
|
||||
* @param unit
|
||||
* the rate unit of the new meter
|
||||
* @return a new {@link Meter}
|
||||
*/
|
||||
public Meter newSettableMeter(MetricName metricName, String eventType,
|
||||
TimeUnit unit) {
|
||||
final Metric existingMetric = getMetrics().get(metricName);
|
||||
if (existingMetric != null) {
|
||||
return (Meter) existingMetric;
|
||||
}
|
||||
return getOrAdd(metricName, new APISettableMeter(newMeterTickThreadPool(),
|
||||
eventType, unit, getClock()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Histogram} and registers it under the given class
|
||||
* and name.
|
||||
*
|
||||
* @param klass
|
||||
* the class which owns the metric
|
||||
* @param name
|
||||
* the name of the metric
|
||||
* @param biased
|
||||
* whether or not the histogram should be biased
|
||||
* @return a new {@link Histogram}
|
||||
*/
|
||||
public Histogram newHistogram(String url, Class<?> klass, String name,
|
||||
boolean biased) {
|
||||
return newHistogram(url, klass, name, null, biased);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Histogram} and registers it under the given class,
|
||||
* name, and scope.
|
||||
*
|
||||
* @param klass
|
||||
* the class which owns the metric
|
||||
* @param name
|
||||
* the name of the metric
|
||||
* @param scope
|
||||
* the scope of the metric
|
||||
* @param biased
|
||||
* whether or not the histogram should be biased
|
||||
* @return a new {@link Histogram}
|
||||
*/
|
||||
public Histogram newHistogram(String url, Class<?> klass, String name,
|
||||
String scope, boolean biased) {
|
||||
return newHistogram(url, createName(klass, name, scope), biased);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new non-biased {@link Histogram} and registers it under the
|
||||
* given class and name.
|
||||
*
|
||||
* @param klass
|
||||
* the class which owns the metric
|
||||
* @param name
|
||||
* the name of the metric
|
||||
* @return a new {@link Histogram}
|
||||
*/
|
||||
public Histogram newHistogram(String url, Class<?> klass, String name) {
|
||||
return newHistogram(url, klass, name, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new non-biased {@link Histogram} and registers it under the
|
||||
* given class, name, and scope.
|
||||
*
|
||||
* @param klass
|
||||
* the class which owns the metric
|
||||
* @param name
|
||||
* the name of the metric
|
||||
* @param scope
|
||||
* the scope of the metric
|
||||
* @return a new {@link Histogram}
|
||||
*/
|
||||
public Histogram newHistogram(String url, Class<?> klass, String name,
|
||||
String scope) {
|
||||
return newHistogram(url, klass, name, scope, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Histogram} and registers it under the given metric
|
||||
* name.
|
||||
*
|
||||
* @param metricName
|
||||
* the name of the metric
|
||||
* @param biased
|
||||
* whether or not the histogram should be biased
|
||||
* @return a new {@link Histogram}
|
||||
*/
|
||||
public Histogram newHistogram(String url, MetricName metricName,
|
||||
boolean biased) {
|
||||
return getOrAdd(metricName, new APIHistogram(url,
|
||||
biased ? SampleType.BIASED : SampleType.UNIFORM));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Timer} and registers it under the given class and
|
||||
* name, measuring elapsed time in milliseconds and invocations per second.
|
||||
*
|
||||
* @param klass
|
||||
* the class which owns the metric
|
||||
* @param name
|
||||
* the name of the metric
|
||||
* @return a new {@link Timer}
|
||||
*/
|
||||
public Timer newTimer(String url, Class<?> klass, String name) {
|
||||
return newTimer(url, klass, name, null, TimeUnit.MILLISECONDS,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Timer} and registers it under the given class and
|
||||
* name.
|
||||
*
|
||||
* @param klass
|
||||
* the class which owns the metric
|
||||
* @param name
|
||||
* the name of the metric
|
||||
* @param durationUnit
|
||||
* the duration scale unit of the new timer
|
||||
* @param rateUnit
|
||||
* the rate scale unit of the new timer
|
||||
* @return a new {@link Timer}
|
||||
*/
|
||||
public Timer newTimer(String url, Class<?> klass, String name,
|
||||
TimeUnit durationUnit, TimeUnit rateUnit) {
|
||||
return newTimer(url, klass, name, null, durationUnit, rateUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Timer} and registers it under the given class, name,
|
||||
* and scope, measuring elapsed time in milliseconds and invocations per
|
||||
* second.
|
||||
*
|
||||
* @param klass
|
||||
* the class which owns the metric
|
||||
* @param name
|
||||
* the name of the metric
|
||||
* @param scope
|
||||
* the scope of the metric
|
||||
* @return a new {@link Timer}
|
||||
*/
|
||||
public Timer newTimer(String url, Class<?> klass, String name, String scope) {
|
||||
return newTimer(url, klass, name, scope, TimeUnit.MILLISECONDS,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Timer} and registers it under the given class, name,
|
||||
* and scope.
|
||||
*
|
||||
* @param klass
|
||||
* the class which owns the metric
|
||||
* @param name
|
||||
* the name of the metric
|
||||
* @param scope
|
||||
* the scope of the metric
|
||||
* @param durationUnit
|
||||
* the duration scale unit of the new timer
|
||||
* @param rateUnit
|
||||
* the rate scale unit of the new timer
|
||||
* @return a new {@link Timer}
|
||||
*/
|
||||
public Timer newTimer(String url, Class<?> klass, String name,
|
||||
String scope, TimeUnit durationUnit, TimeUnit rateUnit) {
|
||||
return newTimer(url, createName(klass, name, scope), durationUnit,
|
||||
rateUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Timer} and registers it under the given metric name.
|
||||
*
|
||||
* @param metricName
|
||||
* the name of the metric
|
||||
* @param durationUnit
|
||||
* the duration scale unit of the new timer
|
||||
* @param rateUnit
|
||||
* the rate scale unit of the new timer
|
||||
* @return a new {@link Timer}
|
||||
*/
|
||||
public Timer newTimer(String url, MetricName metricName,
|
||||
TimeUnit durationUnit, TimeUnit rateUnit) {
|
||||
final Metric existingMetric = getMetrics().get(metricName);
|
||||
if (existingMetric != null) {
|
||||
return (Timer) existingMetric;
|
||||
}
|
||||
return getOrAdd(metricName, new APITimer(url, newMeterTickThreadPool(),
|
||||
durationUnit, rateUnit));
|
||||
}
|
||||
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
package com.yammer.metrics.core;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/*
|
||||
* Copyright 2015 ScyllaDB
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* This file is part of Scylla.
|
||||
*
|
||||
* Scylla is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Scylla is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Scylla. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
public class APISettableMeter extends Meter {
|
||||
|
||||
public APISettableMeter(ScheduledExecutorService tickThread,
|
||||
String eventType, TimeUnit rateUnit, Clock clock) {
|
||||
super(tickThread, eventType, rateUnit, clock);
|
||||
}
|
||||
|
||||
// Meter doesn't have a set value method.
|
||||
// to mimic it, we clear the old value and set it to a new one.
|
||||
// This is safe because the only this method would be used
|
||||
// to update the values
|
||||
public long set(long new_value) {
|
||||
long res = super.count();
|
||||
mark(-res);
|
||||
mark(new_value);
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
}
|
||||
}
|
@ -1,134 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Cloudius Systems
|
||||
*
|
||||
*/
|
||||
package com.yammer.metrics.core;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.json.JsonObject;
|
||||
|
||||
import com.scylladb.jmx.api.APIClient;
|
||||
import com.yammer.metrics.core.Histogram.SampleType;
|
||||
import com.yammer.metrics.stats.Snapshot;
|
||||
|
||||
/**
|
||||
* A timer metric which aggregates timing durations and provides duration
|
||||
* statistics, plus throughput statistics via {@link Meter}.
|
||||
*/
|
||||
public class APITimer extends Timer {
|
||||
public final static long CACHE_DURATION = 1000;
|
||||
|
||||
final TimeUnit durationUnit, rateUnit;
|
||||
final APIMeter meter;
|
||||
final APIHistogram histogram;
|
||||
APIClient c = new APIClient();
|
||||
|
||||
private double convertFromNS(double ns) {
|
||||
return ns / TimeUnit.NANOSECONDS.convert(1, durationUnit);
|
||||
}
|
||||
|
||||
String url;
|
||||
|
||||
public APITimer(String url, ScheduledExecutorService tickThread,
|
||||
TimeUnit durationUnit, TimeUnit rateUnit) {
|
||||
super(tickThread, durationUnit, rateUnit);
|
||||
super.stop();
|
||||
this.url = url;
|
||||
this.durationUnit = durationUnit;
|
||||
this.rateUnit = rateUnit;
|
||||
meter = new APIMeter(null, tickThread, "calls", rateUnit);
|
||||
histogram = new APIHistogram(null, SampleType.BIASED);
|
||||
}
|
||||
|
||||
public void fromJson(JsonObject obj) {
|
||||
meter.fromJson(obj.getJsonObject("meter"));
|
||||
histogram.updateValue(APIClient.json2histogram(obj.getJsonObject("hist")));
|
||||
}
|
||||
|
||||
public void update_fields() {
|
||||
if (url != null) {
|
||||
fromJson(c.getJsonObj(url, null, CACHE_DURATION));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public double max() {
|
||||
update_fields();
|
||||
return convertFromNS(histogram.max());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double min() {
|
||||
update_fields();
|
||||
return convertFromNS(histogram.min());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double mean() {
|
||||
update_fields();
|
||||
return convertFromNS(histogram.mean());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double stdDev() {
|
||||
update_fields();
|
||||
return convertFromNS(histogram.stdDev());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double sum() {
|
||||
update_fields();
|
||||
return convertFromNS(histogram.sum());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Snapshot getSnapshot() {
|
||||
update_fields();
|
||||
return histogram.getSnapshot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeUnit rateUnit() {
|
||||
update_fields();
|
||||
return meter.rateUnit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String eventType() {
|
||||
update_fields();
|
||||
return meter.eventType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
update_fields();
|
||||
return meter.count();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double fifteenMinuteRate() {
|
||||
update_fields();
|
||||
return meter.fifteenMinuteRate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double fiveMinuteRate() {
|
||||
update_fields();
|
||||
return meter.fiveMinuteRate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double meanRate() {
|
||||
update_fields();
|
||||
return meter.meanRate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double oneMinuteRate() {
|
||||
update_fields();
|
||||
return meter.oneMinuteRate();
|
||||
}
|
||||
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package com.yammer.metrics.core;
|
||||
|
||||
public class HistogramValues {
|
||||
public long count;
|
||||
public long min;
|
||||
public long max;
|
||||
public long sum;
|
||||
public double variance;
|
||||
public double mean;
|
||||
public long sample[];
|
||||
}
|
Loading…
Reference in New Issue
Block a user