Skip to content

Commit

Permalink
ISPN-15029 Create metrics for latency between nodes
Browse files Browse the repository at this point in the history
Other side changes included in this PR are
* Publish percentiles for histograms
* Added remaining Micrometer meters (Counter, FunctionTimer,
  DistributionSummary)
* Extract logic from MetricsCollector to a new class MetricsRegistry
  • Loading branch information
pruivo committed Oct 11, 2023
1 parent 8f53ccd commit 1a22bc7
Show file tree
Hide file tree
Showing 48 changed files with 2,007 additions and 598 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,16 @@ public void generate(PrintWriter w, String packageName, String className) throws
w.println("import java.util.Map;");
w.println("import java.util.function.Function;");
w.println("import javax.annotation.processing.Generated;");
w.println("import static org.infinispan.factories.impl.MBeanMetadata.AttributeMetadata;");
w.println("import org.infinispan.commons.stat.GaugeMetricInfo;");
w.println("import org.infinispan.commons.stat.MetricInfo;");
w.println("import org.jgroups.stack.Protocol;");
w.println();
w.printf("@Generated(value = \"%s\", date = \"%s\")%n", getClass().getName(), Instant.now().toString());
w.printf("public class %s {%n", className);
w.println(" public static final Map<Class<? extends Protocol>, Collection<AttributeMetadata>> PROTOCOL_METADATA = new HashMap<>();");
w.println(" public static final Map<Class<? extends Protocol>, Collection<MetricInfo>> PROTOCOL_METADATA = new HashMap<>();");
w.printf(" private %s() {}%n", className);
w.println(" static {");
w.println(" List<AttributeMetadata> attributes;");
w.println(" List<MetricInfo> attributes;");
for (short id = 0; id < 256; id++) {
Class<?> protocol = ClassConfigurator.getProtocol(id);
addProtocol(protocol, w);
Expand Down Expand Up @@ -105,9 +106,8 @@ private static void addProtocol(Class<?> protocol, PrintWriter w) {
if (hasAttributes.compareAndSet(false, true)) {
w.println(" attributes = new ArrayList<>();");
}
w.printf(" attributes.add(new AttributeMetadata(\"%s\", \"%s\", false, false, \"%s\",\n" +
" false, (Function<%s, ?>) %s::%s, null));%n",
method.getName(), annotation.description().replace('"', '\''), method.getReturnType().getName(), protocol.getName(), protocol.getName(), method.getName());
w.printf(" attributes.add(new GaugeMetricInfo<>(\"%s\", \"%s\", null, %s::%s));%n",
method.getName(), annotation.description().replace('"', '\''), protocol.getName(), method.getName());
}
}

