package io.ebeaninternal.server.query;
import io.ebean.ProfileLocation;
import io.ebean.bean.ObjectGraphNode;
import io.ebean.meta.MetaOrmQueryMetric;
import io.ebean.meta.MetaOrmQueryOrigin;
import io.ebean.meta.MetricType;
import io.ebean.metric.TimedMetric;
import io.ebean.metric.TimedMetricStats;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.LongAdder;
public final class CQueryPlanStats {
private final CQueryPlan queryPlan;
private final TimedMetric timedMetric;
private long lastQueryTime;
private final ConcurrentHashMap<ObjectGraphNode, LongAdder> origins;
CQueryPlanStats(CQueryPlan queryPlan, boolean collectQueryOrigins) {
this.queryPlan = queryPlan;
this.origins = !collectQueryOrigins ? null : new ConcurrentHashMap<>();
this.timedMetric = queryPlan.createTimedMetric();
}
public boolean isEmpty() {
return timedMetric.isEmpty();
}
public void add(long loadedBeanCount, long timeMicros, ObjectGraphNode objectGraphNode) {
timedMetric.add(timeMicros, loadedBeanCount);
lastQueryTime = System.currentTimeMillis();
if (origins != null && objectGraphNode != null) {
LongAdder counter = origins.get(objectGraphNode);
if (counter == null) {
counter = new LongAdder();
origins.put(objectGraphNode, counter);
}
counter.increment();
}
}
public void reset() {
timedMetric.reset();
if (origins != null) {
for (LongAdder counter : origins.values()) {
counter.reset();
}
}
}
long getLastQueryTime() {
return lastQueryTime;
}
Snapshot getSnapshot(boolean reset) {
TimedMetricStats collect = timedMetric.collect(reset);
List<MetaOrmQueryOrigin> origins = getOrigins(reset);
return new Snapshot(queryPlan, collect, lastQueryTime, origins);
}
private List<MetaOrmQueryOrigin> getOrigins(boolean reset) {
if (origins == null) {
return Collections.emptyList();
}
List<MetaOrmQueryOrigin> list = new ArrayList<>(origins.size());
for (Entry<ObjectGraphNode, LongAdder> entry : origins.entrySet()) {
if (reset) {
list.add(new OriginSnapshot(entry.getKey(), entry.getValue().sumThenReset()));
} else {
list.add(new OriginSnapshot(entry.getKey(), entry.getValue().sum()));
}
}
return list;
}
private static class OriginSnapshot implements MetaOrmQueryOrigin {
private final ObjectGraphNode objectGraphNode;
private final long count;
OriginSnapshot(ObjectGraphNode objectGraphNode, long count) {
this.objectGraphNode = objectGraphNode;
this.count = count;
}
@Override
public String toString() {
return "node[" + objectGraphNode + "] count[" + count + "]";
}
@Override
public ObjectGraphNode getObjectGraphNode() {
return objectGraphNode;
}
@Override
public long getCount() {
return count;
}
}
static class Snapshot implements MetaOrmQueryMetric {
private final CQueryPlan queryPlan;
private final TimedMetricStats metrics;
private final long lastQueryTime;
private final List<MetaOrmQueryOrigin> origins;
Snapshot(CQueryPlan queryPlan, TimedMetricStats metrics, long lastQueryTime, List<MetaOrmQueryOrigin> origins) {
this.queryPlan = queryPlan;
this.metrics = metrics;
this.lastQueryTime = lastQueryTime;
this.origins = origins;
}
@Override
public String toString() {
return "label:" + getLabel() + " location:" + getLocation() + " metrics:" + metrics + " sql:" + getSql();
}
@Override
public MetricType getMetricType() {
return MetricType.ORM;
}
@Override
public Class<?> getType() {
return queryPlan.getBeanType();
}
@Override
public String getLabel() {
return queryPlan.getLabel();
}
@Override
public String getName() {
return queryPlan.getLabel();
}
@Override
public String getLocation() {
return queryPlan.getLocation();
}
@Override
public ProfileLocation getProfileLocation() {
return queryPlan.getProfileLocation();
}
@Override
public long getBeanCount() {
return metrics.getBeanCount();
}
@Override
public long getCount() {
return metrics.getCount();
}
@Override
public long getTotal() {
return metrics.getTotal();
}
@Override
public long getMax() {
return metrics.getMax();
}
@Override
public long getMean() {
return metrics.getMean();
}
@Override
public long getStartTime() {
return metrics.getStartTime();
}
@Override
public long getLastQueryTime() {
return lastQueryTime;
}
@Override
public boolean isAutoTuned() {
return queryPlan.isAutoTuned();
}
@Override
public String getQueryPlanHash() {
return queryPlan.getSqlHash();
}
@Override
public String getSql() {
return queryPlan.getSql();
}
@Override
public List<MetaOrmQueryOrigin> getOrigins() {
return origins;
}
}
}