split into api and common packages, update to Java 11, gradle 5.6.2

This commit is contained in:
Jörg Prante 2019-11-07 16:07:00 +01:00
parent 00150abbb3
commit aca0b11a0a
38 changed files with 406 additions and 397 deletions

3
.gitignore vendored
View file

@ -9,5 +9,4 @@
/.classpath /.classpath
/.project /.project
/.gradle /.gradle
/build build
/plugins

View file

@ -1,66 +1,108 @@
plugins { plugins {
id "org.sonarqube" version "2.6.1" id "org.sonarqube" version "2.8"
id "io.codearte.nexus-staging" version "0.11.0" id "io.codearte.nexus-staging" version "0.21.1"
} }
printf "Host: %s\nOS: %s %s %s\nJVM: %s %s %s %s\nGroovy: %s\nGradle: %s\n" + subprojects {
"Build: group: ${project.group} name: ${project.name} version: ${project.version}\n",
InetAddress.getLocalHost(),
System.getProperty("os.name"),
System.getProperty("os.arch"),
System.getProperty("os.version"),
System.getProperty("java.version"),
System.getProperty("java.vm.version"),
System.getProperty("java.vm.vendor"),
System.getProperty("java.vm.name"),
GroovySystem.getVersion(),
gradle.gradleVersion
apply plugin: 'java' apply plugin: 'java'
apply plugin: 'maven' apply plugin: 'maven'
apply plugin: 'signing'
apply from: 'gradle/ext.gradle' dependencies {
testCompile "junit:junit:${project.property('junit.version')}"
testCompile "org.apache.logging.log4j:log4j-core:${project.property('log4j.version')}"
testCompile "org.apache.logging.log4j:log4j-slf4j-impl:${project.property('log4j.version')}"
}
configurations { compileJava {
wagon sourceCompatibility = JavaVersion.VERSION_11
} targetCompatibility = JavaVersion.VERSION_11
}
compileTestJava {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint:all"
}
dependencies { task javadocJar(type: Jar, dependsOn: classes) {
testCompile "junit:junit:4.12"
testCompile "org.apache.logging.log4j:log4j-core:2.10.0"
testCompile "org.apache.logging.log4j:log4j-slf4j-impl:2.10.0"
wagon 'org.apache.maven.wagon:wagon-ssh:3.0.0'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint:all" << "-profile" << "compact3"
}
task javadocJar(type: Jar, dependsOn: classes) {
from javadoc from javadoc
into "build/tmp"
classifier 'javadoc' classifier 'javadoc'
} }
task sourcesJar(type: Jar, dependsOn: classes) { task sourcesJar(type: Jar, dependsOn: classes) {
from sourceSets.main.allSource from sourceSets.main.allSource
into "build/tmp"
classifier 'sources' classifier 'sources'
} }
artifacts { artifacts {
archives javadocJar, sourcesJar archives javadocJar, sourcesJar
} }
if (project.hasProperty('signing.keyId')) { ext {
signing { user = 'jprante'
sign configurations.archives name = 'metrics'
description = 'A stripped-down and modified version of Coda Hale Metrics'
scmUrl = 'https://github.com/' + user + '/' + name
scmConnection = 'scm:git:git://github.com/' + user + '/' + name + '.git'
scmDeveloperConnection = 'scm:git:git://github.com/' + user + '/' + name + '.git'
}
task sonaTypeUpload(type: Upload) {
group = 'publish'
configuration = configurations.archives
uploadDescriptor = true
repositories {
if (project.hasProperty('ossrhUsername')) {
mavenDeployer {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
repository(url: 'https://oss.sonatype.org/service/local/staging/deploy/maven2') {
authentication(userName: ossrhUsername, password: ossrhPassword)
}
snapshotRepository(url: 'https://oss.sonatype.org/content/repositories/snapshots') {
authentication(userName: ossrhUsername, password: ossrhPassword)
}
pom.project {
groupId project.group
artifactId project.name
version project.version
name project.name
description description
packaging 'jar'
inceptionYear '2016'
url scmUrl
organization {
name 'xbib'
url 'http://xbib.org'
}
developers {
developer {
id user
name 'Jörg Prante'
email 'joergprante@gmail.com'
url 'https://github.com/jprante'
}
}
scm {
url scmUrl
connection scmConnection
developerConnection scmDeveloperConnection
}
licenses {
license {
name 'The Apache License, Version 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
}
}
}
}
} }
} }
apply from: 'gradle/publish.gradle' nexusStaging {
packageGroup = "org.xbib"
}

View file

@ -1,6 +1,7 @@
group = org.xbib group = org.xbib
name = metrics name = metrics
version = 1.1.0 version = 2.0.0
# test
log4j.version = 2.12.1
junit.version = 4.12 junit.version = 4.12
wagon.version = 3.0.0

View file

@ -1,8 +0,0 @@
ext {
user = 'jprante'
name = 'metrics'
description = 'A stripped-down and modified version of Coda Hale Metrics'
scmUrl = 'https://github.com/' + user + '/' + name
scmConnection = 'scm:git:git://github.com/' + user + '/' + name + '.git'
scmDeveloperConnection = 'scm:git:git://github.com/' + user + '/' + name + '.git'
}

View file

@ -1,72 +0,0 @@
task xbibUpload(type: Upload) {
group = 'publish'
configuration = configurations.archives
uploadDescriptor = true
repositories {
if (project.hasProperty("xbibUsername")) {
mavenDeployer {
configuration = configurations.wagon
repository(url: project.property('xbibUrl')) {
authentication(userName: xbibUsername, privateKey: xbibPrivateKey)
}
}
}
}
}
task sonaTypeUpload(type: Upload) {
group = 'publish'
configuration = configurations.archives
uploadDescriptor = true
repositories {
if (project.hasProperty('ossrhUsername')) {
mavenDeployer {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
repository(url: 'https://oss.sonatype.org/service/local/staging/deploy/maven2') {
authentication(userName: ossrhUsername, password: ossrhPassword)
}
snapshotRepository(url: 'https://oss.sonatype.org/content/repositories/snapshots') {
authentication(userName: ossrhUsername, password: ossrhPassword)
}
pom.project {
groupId project.group
artifactId project.name
version project.version
name project.name
description description
packaging 'jar'
inceptionYear '2016'
url scmUrl
organization {
name 'xbib'
url 'http://xbib.org'
}
developers {
developer {
id user
name 'Jörg Prante'
email 'joergprante@gmail.com'
url 'https://github.com/jprante'
}
}
scm {
url scmUrl
connection scmConnection
developerConnection scmDeveloperConnection
}
licenses {
license {
name 'The Apache License, Version 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
}
}
}
}
}
nexusStaging {
packageGroup = "org.xbib"
}

View file

@ -1,41 +0,0 @@
tasks.withType(FindBugs) {
ignoreFailures = true
reports {
xml.enabled = true
html.enabled = false
}
}
tasks.withType(Pmd) {
ignoreFailures = true
reports {
xml.enabled = true
html.enabled = true
}
}
tasks.withType(Checkstyle) {
ignoreFailures = true
reports {
xml.enabled = true
html.enabled = true
}
}
jacocoTestReport {
reports {
xml.enabled true
csv.enabled false
xml.destination "${buildDir}/reports/jacoco-xml"
html.destination "${buildDir}/reports/jacoco-html"
}
}
sonarqube {
properties {
property "sonar.projectName", "${project.group} ${project.name}"
property "sonar.sourceEncoding", "UTF-8"
property "sonar.tests", "src/test/java"
property "sonar.scm.provider", "git"
property "sonar.java.coveragePlugin", "jacoco"
property "sonar.junit.reportsPath", "build/test-results/test/"
}
}

Binary file not shown.

View file

@ -1,5 +1,6 @@
#Thu Nov 07 15:59:31 CET 2019
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-rc-1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

22
gradlew vendored
View file

@ -1,5 +1,21 @@
#!/usr/bin/env sh #!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed 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
#
# https://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.
#
############################################################################## ##############################################################################
## ##
## Gradle start up script for UN*X ## Gradle start up script for UN*X
@ -28,7 +44,7 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"` APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS="" DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum" MAX_FD="maximum"
@ -109,8 +125,8 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi fi
# For Cygwin, switch paths to Windows format before running java # For Cygwin or MSYS, switch paths to Windows format before running java
if $cygwin ; then if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"` APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"` JAVACMD=`cygpath --unix "$JAVACMD"`

18
gradlew.bat vendored
View file

@ -1,3 +1,19 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off @if "%DEBUG%" == "" @echo off
@rem ########################################################################## @rem ##########################################################################
@rem @rem
@ -14,7 +30,7 @@ set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS= set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe @rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome if defined JAVA_HOME goto findJavaFromJavaHome

View file

@ -0,0 +1,21 @@
package org.xbib.metrics.api;
/**
* An interface for how time passes.
*/
public interface Clock {
/**
* Returns the current time tick.
*
* @return time tick in nanoseconds
*/
long getTick();
/**
* Returns the current time in milliseconds.
*
* @return time in milliseconds
*/
long getTime();
}

View file

@ -1,4 +1,4 @@
package org.xbib.metrics; package org.xbib.metrics.api;
/** /**
* An interface for metric types which have counts. * An interface for metric types which have counts.

View file

@ -1,4 +1,4 @@
package org.xbib.metrics; package org.xbib.metrics.api;
/** /**
* A gauge metric is an instantaneous reading of a particular value. To instrument a queue's depth, * A gauge metric is an instantaneous reading of a particular value. To instrument a queue's depth,

View file

@ -1,4 +1,6 @@
package org.xbib.metrics; package org.xbib.metrics.api;
import org.xbib.metrics.api.Metric;
/** /**
* An object which maintains mean and exponentially-weighted rate. * An object which maintains mean and exponentially-weighted rate.

View file

@ -1,4 +1,4 @@
package org.xbib.metrics; package org.xbib.metrics.api;
/** /**
* *

View file

@ -1,4 +1,4 @@
package org.xbib.metrics; package org.xbib.metrics.api;
/** /**
* A filter used to determine whether or not a metric should be reported, among other things. * A filter used to determine whether or not a metric should be reported, among other things.

View file

@ -1,4 +1,4 @@
package org.xbib.metrics; package org.xbib.metrics.api;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@ -10,8 +10,11 @@ import java.util.TreeSet;
* A metric name with the ability to include semantic tags. * A metric name with the ability to include semantic tags.
*/ */
public class MetricName implements Comparable<MetricName> { public class MetricName implements Comparable<MetricName> {
public static final String SEPARATOR = "."; public static final String SEPARATOR = ".";
public static final Map<String, String> EMPTY_TAGS = Collections.unmodifiableMap(new HashMap<String, String>()); public static final Map<String, String> EMPTY_TAGS = Collections.unmodifiableMap(new HashMap<String, String>());
public static final MetricName EMPTY = new MetricName(); public static final MetricName EMPTY = new MetricName();
private final String key; private final String key;

View file

@ -1,11 +1,9 @@
package org.xbib.metrics; package org.xbib.metrics.api;
import java.util.Map; import java.util.Map;
/** /**
* A set of named metrics. * A set of named metrics.
*
* @see MetricRegistry#registerAll(MetricSet)
*/ */
@FunctionalInterface @FunctionalInterface
public interface MetricSet extends Metric { public interface MetricSet extends Metric {

View file

@ -1,4 +1,4 @@
package org.xbib.metrics; package org.xbib.metrics.api;
/** /**
* A statistically representative reservoir of a data stream. * A statistically representative reservoir of a data stream.

View file

@ -1,4 +1,4 @@
package org.xbib.metrics; package org.xbib.metrics.api;
/** /**
* An object which samples values. * An object which samples values.

View file

@ -1,4 +1,4 @@
package org.xbib.metrics; package org.xbib.metrics.api;
import java.io.OutputStream; import java.io.OutputStream;

View file

@ -0,0 +1,4 @@
/**
* API interfaces for metrics.
*/
package org.xbib.metrics.api;

View file

@ -0,0 +1,3 @@
dependencies {
compile project(':metrics-api')
}

View file

@ -1,4 +1,7 @@
package org.xbib.metrics; package org.xbib.metrics.common;
import org.xbib.metrics.api.Count;
import org.xbib.metrics.api.Metric;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.HashMap; import java.util.HashMap;
@ -49,7 +52,8 @@ public class CountMetric implements Metric, Count {
checksumIn.put(index + "/" + type, crc32); checksumIn.put(index + "/" + type, crc32);
} }
if (id != null) { if (id != null) {
crc32.update(id.getBytes(StandardCharsets.UTF_8)); byte[] b = id.getBytes(StandardCharsets.UTF_8);
crc32.update(b, 0, b.length);
} }
} }
@ -79,7 +83,8 @@ public class CountMetric implements Metric, Count {
checksumOut.put(index + "/" + type, crc32); checksumOut.put(index + "/" + type, crc32);
} }
if (id != null) { if (id != null) {
crc32.update(id.getBytes(StandardCharsets.UTF_8)); byte[] b = id.getBytes(StandardCharsets.UTF_8);
crc32.update(b, 0, b.length);
} }
} }

View file

@ -1,4 +1,6 @@
package org.xbib.metrics; package org.xbib.metrics.common;
import org.xbib.metrics.api.Clock;
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean; import java.lang.management.ThreadMXBean;

View file

@ -1,4 +1,4 @@
package org.xbib.metrics; package org.xbib.metrics.common;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.LongAdder; import java.util.concurrent.atomic.LongAdder;
@ -11,14 +11,22 @@ import java.util.concurrent.atomic.LongAdder;
* Average</a> * Average</a>
*/ */
public class ExpWeightedMovingAverage { public class ExpWeightedMovingAverage {
private static final double M1_ALPHA = 1 - Math.exp(-5 / 60.0); private static final double M1_ALPHA = 1 - Math.exp(-5 / 60.0);
private static final double M5_ALPHA = 1 - Math.exp(-5 / 60.0 / 5); private static final double M5_ALPHA = 1 - Math.exp(-5 / 60.0 / 5);
private static final double M15_ALPHA = 1 - Math.exp(-5 / 60.0 / 15); private static final double M15_ALPHA = 1 - Math.exp(-5 / 60.0 / 15);
private final LongAdder uncounted = new LongAdder(); private final LongAdder uncounted = new LongAdder();
private final double alpha; private final double alpha;
private final double interval; private final double interval;
private volatile boolean initialized = false; private volatile boolean initialized = false;
private volatile double rate = 0.0;
private double rate = 0.0;
/** /**
* Create a new EWMA with a specific smoothing constant. * Create a new EWMA with a specific smoothing constant.

View file

@ -1,4 +1,8 @@
package org.xbib.metrics; package org.xbib.metrics.common;
import org.xbib.metrics.api.Clock;
import org.xbib.metrics.api.Reservoir;
import org.xbib.metrics.api.Snapshot;
import static java.lang.Math.exp; import static java.lang.Math.exp;
import static java.lang.Math.min; import static java.lang.Math.min;
@ -24,7 +28,7 @@ public class ExponentiallyDecayingReservoir implements Reservoir {
private static final double DEFAULT_ALPHA = 0.015; private static final double DEFAULT_ALPHA = 0.015;
private static final long RESCALE_THRESHOLD = TimeUnit.HOURS.toNanos(1); private static final long RESCALE_THRESHOLD = TimeUnit.HOURS.toNanos(1);
private final ConcurrentSkipListMap<Double, org.xbib.metrics.WeightedSnapshot.WeightedSample> values; private final ConcurrentSkipListMap<Double, WeightedSnapshot.WeightedSample> values;
private final ReentrantReadWriteLock lock; private final ReentrantReadWriteLock lock;
private final double alpha; private final double alpha;
private final int size; private final int size;
@ -50,7 +54,7 @@ public class ExponentiallyDecayingReservoir implements Reservoir {
* will be towards newer values * will be towards newer values
*/ */
public ExponentiallyDecayingReservoir(int size, double alpha) { public ExponentiallyDecayingReservoir(int size, double alpha) {
this(size, alpha, Clock.defaultClock()); this(size, alpha, UserTimeClock.defaultClock());
} }
/** /**

View file

@ -1,4 +1,10 @@
package org.xbib.metrics; package org.xbib.metrics.common;
import org.xbib.metrics.api.Count;
import org.xbib.metrics.api.Metric;
import org.xbib.metrics.api.Reservoir;
import org.xbib.metrics.api.Sampling;
import org.xbib.metrics.api.Snapshot;
import java.util.concurrent.atomic.LongAdder; import java.util.concurrent.atomic.LongAdder;
@ -9,7 +15,9 @@ import java.util.concurrent.atomic.LongAdder;
* variance</a> * variance</a>
*/ */
public class Histogram implements Metric, Sampling, Count { public class Histogram implements Metric, Sampling, Count {
private final Reservoir reservoir; private final Reservoir reservoir;
private final LongAdder count; private final LongAdder count;
/** /**

View file

@ -1,4 +1,7 @@
package org.xbib.metrics; package org.xbib.metrics.common;
import org.xbib.metrics.api.Clock;
import org.xbib.metrics.api.Metered;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
@ -38,7 +41,7 @@ public class Meter implements Metered {
* @param executorService the executor service * @param executorService the executor service
*/ */
public Meter(ScheduledExecutorService executorService) { public Meter(ScheduledExecutorService executorService) {
this(executorService, Clock.defaultClock()); this(executorService, UserTimeClock.defaultClock());
} }
/** /**

View file

@ -1,4 +1,10 @@
package org.xbib.metrics; package org.xbib.metrics.common;
import org.xbib.metrics.api.Gauge;
import org.xbib.metrics.api.Metric;
import org.xbib.metrics.api.MetricFilter;
import org.xbib.metrics.api.MetricName;
import org.xbib.metrics.api.MetricSet;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -20,8 +26,10 @@ import java.util.logging.Logger;
public class MetricRegistry implements MetricSet { public class MetricRegistry implements MetricSet {
private static final Logger logger = Logger.getLogger(MetricRegistry.class.getName()); private static final Logger logger = Logger.getLogger(MetricRegistry.class.getName());
private final ConcurrentMap<MetricName, Metric> metrics; private final ConcurrentMap<MetricName, Metric> metrics;
private final List<MetricRegistryListener> listeners;
private final List<Listener> listeners;
/** /**
* Creates a new {@link MetricRegistry}. * Creates a new {@link MetricRegistry}.
@ -234,13 +242,13 @@ public class MetricRegistry implements MetricSet {
} }
/** /**
* Adds a {@link MetricRegistryListener} to a collection of listeners that will be notified on * Adds a {@link Listener} to a collection of listeners that will be notified on
* metric creation. Listeners will be notified in the order in which they are added. * metric creation. Listeners will be notified in the order in which they are added.
* The listener will be notified of all existing metrics when it first registers. * The listener will be notified of all existing metrics when it first registers.
* *
* @param listener the listener that will be notified * @param listener the listener that will be notified
*/ */
public void addListener(MetricRegistryListener listener) { public void addListener(Listener listener) {
listeners.add(listener); listeners.add(listener);
for (Map.Entry<MetricName, Metric> entry : metrics.entrySet()) { for (Map.Entry<MetricName, Metric> entry : metrics.entrySet()) {
@ -249,11 +257,11 @@ public class MetricRegistry implements MetricSet {
} }
/** /**
* Removes a {@link MetricRegistryListener} from this registry's collection of listeners. * Removes a {@link Listener} from this registry's collection of listeners.
* *
* @param listener the listener that will be removed * @param listener the listener that will be removed
*/ */
public void removeListener(MetricRegistryListener listener) { public void removeListener(Listener listener) {
listeners.remove(listener); listeners.remove(listener);
} }
@ -397,12 +405,12 @@ public class MetricRegistry implements MetricSet {
} }
private void onMetricAdded(MetricName name, Metric metric) { private void onMetricAdded(MetricName name, Metric metric) {
for (MetricRegistryListener listener : listeners) { for (Listener listener : listeners) {
notifyListenerOfAddedMetric(listener, metric, name); notifyListenerOfAddedMetric(listener, metric, name);
} }
} }
private void notifyListenerOfAddedMetric(MetricRegistryListener listener, Metric metric, MetricName name) { private void notifyListenerOfAddedMetric(Listener listener, Metric metric, MetricName name) {
if (metric instanceof Gauge) { if (metric instanceof Gauge) {
listener.onGaugeAdded(name, (Gauge<?>) metric); listener.onGaugeAdded(name, (Gauge<?>) metric);
} else if (metric instanceof CountMetric) { } else if (metric instanceof CountMetric) {
@ -419,12 +427,12 @@ public class MetricRegistry implements MetricSet {
} }
private void onMetricRemoved(MetricName name, Metric metric) { private void onMetricRemoved(MetricName name, Metric metric) {
for (MetricRegistryListener listener : listeners) { for (Listener listener : listeners) {
notifyListenerOfRemovedMetric(name, metric, listener); notifyListenerOfRemovedMetric(name, metric, listener);
} }
} }
private void notifyListenerOfRemovedMetric(MetricName name, Metric metric, MetricRegistryListener listener) { private void notifyListenerOfRemovedMetric(MetricName name, Metric metric, Listener listener) {
if (metric instanceof Gauge) { if (metric instanceof Gauge) {
listener.onGaugeRemoved(name); listener.onGaugeRemoved(name);
} else if (metric instanceof CountMetric) { } else if (metric instanceof CountMetric) {
@ -456,6 +464,132 @@ public class MetricRegistry implements MetricSet {
return Collections.unmodifiableMap(metrics); return Collections.unmodifiableMap(metrics);
} }
/**
* Listeners for events from the registry. Listeners must be thread-safe.
*/
public interface Listener {
/**
* Called when a {@link Gauge} is added to the registry.
*
* @param name the gauge's name
* @param gauge the gauge
*/
void onGaugeAdded(MetricName name, Gauge<?> gauge);
/**
* Called when a {@link Gauge} is removed from the registry.
*
* @param name the gauge's name
*/
void onGaugeRemoved(MetricName name);
/**
* Called when a {@link CountMetric} is added to the registry.
*
* @param name the counter's name
* @param counter the counter
*/
void onCounterAdded(MetricName name, CountMetric counter);
/**
* Called when a {@link CountMetric} is removed from the registry.
*
* @param name the counter's name
*/
void onCounterRemoved(MetricName name);
/**
* Called when a {@link Histogram} is added to the registry.
*
* @param name the histogram's name
* @param histogram the histogram
*/
void onHistogramAdded(MetricName name, Histogram histogram);
/**
* Called when a {@link Histogram} is removed from the registry.
*
* @param name the histogram's name
*/
void onHistogramRemoved(MetricName name);
/**
* Called when a {@link Meter} is added to the registry.
*
* @param name the meter's name
* @param meter the meter
*/
void onMeterAdded(MetricName name, Meter meter);
/**
* Called when a {@link Meter} is removed from the registry.
*
* @param name the meter's name
*/
void onMeterRemoved(MetricName name);
/**
* Called when a {@link Sampler} is added to the registry.
*
* @param name the sampler's name
* @param sampler the sampler
*/
void onTimerAdded(MetricName name, Sampler sampler);
/**
* Called when a {@link Sampler} is removed from the registry.
*
* @param name the timer's name
*/
void onTimerRemoved(MetricName name);
}
/**
* A no-op implementation of {@link Listener}.
*/
abstract class Base implements Listener {
@Override
public void onGaugeAdded(MetricName name, Gauge<?> gauge) {
}
@Override
public void onGaugeRemoved(MetricName name) {
}
@Override
public void onCounterAdded(MetricName name, CountMetric counter) {
}
@Override
public void onCounterRemoved(MetricName name) {
}
@Override
public void onHistogramAdded(MetricName name, Histogram histogram) {
}
@Override
public void onHistogramRemoved(MetricName name) {
}
@Override
public void onMeterAdded(MetricName name, Meter meter) {
}
@Override
public void onMeterRemoved(MetricName name) {
}
@Override
public void onTimerAdded(MetricName name, Sampler sampler) {
}
@Override
public void onTimerRemoved(MetricName name) {
}
}
/** /**
* A quick and easy way of capturing the notion of default metrics. * A quick and easy way of capturing the notion of default metrics.
*/ */

View file

@ -1,4 +1,10 @@
package org.xbib.metrics; package org.xbib.metrics.common;
import org.xbib.metrics.api.Clock;
import org.xbib.metrics.api.Metered;
import org.xbib.metrics.api.Reservoir;
import org.xbib.metrics.api.Sampling;
import org.xbib.metrics.api.Snapshot;
import java.io.Closeable; import java.io.Closeable;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
@ -12,7 +18,9 @@ import java.util.concurrent.TimeUnit;
public class Sampler implements Metered, Sampling { public class Sampler implements Metered, Sampling {
private final Meter meter; private final Meter meter;
private final Histogram histogram; private final Histogram histogram;
private final Clock clock; private final Clock clock;
/** /**
@ -31,7 +39,7 @@ public class Sampler implements Metered, Sampling {
* @param executorService the executor service * @param executorService the executor service
*/ */
public Sampler(Reservoir reservoir, ScheduledExecutorService executorService) { public Sampler(Reservoir reservoir, ScheduledExecutorService executorService) {
this(reservoir, Clock.defaultClock(), executorService); this(reservoir, UserTimeClock.defaultClock(), executorService);
} }
/** /**

View file

@ -1,10 +1,23 @@
package org.xbib.metrics; package org.xbib.metrics.common;
import org.xbib.metrics.api.Clock;
/** /**
* A clock implementation which returns the current time in epoch nanoseconds. * A clock implementation which returns the current time in epoch nanoseconds.
*/ */
class UserTimeClock implements Clock { class UserTimeClock implements Clock {
/**
* The default clock to use.
*
* @return the default {@link Clock} instance
* @see UserTimeClock
*/
static Clock defaultClock() {
return UserTimeClock.DEFAULT;
}
static final Clock DEFAULT = new UserTimeClock(); static final Clock DEFAULT = new UserTimeClock();
@Override @Override

View file

@ -1,4 +1,6 @@
package org.xbib.metrics; package org.xbib.metrics.common;
import org.xbib.metrics.api.Snapshot;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
@ -6,6 +8,7 @@ import java.io.PrintWriter;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator;
/** /**
* A statistical snapshot of a {@link WeightedSnapshot}. * A statistical snapshot of a {@link WeightedSnapshot}.
@ -13,7 +16,9 @@ import java.util.Collection;
public class WeightedSnapshot implements Snapshot { public class WeightedSnapshot implements Snapshot {
private final long[] values; private final long[] values;
private final double[] normWeights; private final double[] normWeights;
private final double[] quantiles; private final double[] quantiles;
/** /**
@ -24,15 +29,7 @@ public class WeightedSnapshot implements Snapshot {
public WeightedSnapshot(Collection<WeightedSample> values) { public WeightedSnapshot(Collection<WeightedSample> values) {
final WeightedSample[] copy = values.toArray(new WeightedSample[]{}); final WeightedSample[] copy = values.toArray(new WeightedSample[]{});
Arrays.sort(copy, (o1, o2) -> { Arrays.sort(copy, Comparator.comparingLong(o -> o.value));
if (o1.value > o2.value) {
return 1;
}
if (o1.value < o2.value) {
return -1;
}
return 0;
});
this.values = new long[copy.length]; this.values = new long[copy.length];
this.normWeights = new double[copy.length]; this.normWeights = new double[copy.length];

View file

@ -0,0 +1,4 @@
/**
* Implementation classes for metrics.
*/
package org.xbib.metrics.common;

2
settings.gradle Normal file
View file

@ -0,0 +1,2 @@
include 'metrics-api'
include 'metrics-common'

View file

@ -1,32 +0,0 @@
package org.xbib.metrics;
/**
* An interface for how time passes. It is passed to {@link Sampler} to track timing.
*/
public interface Clock {
/**
* The default clock to use.
*
* @return the default {@link Clock} instance
* @see UserTimeClock
*/
static Clock defaultClock() {
return UserTimeClock.DEFAULT;
}
/**
* Returns the current time tick.
*
* @return time tick in nanoseconds
*/
long getTick();
/**
* Returns the current time in milliseconds.
*
* @return time in milliseconds
*/
long getTime();
}

View file

@ -1,128 +0,0 @@
package org.xbib.metrics;
import java.util.EventListener;
/**
* Listeners for events from the registry. Listeners must be thread-safe.
*/
public interface MetricRegistryListener extends EventListener {
/**
* Called when a {@link Gauge} is added to the registry.
*
* @param name the gauge's name
* @param gauge the gauge
*/
void onGaugeAdded(MetricName name, Gauge<?> gauge);
/**
* Called when a {@link Gauge} is removed from the registry.
*
* @param name the gauge's name
*/
void onGaugeRemoved(MetricName name);
/**
* Called when a {@link CountMetric} is added to the registry.
*
* @param name the counter's name
* @param counter the counter
*/
void onCounterAdded(MetricName name, CountMetric counter);
/**
* Called when a {@link CountMetric} is removed from the registry.
*
* @param name the counter's name
*/
void onCounterRemoved(MetricName name);
/**
* Called when a {@link Histogram} is added to the registry.
*
* @param name the histogram's name
* @param histogram the histogram
*/
void onHistogramAdded(MetricName name, Histogram histogram);
/**
* Called when a {@link Histogram} is removed from the registry.
*
* @param name the histogram's name
*/
void onHistogramRemoved(MetricName name);
/**
* Called when a {@link Meter} is added to the registry.
*
* @param name the meter's name
* @param meter the meter
*/
void onMeterAdded(MetricName name, Meter meter);
/**
* Called when a {@link Meter} is removed from the registry.
*
* @param name the meter's name
*/
void onMeterRemoved(MetricName name);
/**
* Called when a {@link Sampler} is added to the registry.
*
* @param name the sampler's name
* @param sampler the sampler
*/
void onTimerAdded(MetricName name, Sampler sampler);
/**
* Called when a {@link Sampler} is removed from the registry.
*
* @param name the timer's name
*/
void onTimerRemoved(MetricName name);
/**
* A no-op implementation of {@link MetricRegistryListener}.
*/
abstract class Base implements MetricRegistryListener {
@Override
public void onGaugeAdded(MetricName name, Gauge<?> gauge) {
}
@Override
public void onGaugeRemoved(MetricName name) {
}
@Override
public void onCounterAdded(MetricName name, CountMetric counter) {
}
@Override
public void onCounterRemoved(MetricName name) {
}
@Override
public void onHistogramAdded(MetricName name, Histogram histogram) {
}
@Override
public void onHistogramRemoved(MetricName name) {
}
@Override
public void onMeterAdded(MetricName name, Meter meter) {
}
@Override
public void onMeterRemoved(MetricName name) {
}
@Override
public void onTimerAdded(MetricName name, Sampler sampler) {
}
@Override
public void onTimerRemoved(MetricName name) {
}
}
}

View file

@ -1,4 +0,0 @@
/**
* Classes for metrics.
*/
package org.xbib.metrics;