Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions ebean-api/src/main/java/io/ebean/meta/AbstractMetricVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,31 @@
*/
public abstract class AbstractMetricVisitor implements MetricVisitor {

private final boolean reset;
private final Mode mode;
private final boolean collectTransactionMetrics;
private final boolean collectQueryMetrics;
private final boolean collectL2Metrics;

public AbstractMetricVisitor(boolean reset, boolean collectTransactionMetrics, boolean collectQueryMetrics, boolean collectL2Metrics) {
this.reset = reset;
this(reset ? Mode.RESET : Mode.CUMULATIVE,
collectTransactionMetrics, collectQueryMetrics, collectL2Metrics);
}

public AbstractMetricVisitor(Mode mode, boolean collectTransactionMetrics, boolean collectQueryMetrics, boolean collectL2Metrics) {
this.mode = mode;
this.collectTransactionMetrics = collectTransactionMetrics;
this.collectQueryMetrics = collectQueryMetrics;
this.collectL2Metrics = collectL2Metrics;
}

@Override
public boolean reset() {
return reset;
return mode == Mode.RESET;
}

@Override
public Mode mode() {
return mode;
}

@Override
Expand Down Expand Up @@ -47,4 +57,3 @@ public void visitEnd() {
// do nothing by default
}
}

11 changes: 10 additions & 1 deletion ebean-api/src/main/java/io/ebean/meta/BasicMetricVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,16 @@ public BasicMetricVisitor(String name, Function<String,String> naming) {
* Construct specifying reset and what to collect.
*/
public BasicMetricVisitor(String name, Function<String,String> naming, boolean reset, boolean collectTransactionMetrics, boolean collectQueryMetrics, boolean collectL2Metrics) {
super(reset, collectTransactionMetrics, collectQueryMetrics, collectL2Metrics);
this(name, naming, reset ? Mode.RESET : Mode.CUMULATIVE,
collectTransactionMetrics, collectQueryMetrics, collectL2Metrics);
}

/**
* Construct specifying the collection mode and what to collect.
*/
public BasicMetricVisitor(String name, Function<String,String> naming, Mode mode,
boolean collectTransactionMetrics, boolean collectQueryMetrics, boolean collectL2Metrics) {
super(mode, collectTransactionMetrics, collectQueryMetrics, collectL2Metrics);
this.name = name;
this.naming = naming;
}
Expand Down
13 changes: 13 additions & 0 deletions ebean-api/src/main/java/io/ebean/meta/MetricVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
*/
public interface MetricVisitor {

enum Mode {
RESET,
CUMULATIVE,
DELTA
}

/**
* Return the naming convention that should be applied to the reported metric names.
*/
Expand All @@ -17,6 +23,13 @@ public interface MetricVisitor {
*/
boolean reset();

/**
* Return the metric collection mode.
*/
default Mode mode() {
return reset() ? Mode.RESET : Mode.CUMULATIVE;
}

/**
* Return true if we should visit the transaction metrics.
*/
Expand Down
10 changes: 10 additions & 0 deletions ebean-api/src/main/java/io/ebean/metric/TimedMetric.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ public interface TimedMetric {
*/
TimedMetricStats collect(boolean reset);

/**
* Collect a snapshot using the given collection mode.
*
* <p>Implementations that do not support delta collection use cumulative
* collection for {@link MetricVisitor.Mode#DELTA}.</p>
*/
default TimedMetricStats collect(MetricVisitor.Mode mode) {
return collect(mode == MetricVisitor.Mode.RESET);
}

/**
* Visit non empty metrics.
*/
Expand Down
14 changes: 14 additions & 0 deletions ebean-api/src/test/java/io/ebean/meta/MetaInfoManagerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,18 @@ public List<MetaQueryPlan> queryPlanCollectNow(QueryPlanRequest request) {

assertThat(manager.collectMetrics(false)).isSameAs(metrics);
}

@Test
void basicMetricVisitorSupportsExplicitCollectionModes() {
var reset = new BasicMetricVisitor("db", MetricNamingMatch.INSTANCE, MetricVisitor.Mode.RESET, true, true, true);
var cumulative = new BasicMetricVisitor("db", MetricNamingMatch.INSTANCE, MetricVisitor.Mode.CUMULATIVE, true, true, true);
var delta = new BasicMetricVisitor("db", MetricNamingMatch.INSTANCE, MetricVisitor.Mode.DELTA, true, true, true);

assertThat(reset.reset()).isTrue();
assertThat(reset.mode()).isEqualTo(MetricVisitor.Mode.RESET);
assertThat(cumulative.reset()).isFalse();
assertThat(cumulative.mode()).isEqualTo(MetricVisitor.Mode.CUMULATIVE);
assertThat(delta.reset()).isFalse();
assertThat(delta.mode()).isEqualTo(MetricVisitor.Mode.DELTA);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,32 @@
import io.ebean.metric.CountMetric;
import io.ebean.metric.CountMetricStats;

import java.util.concurrent.atomic.LongAdder;

/**
* Used to collect counter metrics.
*/
final class DCountMetric implements CountMetric {

private final String name;
private final LongAdder count = new LongAdder();
private final ValueAdder count = new ValueAdder();
private String reportName;

DCountMetric(String name) {
this.name = name;
}

/**
* Add a value. Usually the value is Time or Bytes etc.
*/
@Override
public void add(long value) {
count.add(value);
}

@Override
public void increment() {
count.increment();
count.add(1);
}

@Override
public boolean isEmpty() {
return count.sum() == 0;
return count.currentValue() == 0;
}

@Override
Expand All @@ -44,12 +39,25 @@ public void reset() {

@Override
public long get(boolean reset) {
return reset ? count.sumThenReset() : count.sum();
return reset ? count.getAndReset() : count.cumulative();
}

@Override
public void visit(MetricVisitor visitor) {
long val = visitor.reset() ? count.sumThenReset() : count.sum();
long val;
switch (visitor.mode()) {
case RESET:
val = count.getAndReset();
break;
case CUMULATIVE:
val = count.cumulative();
break;
case DELTA:
val = count.delta();
break;
default:
throw new IllegalStateException("Unknown metric collection mode");
}
if (val > 0) {
final String name = reportName != null ? reportName : reportName(visitor);
visitor.visitCount(new DCountMetricStats(name, val));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ final class DQueryPlanMetric implements QueryPlanMetric {

@Override
public void visit(MetricVisitor visitor) {
TimedMetricStats stats = metric.collect(visitor.reset());
TimedMetricStats stats = metric.collect(visitor.mode());
if (stats != null) {
String name = reportName != null ? reportName : reportName(visitor);
visitor.visitQuery(new Stats(name, meta, stats, collected));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import io.ebean.metric.TimedMetric;

import java.util.concurrent.atomic.LongAccumulator;
import java.util.concurrent.atomic.LongAdder;

/**
* Used to collect timed execution statistics.
Expand All @@ -15,8 +14,8 @@
final class DTimedMetric implements TimedMetric {

private final String name;
private final LongAdder count = new LongAdder();
private final LongAdder total = new LongAdder();
private final ValueAdder count = new ValueAdder();
private final ValueAdder total = new ValueAdder();
private final LongAccumulator max = new LongAccumulator(Math::max, 0);
private boolean collected;
private String reportName;
Expand All @@ -43,14 +42,14 @@ public void addSinceNanos(long startNanos) {

@Override
public void add(long value) {
count.increment();
count.add(1);
total.add(value);
max.accumulate(value);
}

@Override
public boolean isEmpty() {
return count.sum() == 0;
return count.currentValue() == 0;
}

@Override
Expand All @@ -62,29 +61,61 @@ public void reset() {

@Override
public void visit(MetricVisitor visitor) {
final long countSum = visitor.reset() ? count.sumThenReset() : count.sum();
if (countSum > 0) {
final DTimeMetricStats stats = collect(visitor.mode());
if (stats != null) {
final String name = reportName != null ? reportName : reportName(visitor);
visitor.visitTimed(stats(visitor.reset(), name, countSum));
stats.setName(name);
visitor.visitTimed(stats);
}
}

@Override
public DTimeMetricStats collect(boolean reset) {
final long countSum = reset ? count.sumThenReset() : count.sum();
return collect(reset ? MetricVisitor.Mode.RESET : MetricVisitor.Mode.CUMULATIVE);
}

@Override
public DTimeMetricStats collect(MetricVisitor.Mode mode) {
final long countSum;
switch (mode) {
case RESET:
countSum = count.getAndReset();
break;
case CUMULATIVE:
countSum = count.cumulative();
break;
case DELTA:
countSum = count.delta();
break;
default:
throw new IllegalStateException("Unknown metric collection mode");
}
if (countSum == 0) {
return null;
} else {
return stats(reset, name, countSum);
return stats(mode, name, countSum);
}
}

/**
* Return the current statistics resetting the internal values if reset is true.
*/
private DTimeMetricStats stats(boolean reset, String name, long countSum) {
private DTimeMetricStats stats(MetricVisitor.Mode mode, String name, long countSum) {
try {
final long totalSum = reset ? total.sumThenReset() : total.sum();
final long totalSum;
switch (mode) {
case RESET:
totalSum = total.getAndReset();
break;
case CUMULATIVE:
totalSum = total.cumulative();
break;
case DELTA:
totalSum = total.delta();
break;
default:
throw new IllegalStateException("Unknown metric collection mode");
}
return new DTimeMetricStats(name, collected, countSum, totalSum, max.getThenReset());
} finally {
collected = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public void add(long executionTime) {

@Override
public void visit(MetricVisitor visitor) {
TimedMetricStats collect = timedMetric.collect(visitor.reset());
TimedMetricStats collect = timedMetric.collect(visitor.mode());
if (collect != null) {
final String name = reportName != null ? reportName : reportName(visitor, collect.name());
collect.setName(name);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package io.ebeaninternal.server.profile;

import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;

/**
* Accumulates a value while supporting cumulative and reset-based delta reads.
*/
final class ValueAdder {

private final LongAdder value = new LongAdder();
private final AtomicLong previousValue = new AtomicLong();

void add(long amount) {
value.add(amount);
}

long cumulative() {
return value.sum();
}

long delta() {
long currentValue = value.sum();
long previous = previousValue.getAndSet(currentValue);
return currentValue >= previous ? currentValue - previous : currentValue;
}

long getAndReset() {
long currentValue = value.sumThenReset();
previousValue.set(0);
return currentValue;
}

void reset() {
value.reset();
previousValue.set(0);
}

long currentValue() {
return value.sum();
}
}
Loading
Loading