Expand All @@ -133,9 +133,8 @@ private static void addTPComponent(String getterMethodName, Class<?> protocol, C
if (hasAttributes.compareAndSet(false, true)) {
w.println(" attributes = new ArrayList<>();");
}
w.printf(" attributes.add(new AttributeMetadata(\"%s\", \"%s\", false, false, \"%s\",\n" +
" false, (Function<%s, ?>) p -> p.%s().%s(), null));%n",
method.getName(), annotation.description().replace('"', '\''), method.getReturnType().getName(), protocol.getName(), getterMethodName, method.getName());
w.printf(" attributes.add(new GaugeMetricInfo<>(\"%s\", \"%s\", null, ((Function<%s, Number>) p -> p.%s().%s())));%n",
method.getName(), annotation.description().replace('"', '\''), protocol.getName(), getterMethodName, method.getName());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package org.infinispan.commons.stat;

import java.util.Collections;
import java.util.Map;
import java.util.Objects;

/**
* Base implementation of {@link MetricInfo} with all the required information.
*
* @since 15.0
*/
abstract class BaseMetricInfo implements MetricInfo {

private final String name;
private final String description;
private final Map<String, String> map;

BaseMetricInfo(String name, String description, Map<String, String> map) {
this.name = Objects.requireNonNull(name);
this.description = Objects.requireNonNull(description);
this.map = map == null || map.isEmpty() ? Collections.emptyMap() : Map.copyOf(map);
}

@Override
public final String getName() {
return name;
}

@Override
public final String getDescription() {
return description;
}

@Override
public final Map<String, String> getTags() {
return map;
}

@Override
public String toString() {
return getClass().getSimpleName() + "{" +
"name='" + getName() + '\'' +
", description='" + getDescription() + '\'' +
", tags=" + getTags() +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.infinispan.commons.stat;

import java.util.Map;
import java.util.Objects;
import java.util.function.BiConsumer;

/**
* Extends {@link BaseMetricInfo} with a consumer, usually a target instance and the tracker to set.
*
* @since 15.0
*/
abstract class BaseSetterMetricInfo<O, M> extends BaseMetricInfo {

private final BiConsumer<O, M> setter;

BaseSetterMetricInfo(String name, String description, Map<String, String> map, BiConsumer<O, M> setter) {
super(name, description, map);
this.setter = Objects.requireNonNull(setter);
}

public final void accept(O targetInstance, M metricTracker) {
setter.accept(targetInstance, metricTracker);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.infinispan.commons.stat;

import java.util.Map;
import java.util.function.BiConsumer;

/**
* Represents a counter. It sets {@link CounterTracker} into the target instance.
* <p>
* A counter tracks a monotonically increasing values and never resets to a lesser value.
*
* @since 15.0
*/
public final class CounterMetricInfo<T> extends BaseSetterMetricInfo<T, CounterTracker> {

public CounterMetricInfo(String name, String description, Map<String, String> map, BiConsumer<T, CounterTracker> setter) {
super(name, description, map, setter);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.infinispan.commons.stat;

/**
* Tracks a monotonically increasing values.
* <p>
* The counters may never be reset to a lesser value.
*/
public interface CounterTracker {

/**
* Update the counter by one.
*/
void increment();

/**
* Update the counter by {@code amount}.
*
* @param amount The amount to add to the counter.
*/
void increment(double amount);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.infinispan.commons.stat;

import java.util.Map;
import java.util.function.BiConsumer;

/**
* Represents a distribution summary (histogram). It sets {@link DistributionSummaryTracker} into the target instance.
* <p>
* A distribution summary tracks the sample distribution of events.
*
* @since 15.0
*/
public final class DistributionSummaryMetricInfo<T> extends BaseSetterMetricInfo<T, DistributionSummaryTracker> {

public DistributionSummaryMetricInfo(String name, String description, Map<String, String> map, BiConsumer<T, DistributionSummaryTracker> setter) {
super(name, description, map, setter);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.infinispan.commons.stat;

/**
* Track the sample distribution of events.
*/
public interface DistributionSummaryTracker {

/**
* Updates the statistics kept by the summary with the specified amount.
*
* @param amount Amount for an event being tracked.
*/
void record(double amount);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.infinispan.commons.stat;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;

/**
* Represents a duration metric. It sets {@link TimerTracker} into the target instance.
* <p>
* A distribution summary tracks a duration.
*
* @since 15.0
*/
public final class FunctionTimerMetricInfo<T> extends BaseSetterMetricInfo<T, TimerTracker> {

private final TimeUnit timeUnit;

public FunctionTimerMetricInfo(String name, String description, Map<String, String> map, BiConsumer<T, TimerTracker> setter, TimeUnit timeUnit) {
super(name, description, map, setter);
this.timeUnit = Objects.requireNonNull(timeUnit);
}

/**
* @return The {@link TimeUnit} of the time tracked by the event.
*/
public TimeUnit getTimeUnit() {
return timeUnit;
}

@Override
public String toString() {
return "FunctionTimerMetricInfo{" +
"name='" + getName() + '\'' +
", timeUnit=" + timeUnit +
", description='" + getDescription() + '\'' +
", tags=" + getTags() +
'}';
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.infinispan.commons.stat;

import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.Supplier;

/**
* Represents a gauge metric.
* <p>
* A gauge tracks a specific value, like a queue size.
*
* @since 15.0
*/
public final class GaugeMetricInfo<T> extends BaseMetricInfo {

private final Function<T, Number> function;

public GaugeMetricInfo(String name, String description, Map<String, String> map, Function<T, Number> function) {
super(name, description, map);
this.function = Objects.requireNonNull(function);
}

/**
* @return The {@link Supplier} to be invoked to fetch the value from {@code instance}.
*/
public Supplier<Number> getGauge(T instance) {
return () -> function.apply(instance);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.infinispan.commons.stat;

import java.util.Collections;
import java.util.Map;

/**
* Class that represent the information about a metrics.
* <p>
* Includes the metrics's name, description and tags. Subclasses can add more information about it.
*
* @since 15.0
*/
public interface MetricInfo {

/**
* @return The metrics name.
*/
String getName();

/**
* @return The metrics description/help message.
*/
String getDescription();

/**
* @return The tags to be used. Must be non-null.
*/
default Map<String, String> getTags() {
return Collections.emptyMap();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.infinispan.commons.stat;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Supplier;

/**
* Same as {@link GaugeMetricInfo} but the tracked value is a time or duration.
*
* @since 15.0
*/
public final class TimeGaugeMetricInfo<T> extends BaseMetricInfo {

private final Function<T, Number> function;
private final TimeUnit timeUnit;

public TimeGaugeMetricInfo(String name, String description, Map<String, String> map, Function<T, Number> function, TimeUnit timeUnit) {
super(name, description, map);
this.function = Objects.requireNonNull(function);
this.timeUnit = Objects.requireNonNull(timeUnit);
}

/**
* @return The {@link Supplier} to invoke to return the current value of the metric.
*/
public Supplier<Number> getGauge(T instance) {
return () -> function.apply(instance);
}

/**
* @return The {@link TimeUnit} of the tracked value.
*/
public TimeUnit getTimeUnit() {
return timeUnit;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.infinispan.commons.stat;

import java.util.Map;
import java.util.function.BiConsumer;

/**
* Represents a duration event (histogram). It sets {@link TimerTracker} into the target instance.
*
* @since 15.0
*/
public final class TimerMetricInfo<T> extends BaseSetterMetricInfo<T, TimerTracker> {

public TimerMetricInfo(String name, String description, Map<String, String> map, BiConsumer<T, TimerTracker> setter) {
super(name, description, map, setter);
}
}

0 comments on commit 1a22bc7

Please sign in to comment.