#1345 - Refactor io.ebean.meta.MetaInfoManager API (query execution metrics). Breaking change for people collecting query execution metrics.

This commit is contained in:
Rob Bygrave
2018-03-10 02:51:51 +13:00
parent eda6350d89
commit 85bfe3d03e
79 changed files with 928 additions and 466 deletions
@@ -24,7 +24,7 @@ import java.sql.SQLException;
*/
public abstract class AbstractSqlQueryRequest {
private final SpiSqlBinding query;
protected final SpiSqlBinding query;
protected final SpiEbeanServer server;
@@ -1,7 +1,7 @@
package io.ebeaninternal.server.core;
import io.ebean.bean.ObjectGraphNode;
import io.ebean.meta.MetaObjectGraphNodeStats;
import io.ebean.meta.MetaOrmQueryNode;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
@@ -35,7 +35,7 @@ public class CObjectGraphNodeStatistics {
totalBeans.add(beanCount);
}
public MetaObjectGraphNodeStats get(boolean reset) {
public MetaOrmQueryNode get(boolean reset) {
if (reset) {
return new Snapshot(node, startTime.getAndSet(System.currentTimeMillis()), count.sumThenReset(),
totalTime.sumThenReset(), totalBeans.sumThenReset());
@@ -44,7 +44,7 @@ public class CObjectGraphNodeStatistics {
}
}
private static class Snapshot implements MetaObjectGraphNodeStats {
private static class Snapshot implements MetaOrmQueryNode {
private final ObjectGraphNode node;
private final long startTime;
@@ -1,12 +1,13 @@
package io.ebeaninternal.server.core;
import io.ebean.meta.AbstractMetricVisitor;
import io.ebean.meta.BasicMetricVisitor;
import io.ebean.meta.MetaInfoManager;
import io.ebean.meta.MetaObjectGraphNodeStats;
import io.ebean.meta.MetaOrmQueryMetric;
import io.ebean.meta.MetaOrmQueryNode;
import io.ebean.meta.MetaQueryMetric;
import io.ebean.meta.MetaQueryPlanStatistic;
import io.ebean.meta.MetaTimedMetric;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.query.CQueryPlanStatsCollector;
import io.ebean.meta.MetricVisitor;
import java.util.ArrayList;
import java.util.List;
@@ -23,29 +24,26 @@ public class DefaultMetaInfoManager implements MetaInfoManager {
}
@Override
public List<MetaTimedMetric> collectTransactionStatistics(boolean reset) {
return server.collectTransactionStatistics(reset);
public void visitMetrics(MetricVisitor visitor) {
server.visitMetrics(visitor);
}
@Override
public List<MetaQueryMetric> collectQueryStatistics(boolean reset) {
return server.collectQueryStatistics(reset);
public BasicMetricVisitor visitBasic() {
BasicMetricVisitor basic = new BasicMetricVisitor();
visitMetrics(basic);
return basic;
}
@Override
public List<MetaQueryPlanStatistic> collectQueryPlanStatistics(boolean reset) {
CQueryPlanStatsCollector collector = new CQueryPlanStatsCollector(reset);
for (BeanDescriptor<?> desc : server.getBeanDescriptors()) {
desc.collectQueryPlanStatistics(collector);
}
return collector.getList();
public void resetAllMetrics() {
server.visitMetrics(new ResetVisitor());
}
@Override
public List<MetaObjectGraphNodeStats> collectNodeStatistics(boolean reset) {
public List<MetaOrmQueryNode> collectNodeStatistics(boolean reset) {
List<MetaObjectGraphNodeStats> list = new ArrayList<>();
List<MetaOrmQueryNode> list = new ArrayList<>();
for (CObjectGraphNodeStatistics nodeStatistics : server.objectGraphStats.values()) {
if (!nodeStatistics.isEmpty()) {
list.add(nodeStatistics.get(reset));
@@ -54,4 +52,29 @@ public class DefaultMetaInfoManager implements MetaInfoManager {
return list;
}
/**
* Visitor that resets the statistics but doesn't collect them.
*/
private static class ResetVisitor extends AbstractMetricVisitor {
ResetVisitor() {
super(true, true, true);
}
@Override
public void visitTimed(MetaTimedMetric metric) {
// ignore
}
@Override
public void visitQuery(MetaQueryMetric metric) {
// ignore
}
@Override
public void visitOrmQuery(MetaOrmQueryMetric metric) {
// ignore
}
}
}
@@ -48,8 +48,7 @@ import io.ebean.event.BeanPersistController;
import io.ebean.event.readaudit.ReadAuditLogger;
import io.ebean.event.readaudit.ReadAuditPrepare;
import io.ebean.meta.MetaInfoManager;
import io.ebean.meta.MetaQueryMetric;
import io.ebean.meta.MetaTimedMetric;
import io.ebean.meta.MetricVisitor;
import io.ebean.plugin.BeanType;
import io.ebean.plugin.Plugin;
import io.ebean.plugin.Property;
@@ -2192,10 +2191,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
}
public List<MetaTimedMetric> collectTransactionStatistics(boolean reset) {
return transactionManager.collectTransactionStatistics(reset);
}
@Override
public Set<Property> checkUniqueness(Object bean) {
return checkUniqueness(bean, null);
@@ -2237,8 +2232,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
/**
* Returns a set of properties if saving the bean will violate the unique constraints
* (definded by given properties).
* Returns a set of properties if saving the bean will violate the unique constraints (defined by given properties).
*/
private Set<Property> checkUniqueness(EntityBean entityBean, BeanDescriptor<?> beanDesc, BeanProperty[] props,
Transaction transaction) {
@@ -2261,15 +2255,24 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
if (findCount(query, transaction) > 0) {
Set<Property> ret = new LinkedHashSet<>();
for (Property prop : props) {
ret.add(prop);
}
Collections.addAll(ret, props);
return ret;
}
return null;
}
public List<MetaQueryMetric> collectQueryStatistics(boolean reset) {
return dtoBeanManager.collectStats(reset);
@Override
public void visitMetrics(MetricVisitor visitor) {
visitor.visitStart();
if (visitor.isCollectTransactionMetrics()) {
transactionManager.visitMetrics(visitor);
}
if (visitor.isCollectQueryMetrics()) {
beanDescriptorManager.visitMetrics(visitor);
dtoBeanManager.visitMetrics(visitor);
relationalQueryEngine.visitMetrics(visitor);
persister.visitMetrics(visitor);
}
visitor.visitEnd();
}
}
@@ -22,6 +22,7 @@ public abstract class PersistRequest extends BeanRequest implements BatchPostExe
UPDATESQL(EVT_UPDATESQL),
CALLABLESQL(EVT_CALLABLESQL);
String profileEventId;
Type(String profileEventId) {
this.profileEventId = profileEventId;
}
@@ -36,12 +37,30 @@ public abstract class PersistRequest extends BeanRequest implements BatchPostExe
final PersistExecute persistExecute;
protected String label;
protected long startNanos;
PersistRequest(SpiEbeanServer server, SpiTransaction t, PersistExecute persistExecute) {
super(server, t);
this.persistExecute = persistExecute;
}
/**
* Used by CallableSqlRequest and UpdateSqlRequest.
*/
public PersistRequest(SpiEbeanServer server, SpiTransaction t, PersistExecute persistExecute) {
super(server, t);
this.persistExecute = persistExecute;
PersistRequest(SpiEbeanServer server, SpiTransaction t, PersistExecute persistExecute, String label) {
this(server, t, persistExecute);
this.label = label;
}
/**
* Effectively set start nanos if we are collecting metrics on a label.
*/
public void startBind(boolean batchThisRequest) {
if (!batchThisRequest && label != null) {
startNanos = System.nanoTime();
}
}
/**
@@ -31,10 +31,9 @@ public final class PersistRequestCallableSql extends PersistRequest {
/**
* Create.
*/
public PersistRequestCallableSql(SpiEbeanServer server,
CallableSql cs, SpiTransaction t, PersistExecute persistExecute) {
public PersistRequestCallableSql(SpiEbeanServer server, CallableSql cs, SpiTransaction t, PersistExecute persistExecute) {
super(server, t, persistExecute);
super(server, t, persistExecute, cs.getLabel());
this.type = PersistRequest.Type.CALLABLESQL;
this.callableSql = (SpiCallableSql) cs;
}
@@ -88,7 +87,9 @@ public final class PersistRequestCallableSql extends PersistRequest {
*/
@Override
public void postExecute() {
if (startNanos > 0) {
persistExecute.collectSqlCall(label, startNanos, rowCount);
}
if (transaction.isLogSummary()) {
String m = "CallableSql label[" + callableSql.getLabel() + "]" + " rows[" + rowCount + "]" + " bind[" + bindLog + "]";
transaction.logSummary(m);
@@ -27,7 +27,7 @@ public final class PersistRequestOrmUpdate extends PersistRequest {
public PersistRequestOrmUpdate(SpiEbeanServer server, BeanManager<?> mgr, SpiUpdate<?> ormUpdate,
SpiTransaction t, PersistExecute persistExecute) {
super(server, t, persistExecute);
super(server, t, persistExecute, ormUpdate.getLabel());
this.beanDescriptor = mgr.getBeanDescriptor();
this.ormUpdate = ormUpdate;
}
@@ -86,7 +86,9 @@ public final class PersistRequestOrmUpdate extends PersistRequest {
*/
@Override
public void postExecute() {
if (startNanos > 0) {
persistExecute.collectOrmUpdate(label, startNanos, rowCount);
}
OrmUpdateType ormUpdateType = ormUpdate.getOrmUpdateType();
String tableName = ormUpdate.getBaseTable();
@@ -33,7 +33,7 @@ public final class PersistRequestUpdateSql extends PersistRequest {
public PersistRequestUpdateSql(SpiEbeanServer server, SqlUpdate updateSql,
SpiTransaction t, PersistExecute persistExecute) {
super(server, t, persistExecute);
super(server, t, persistExecute, updateSql.getLabel());
this.type = Type.UPDATESQL;
this.updateSql = (SpiSqlUpdate) updateSql;
}
@@ -102,7 +102,9 @@ public final class PersistRequestUpdateSql extends PersistRequest {
*/
@Override
public void postExecute() {
if (startNanos > 0) {
persistExecute.collectSqlUpdate(label, startNanos, rowCount);
}
if (transaction.isLogSummary()) {
String m = description + " table[" + tableName + "] rows[" + rowCount + "] bind[" + bindLog + "]";
transaction.logSummary(m);
@@ -6,6 +6,7 @@ import io.ebean.SqlUpdate;
import io.ebean.Transaction;
import io.ebean.Update;
import io.ebean.bean.EntityBean;
import io.ebean.meta.MetricVisitor;
import java.util.Collection;
import java.util.List;
@@ -78,4 +79,8 @@ public interface Persister {
*/
<T> List<T> draftRestore(Query<T> query, Transaction transaction);
/**
* Visit the metrics.
*/
void visitMetrics(MetricVisitor visitor);
}
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.core;
import io.ebean.SqlRow;
import io.ebean.meta.MetricVisitor;
import java.util.List;
import java.util.function.Consumer;
@@ -29,4 +30,13 @@ public interface RelationalQueryEngine {
*/
void findEach(RelationalQueryRequest request, Predicate<SqlRow> consumer);
/**
* Collect SQL query execution statistics.
*/
void collect(String label, long exeMicros, int rows);
/**
* Visit the metrics.
*/
void visitMetrics(MetricVisitor visitor);
}
@@ -46,7 +46,11 @@ public final class RelationalQueryRequest extends AbstractSqlQueryRequest {
@Override
protected void requestComplete() {
String label = query.getLabel();
if (label != null) {
long exeMicros = (System.nanoTime() - startNano) / 1000L;
queryEngine.collect(label, exeMicros, rows);
}
}
public void findEach(Consumer<SqlRow> consumer) {
@@ -27,6 +27,7 @@ import io.ebean.event.changelog.ChangeType;
import io.ebean.event.readaudit.ReadAuditLogger;
import io.ebean.event.readaudit.ReadAuditPrepare;
import io.ebean.event.readaudit.ReadEvent;
import io.ebean.meta.MetricVisitor;
import io.ebean.plugin.BeanDocType;
import io.ebean.plugin.BeanType;
import io.ebean.plugin.ExpressionPath;
@@ -61,7 +62,6 @@ import io.ebeaninternal.server.el.ElPropertyDeploy;
import io.ebeaninternal.server.el.ElPropertyValue;
import io.ebeaninternal.server.persist.DmlUtil;
import io.ebeaninternal.server.query.CQueryPlan;
import io.ebeaninternal.server.query.CQueryPlanStatsCollector;
import io.ebeaninternal.server.query.SqlTreeProperty;
import io.ebeaninternal.server.querydefn.OrmQueryDetail;
import io.ebeaninternal.server.rawsql.SpiRawSql;
@@ -1598,10 +1598,13 @@ public class BeanDescriptor<T> implements BeanType<T> {
return new DeployUpdateParser(this).parse(ormUpdateStatement);
}
public void collectQueryPlanStatistics(CQueryPlanStatsCollector collector) {
/**
* Visit all the ORM query plan metrics (includes UpdateQuery with updates and deletes).
*/
public void visitMetrics(MetricVisitor visitor) {
for (CQueryPlan queryPlan : queryPlanCache.values()) {
if (!queryPlan.isEmptyStats()) {
collector.add(queryPlan.getSnapshot(collector.isReset()));
visitor.visitOrmQuery(queryPlan.getSnapshot(visitor.isReset()));
}
}
}
@@ -19,6 +19,7 @@ import io.ebean.event.changelog.ChangeLogFilter;
import io.ebean.event.changelog.ChangeLogListener;
import io.ebean.event.changelog.ChangeLogPrepare;
import io.ebean.event.changelog.ChangeLogRegister;
import io.ebean.meta.MetricVisitor;
import io.ebean.plugin.BeanType;
import io.ebean.util.AnnotationUtil;
import io.ebeaninternal.api.ConcurrencyMode;
@@ -1632,6 +1633,12 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
target.setPrimaryKeyJoin(inverseJoin);
}
public void visitMetrics(MetricVisitor visitor) {
for (BeanDescriptor<?> desc : immutableDescriptorList) {
desc.visitMetrics(visitor);
}
}
/**
* Comparator to sort the BeanDescriptors by name.
*/
@@ -1,6 +1,6 @@
package io.ebeaninternal.server.dto;
import io.ebeaninternal.metric.QueryPlanCollector;
import io.ebean.meta.MetricVisitor;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -37,9 +37,9 @@ public class DtoBeanDescriptor<T> {
plans.put(planKey, plan);
}
public void collectStats(QueryPlanCollector collector) {
public void visit(MetricVisitor visitor) {
for (DtoQueryPlan plan : plans.values()) {
plan.collectStats(collector);
plan.visit(visitor);
}
}
}
@@ -1,11 +1,8 @@
package io.ebeaninternal.server.dto;
import io.ebean.meta.MetaQueryMetric;
import io.ebeaninternal.metric.MetricFactory;
import io.ebeaninternal.metric.QueryPlanCollector;
import io.ebean.meta.MetricVisitor;
import io.ebeaninternal.server.type.TypeManager;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -41,13 +38,9 @@ public class DtoBeanManager {
}
}
public List<MetaQueryMetric> collectStats(boolean reset) {
QueryPlanCollector collector = MetricFactory.get().createCollector(reset);
public void visitMetrics(MetricVisitor visitor) {
for (DtoBeanDescriptor value : descriptorMap.values()) {
value.collectStats(collector);
value.visit(visitor);
}
return collector.complete();
}
}
@@ -1,5 +1,6 @@
package io.ebeaninternal.server.dto;
import io.ebean.meta.MetricType;
import io.ebeaninternal.api.SpiDtoQuery;
import io.ebeaninternal.metric.MetricFactory;
import io.ebeaninternal.metric.QueryPlanMetric;
@@ -44,6 +45,6 @@ public class DtoMappingRequest {
}
public QueryPlanMetric createMetric() {
return MetricFactory.get().createQueryPlanMetric(type, label, sql);
return MetricFactory.get().createQueryPlanMetric(MetricType.DTO, type, label, sql);
}
}
@@ -1,6 +1,6 @@
package io.ebeaninternal.server.dto;
import io.ebeaninternal.metric.QueryPlanCollector;
import io.ebean.meta.MetricVisitor;
import io.ebeaninternal.server.type.DataReader;
import java.sql.SQLException;
@@ -21,7 +21,7 @@ public interface DtoQueryPlan {
void collect(long exeMicros, int rows);
/**
* Collect the query plan statistics.
* Visit the metric (if not empty).
*/
void collectStats(QueryPlanCollector collector);
void visit(MetricVisitor visitor);
}
@@ -1,6 +1,6 @@
package io.ebeaninternal.server.dto;
import io.ebeaninternal.metric.QueryPlanCollector;
import io.ebean.meta.MetricVisitor;
import io.ebeaninternal.metric.QueryPlanMetric;
import io.ebeaninternal.metric.TimedMetric;
@@ -21,8 +21,7 @@ abstract class DtoQueryPlanBase implements DtoQueryPlan {
}
@Override
public void collectStats(QueryPlanCollector collector) {
planMetric.collect(collector);
public void visit(MetricVisitor visitor) {
planMetric.visit(visitor);
}
}
@@ -513,6 +513,11 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
return query.setDisableReadAuditing();
}
@Override
public Query<T> setLabel(String label) {
return query.setLabel(label);
}
@Override
public ExpressionList<T> having() {
return query.having();
@@ -798,6 +798,11 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
return exprList.setCountDistinct(orderBy);
}
@Override
public Query<T> setLabel(String label) {
return exprList.setLabel(label);
}
@Override
public ExpressionList<T> startsWith(String propertyName, String value) {
return exprList.startsWith(propertyName, value);
@@ -1,6 +1,10 @@
package io.ebeaninternal.server.persist;
import io.ebean.meta.MetricType;
import io.ebean.meta.MetricVisitor;
import io.ebeaninternal.api.SpiTransaction;
import io.ebeaninternal.metric.MetricFactory;
import io.ebeaninternal.metric.TimedMetricMap;
import io.ebeaninternal.server.core.PersistRequestCallableSql;
import io.ebeaninternal.server.core.PersistRequestOrmUpdate;
import io.ebeaninternal.server.core.PersistRequestUpdateSql;
@@ -24,15 +28,48 @@ final class DefaultPersistExecute implements PersistExecute {
*/
private final int defaultBatchSize;
private final TimedMetricMap ormUpdateMetric;
private final TimedMetricMap sqlUpdateMetric;
private final TimedMetricMap sqlCallMetric;
/**
* Construct this DmlPersistExecute.
*/
DefaultPersistExecute(Binder binder, int defaultBatchSize) {
this.exeOrmUpdate = new ExeOrmUpdate(binder);
this.exeUpdateSql = new ExeUpdateSql(binder);
this.exeCallableSql = new ExeCallableSql(binder);
this.defaultBatchSize = defaultBatchSize;
this.ormUpdateMetric = MetricFactory.get().createTimedMetricMap(MetricType.SQL, "orm.update.");
this.sqlUpdateMetric = MetricFactory.get().createTimedMetricMap(MetricType.SQL, "sql.update.");
this.sqlCallMetric = MetricFactory.get().createTimedMetricMap(MetricType.SQL, "sql.call.");
}
@Override
public void visitMetrics(MetricVisitor visitor) {
ormUpdateMetric.visit(visitor);
sqlUpdateMetric.visit(visitor);
sqlCallMetric.visit(visitor);
}
@Override
public void collectOrmUpdate(String label, long startNanos, int rowCount) {
long exeMicros = (System.nanoTime() - startNanos) / 1000L;
ormUpdateMetric.add(label, exeMicros, rowCount);
}
@Override
public void collectSqlUpdate(String label, long startNanos, int rowCount) {
long exeMicros = (System.nanoTime() - startNanos) / 1000L;
sqlUpdateMetric.add(label, exeMicros, rowCount);
}
@Override
public void collectSqlCall(String label, long startNanos, int rowCount) {
long exeMicros = (System.nanoTime() - startNanos) / 1000L;
sqlCallMetric.add(label, exeMicros, rowCount);
}
@Override
@@ -10,6 +10,7 @@ import io.ebean.bean.BeanCollection.ModifyListenMode;
import io.ebean.bean.EntityBean;
import io.ebean.bean.PersistenceContext;
import io.ebean.event.BeanPersistController;
import io.ebean.meta.MetricVisitor;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.SpiTransaction;
import io.ebeaninternal.api.SpiUpdate;
@@ -79,6 +80,11 @@ public final class DefaultPersister implements Persister {
this.persistExecute = new DefaultPersistExecute(binder, server.getServerConfig().getPersistBatchSize());
}
@Override
public void visitMetrics(MetricVisitor visitor) {
persistExecute.visitMetrics(visitor);
}
/**
* Execute the CallableSql.
*/
@@ -60,6 +60,7 @@ class ExeCallableSql {
private CallableStatement bindStmt(PersistRequestCallableSql request, boolean batchThisRequest) throws SQLException {
request.startBind(batchThisRequest);
SpiCallableSql callableSql = request.getCallableSql();
SpiTransaction t = request.getTransaction();
@@ -75,6 +75,7 @@ class ExeOrmUpdate {
private PreparedStatement bindStmt(PersistRequestOrmUpdate request, boolean batchThisRequest) throws SQLException {
request.startBind(batchThisRequest);
SpiUpdate<?> ormUpdate = request.getOrmUpdate();
SpiTransaction t = request.getTransaction();
@@ -83,6 +83,7 @@ class ExeUpdateSql {
private PreparedStatement bindStmt(PersistRequestUpdateSql request, boolean batchThisRequest) throws SQLException {
request.startBind(batchThisRequest);
SpiSqlUpdate updateSql = request.getUpdateSql();
SpiTransaction t = request.getTransaction();
@@ -1,5 +1,6 @@
package io.ebeaninternal.server.persist;
import io.ebean.meta.MetricVisitor;
import io.ebeaninternal.api.SpiTransaction;
import io.ebeaninternal.server.core.PersistRequestCallableSql;
import io.ebeaninternal.server.core.PersistRequestOrmUpdate;
@@ -34,4 +35,23 @@ public interface PersistExecute {
*/
int executeSqlUpdate(PersistRequestUpdateSql request);
/**
* Collect execution metrics for sql update.
*/
void collectOrmUpdate(String label, long startNanos, int rowCount);
/**
* Collect execution metrics for sql update.
*/
void collectSqlUpdate(String label, long startNanos, int rowCount);
/**
* Collect execution metrics for sql callable.
*/
void collectSqlCall(String label, long startNanos, int rowCount);
/**
* Visit the metrics.
*/
void visitMetrics(MetricVisitor visitor);
}
@@ -1,7 +1,7 @@
package io.ebeaninternal.server.profile;
import io.ebean.meta.MetricType;
import io.ebeaninternal.metric.MetricFactory;
import io.ebeaninternal.metric.QueryPlanCollector;
import io.ebeaninternal.metric.QueryPlanMetric;
import io.ebeaninternal.metric.TimedMetric;
import io.ebeaninternal.metric.TimedMetricMap;
@@ -12,22 +12,18 @@ import io.ebeaninternal.metric.TimedMetricMap;
public class DMetricFactory implements MetricFactory {
@Override
public TimedMetricMap createTimedMetricMap(String name) {
return new DTimedMetricMap(name);
public TimedMetricMap createTimedMetricMap(MetricType metricType, String name) {
return new DTimedMetricMap(metricType, name);
}
@Override
public TimedMetric createTimedMetric(String name) {
return new DTimedMetric(name);
public TimedMetric createTimedMetric(MetricType metricType, String name) {
return new DTimedMetric(metricType, name);
}
@Override
public QueryPlanMetric createQueryPlanMetric(Class<?> type, String label, String sql) {
return new DQueryPlanMetric(new DQueryPlanMeta(type, label, sql), createTimedMetric(label));
public QueryPlanMetric createQueryPlanMetric(MetricType metricType, Class<?> type, String label, String sql) {
return new DQueryPlanMetric(new DQueryPlanMeta(type, label, sql), new DTimedMetric(metricType, label));
}
@Override
public QueryPlanCollector createCollector(boolean reset) {
return new DQueryPlanCollector(reset);
}
}
@@ -1,6 +1,7 @@
package io.ebeaninternal.server.profile;
import io.ebean.ProfileLocation;
import io.ebean.meta.MetricType;
import io.ebean.service.SpiProfileLocationFactory;
import io.ebeaninternal.metric.MetricFactory;
import io.ebeaninternal.metric.TimedMetric;
@@ -18,7 +19,7 @@ public class DProfileLocationFactory implements SpiProfileLocationFactory {
@Override
public ProfileLocation create(int lineNumber, String label) {
TimedMetric timedMetric = MetricFactory.get().createTimedMetric("txn.named." + label);
TimedMetric timedMetric = MetricFactory.get().createTimedMetric(MetricType.TXN, "txn.named." + label);
DTimedProfileLocation loc = new DTimedProfileLocation(lineNumber, label, timedMetric);
TimedProfileLocationRegistry.register(loc);
@@ -1,7 +1,8 @@
package io.ebeaninternal.server.profile;
import io.ebean.meta.MetaQueryMetric;
import io.ebeaninternal.metric.QueryPlanCollector;
import io.ebean.meta.MetricType;
import io.ebean.meta.MetricVisitor;
import io.ebeaninternal.metric.QueryPlanMetric;
import io.ebeaninternal.metric.TimedMetric;
import io.ebeaninternal.metric.TimedMetricStats;
@@ -9,18 +10,18 @@ import io.ebeaninternal.metric.TimedMetricStats;
class DQueryPlanMetric implements QueryPlanMetric {
private final DQueryPlanMeta meta;
private final TimedMetric metric;
private final DTimedMetric metric;
DQueryPlanMetric(DQueryPlanMeta meta, TimedMetric metric) {
DQueryPlanMetric(DQueryPlanMeta meta, DTimedMetric metric) {
this.meta = meta;
this.metric = metric;
}
@Override
public void collect(QueryPlanCollector collector) {
TimedMetricStats stats = metric.collect(collector.isReset());
public void visit(MetricVisitor visitor) {
TimedMetricStats stats = metric.collect(visitor.isReset());
if (stats != null) {
collector.add(new Stats(meta, stats));
visitor.visitQuery(new Stats(meta, stats));
}
}
@@ -44,6 +45,11 @@ class DQueryPlanMetric implements QueryPlanMetric {
return meta + " " + stats + " sql:" + getSql();
}
@Override
public MetricType getMetricType() {
return stats.getMetricType();
}
@Override
public Class<?> getType() {
return meta.getType();
@@ -1,5 +1,6 @@
package io.ebeaninternal.server.profile;
import io.ebean.meta.MetricType;
import io.ebeaninternal.metric.TimedMetricStats;
/**
@@ -7,6 +8,8 @@ import io.ebeaninternal.metric.TimedMetricStats;
*/
class DTimeMetricStats implements TimedMetricStats {
private final MetricType metricType;
private final String name;
private String location;
@@ -21,7 +24,8 @@ class DTimeMetricStats implements TimedMetricStats {
private final long beanCount;
DTimeMetricStats(String name, long collectionStart, long count, long total, long max, long beanCount) {
DTimeMetricStats(MetricType metricType, String name, long collectionStart, long count, long total, long max, long beanCount) {
this.metricType = metricType;
this.name = name;
this.startTime = collectionStart;
this.count = count;
@@ -53,6 +57,11 @@ class DTimeMetricStats implements TimedMetricStats {
this.location = location;
}
@Override
public MetricType getMetricType() {
return metricType;
}
@Override
public String getName() {
return name;
@@ -1,9 +1,9 @@
package io.ebeaninternal.server.profile;
import io.ebean.meta.MetaTimedMetric;
import io.ebean.meta.MetricType;
import io.ebean.meta.MetricVisitor;
import io.ebeaninternal.metric.TimedMetric;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAccumulator;
import java.util.concurrent.atomic.LongAdder;
@@ -16,6 +16,8 @@ import java.util.concurrent.atomic.LongAdder;
*/
class DTimedMetric implements TimedMetric {
private final MetricType metricType;
private final String name;
private final LongAdder beanCount = new LongAdder();
@@ -28,7 +30,8 @@ class DTimedMetric implements TimedMetric {
private final AtomicLong startTime = new AtomicLong(System.currentTimeMillis());
DTimedMetric(String name) {
DTimedMetric(MetricType metricType, String name) {
this.metricType = metricType;
this.name = name;
}
@@ -54,11 +57,23 @@ class DTimedMetric implements TimedMetric {
return count.sum() == 0;
}
/**
* Reset all the internal counters and start time.
*/
@Override
public void collect(boolean reset, List<MetaTimedMetric> result) {
DTimeMetricStats metric = collect(reset);
public void reset() {
startTime.set(System.currentTimeMillis());
max.reset();
count.reset();
total.reset();
beanCount.reset();
}
@Override
public void visit(MetricVisitor visitor) {
DTimeMetricStats metric = collect(visitor.isReset());
if (metric != null) {
result.add(metric);
visitor.visitTimed(metric);
}
}
@@ -78,7 +93,7 @@ class DTimedMetric implements TimedMetric {
/**
* Return the current statistics resetting the internal values if reset is true.
*/
public DTimeMetricStats getStatistics(boolean reset) {
private DTimeMetricStats getStatistics(boolean reset) {
if (reset) {
// Note these values are not guaranteed to be consistent wrt each other
@@ -88,21 +103,11 @@ class DTimedMetric implements TimedMetric {
final long totalVal = total.sumThenReset();
final long countVal = count.sumThenReset();
final long startTimeVal = startTime.getAndSet(System.currentTimeMillis());
return new DTimeMetricStats(name, startTimeVal, countVal, totalVal, maxVal, beans);
return new DTimeMetricStats(metricType, name, startTimeVal, countVal, totalVal, maxVal, beans);
} else {
return new DTimeMetricStats(name, startTime.get(), count.sum(), total.sum(), max.get(), beanCount.sum());
return new DTimeMetricStats(metricType, name, startTime.get(), count.sum(), total.sum(), max.get(), beanCount.sum());
}
}
/**
* Reset all the internal counters and start time.
*/
public void reset() {
startTime.set(System.currentTimeMillis());
max.reset();
count.reset();
total.reset();
}
}
@@ -1,30 +1,38 @@
package io.ebeaninternal.server.profile;
import io.ebean.meta.MetaTimedMetric;
import io.ebean.meta.MetricType;
import io.ebean.meta.MetricVisitor;
import io.ebeaninternal.metric.TimedMetricMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
class DTimedMetricMap implements TimedMetricMap {
private final MetricType metricType;
private final String name;
private final ConcurrentHashMap<String, DTimedMetric> map = new ConcurrentHashMap<>();
DTimedMetricMap(String name) {
DTimedMetricMap(MetricType metricType, String name) {
this.metricType = metricType;
this.name = name;
}
@Override
public void add(String key, long exeMicros) {
map.computeIfAbsent(key, (k)-> new DTimedMetric(name + key)).add(exeMicros);
map.computeIfAbsent(key, (k) -> new DTimedMetric(metricType, name + key)).add(exeMicros);
}
@Override
public void collect(boolean reset, List<MetaTimedMetric> list) {
public void add(String key, long exeMicros, int rows) {
map.computeIfAbsent(key, (k) -> new DTimedMetric(metricType, name + key)).add(exeMicros, rows);
}
@Override
public void visit(MetricVisitor visitor) {
for (DTimedMetric value : map.values()) {
value.collect(reset, list);
value.visit(visitor);
}
}
}
@@ -1,11 +1,9 @@
package io.ebeaninternal.server.profile;
import io.ebean.meta.MetaTimedMetric;
import io.ebean.meta.MetricVisitor;
import io.ebeaninternal.metric.TimedMetric;
import io.ebeaninternal.metric.TimedMetricStats;
import java.util.List;
/**
* Default profile location that uses stack trace.
*/
@@ -37,13 +35,11 @@ class DTimedProfileLocation extends DProfileLocation implements TimedProfileLoca
}
@Override
public void collect(boolean reset, List<MetaTimedMetric> list) {
TimedMetricStats collect = timedMetric.collect(reset);
public void visit(MetricVisitor visitor) {
TimedMetricStats collect = timedMetric.collect(visitor.isReset());
if (collect != null) {
collect.setLocation(obtain());
list.add(collect);
visitor.visitTimed(collect);
}
}
}
@@ -1,11 +1,9 @@
package io.ebeaninternal.server.profile;
import io.ebean.ProfileLocation;
import io.ebean.meta.MetaTimedMetric;
import io.ebean.meta.MetricVisitor;
import io.ebeaninternal.metric.TimedMetric;
import java.util.List;
/**
* ProfileLocation that collects timing metrics.
*/
@@ -22,7 +20,7 @@ public interface TimedProfileLocation extends ProfileLocation {
TimedMetric getMetric();
/**
* Collect the metrics adding to the given list if the metrics are non empty.
* Visit the non empty metrics.
*/
void collect(boolean reset, List<MetaTimedMetric> list);
void visit(MetricVisitor visitor);
}
@@ -3,8 +3,12 @@ package io.ebeaninternal.server.query;
import io.ebean.ProfileLocation;
import io.ebean.bean.ObjectGraphNode;
import io.ebean.config.dbplatform.SqlLimitResponse;
import io.ebean.meta.MetricType;
import io.ebeaninternal.api.CQueryPlanKey;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.metric.MetricFactory;
import io.ebeaninternal.metric.TimedMetric;
import io.ebeaninternal.server.core.OrmQueryRequest;
import io.ebeaninternal.server.core.timezone.DataTimeZone;
import io.ebeaninternal.server.deploy.BeanProperty;
@@ -51,6 +55,10 @@ public class CQueryPlan {
private final ProfileLocation profileLocation;
private final String location;
private final String label;
private final CQueryPlanKey planKey;
private final boolean rawSql;
@@ -90,9 +98,12 @@ public class CQueryPlan {
this.dataTimeZone = server.getDataTimeZone();
this.beanType = request.getBeanDescriptor().getBeanType();
this.planKey = request.getQueryPlanKey();
this.profileLocation = request.getQuery().getProfileLocation();
this.autoTuned = request.getQuery().isAutoTuned();
this.asOfTableCount = request.getQuery().getAsOfTableCount();
SpiQuery<?> query = request.getQuery();
this.profileLocation = query.getProfileLocation();
this.label = query.getLabel();
this.location = location();
this.autoTuned = query.isAutoTuned();
this.asOfTableCount = query.getAsOfTableCount();
this.sql = sqlRes.getSql();
this.rowNumberIncluded = sqlRes.isIncludesRowNumberColumn();
this.sqlTree = sqlTree;
@@ -105,13 +116,15 @@ public class CQueryPlan {
/**
* Create a query plan for a raw sql query.
*/
CQueryPlan(OrmQueryRequest<?> request, String sql, SqlTree sqlTree,
boolean rawSql, boolean rowNumberIncluded, String logWhereSql) {
CQueryPlan(OrmQueryRequest<?> request, String sql, SqlTree sqlTree, boolean rawSql, boolean rowNumberIncluded, String logWhereSql) {
this.server = request.getServer();
this.dataTimeZone = server.getDataTimeZone();
this.beanType = request.getBeanDescriptor().getBeanType();
this.profileLocation = request.getQuery().getProfileLocation();
SpiQuery<?> query = request.getQuery();
this.profileLocation = query.getProfileLocation();
this.label = query.getLabel();
this.location = location();
this.planKey = buildPlanKey(sql, rawSql, rowNumberIncluded, logWhereSql);
this.autoTuned = false;
this.asOfTableCount = 0;
@@ -124,6 +137,9 @@ public class CQueryPlan {
this.stats = new CQueryPlanStats(this, server.isCollectQueryOrigins());
}
private String location() {
return (profileLocation == null) ? "" : profileLocation.shortDescription();
}
private CQueryPlanKey buildPlanKey(String sql, boolean rawSql, boolean rowNumberIncluded, String logWhereSql) {
@@ -143,6 +159,14 @@ public class CQueryPlan {
return profileLocation;
}
public String getLabel() {
return label;
}
public String getLocation() {
return location;
}
public DataReader createDataReader(ResultSet rset) {
return new RsetDataReader(dataTimeZone, rset);
}
@@ -240,17 +264,13 @@ public class CQueryPlan {
}
}
/**
* Return a copy of the current query statistics.
*/
public Snapshot getSnapshot(boolean reset) {
return stats.getSnapshot(reset);
}
/**
* Return the current query statistics.
*/
public CQueryPlanStats getQueryStats() {
return stats;
}
/**
* Return the time this query plan was last used.
*/
@@ -268,4 +288,8 @@ public class CQueryPlan {
public boolean isEmptyStats() {
return stats.isEmpty();
}
public TimedMetric createTimedMetric() {
return MetricFactory.get().createTimedMetric(MetricType.ORM, label);
}
}
@@ -2,16 +2,17 @@ package io.ebeaninternal.server.query;
import io.ebean.ProfileLocation;
import io.ebean.bean.ObjectGraphNode;
import io.ebean.meta.MetaQueryPlanOriginCount;
import io.ebean.meta.MetaQueryPlanStatistic;
import io.ebean.meta.MetaOrmQueryMetric;
import io.ebean.meta.MetaOrmQueryOrigin;
import io.ebean.meta.MetricType;
import io.ebeaninternal.metric.TimedMetric;
import io.ebeaninternal.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.AtomicLong;
import java.util.concurrent.atomic.LongAccumulator;
import java.util.concurrent.atomic.LongAdder;
/**
@@ -21,15 +22,7 @@ public final class CQueryPlanStats {
private final CQueryPlan queryPlan;
private final LongAdder count = new LongAdder();
private final LongAdder totalTime = new LongAdder();
private final LongAdder totalBeans = new LongAdder();
private final LongAccumulator maxTime = new LongAccumulator(Math::max, Long.MIN_VALUE);
private final AtomicLong startTime = new AtomicLong(System.currentTimeMillis());
private final TimedMetric timedMetric;
private long lastQueryTime;
@@ -39,16 +32,16 @@ public final class CQueryPlanStats {
* Construct for a given query plan.
*/
CQueryPlanStats(CQueryPlan queryPlan, boolean collectQueryOrigins) {
this.queryPlan = queryPlan;
this.origins = !collectQueryOrigins ? null : new ConcurrentHashMap<>();
this.timedMetric = queryPlan.createTimedMetric();
}
/**
* Return true if there are no statistics collected since the last reset.
*/
public boolean isEmpty() {
return count.sum() == 0;
return timedMetric.isEmpty();
}
/**
@@ -56,10 +49,7 @@ public final class CQueryPlanStats {
*/
public void add(long loadedBeanCount, long timeMicros, ObjectGraphNode objectGraphNode) {
count.increment();
totalBeans.add(loadedBeanCount);
totalTime.add(timeMicros);
maxTime.accumulate(timeMicros);
timedMetric.add(timeMicros, loadedBeanCount);
// not safe but should be atomic
lastQueryTime = System.currentTimeMillis();
@@ -82,14 +72,7 @@ public final class CQueryPlanStats {
* Reset the internal statistics counters.
*/
public void reset() {
// Racey but near enough for our purposes as we don't want locks
count.reset();
totalBeans.reset();
totalTime.reset();
maxTime.reset();
startTime.set(System.currentTimeMillis());
timedMetric.reset();
if (origins != null) {
for (LongAdder counter : origins.values()) {
counter.reset();
@@ -109,25 +92,20 @@ public final class CQueryPlanStats {
*/
Snapshot getSnapshot(boolean reset) {
List<MetaQueryPlanOriginCount> origins = getOrigins(reset);
// not guaranteed to be consistent due to time gaps between getting each value out of LongAdders but can live with that
// relative to the cost of making sure count and totalTime etc are all guaranteed to be consistent
if (reset) {
return new Snapshot(queryPlan, count.sumThenReset(), totalTime.sumThenReset(), totalBeans.sumThenReset(), maxTime.getThenReset(), startTime.getAndSet(System.currentTimeMillis()), lastQueryTime, origins);
}
return new Snapshot(queryPlan, count.sum(), totalTime.sum(), totalBeans.sum(), maxTime.get(), startTime.get(), lastQueryTime, origins);
TimedMetricStats collect = timedMetric.collect(reset);
List<MetaOrmQueryOrigin> origins = getOrigins(reset);
return new Snapshot(queryPlan, collect, lastQueryTime, origins);
}
/**
* Return the list/snapshot of the origins and their counter value.
*/
private List<MetaQueryPlanOriginCount> getOrigins(boolean reset) {
private List<MetaOrmQueryOrigin> getOrigins(boolean reset) {
if (origins == null) {
return Collections.emptyList();
}
List<MetaQueryPlanOriginCount> list = new ArrayList<>(origins.size());
List<MetaOrmQueryOrigin> list = new ArrayList<>(origins.size());
for (Entry<ObjectGraphNode, LongAdder> entry : origins.entrySet()) {
if (reset) {
@@ -142,7 +120,7 @@ public final class CQueryPlanStats {
/**
* Snapshot of the origin ObjectGraphNode and counter value.
*/
private static class OriginSnapshot implements MetaQueryPlanOriginCount {
private static class OriginSnapshot implements MetaOrmQueryOrigin {
private final ObjectGraphNode objectGraphNode;
private final long count;
@@ -170,70 +148,83 @@ public final class CQueryPlanStats {
/**
* A snapshot of the current statistics for a query plan.
*/
public static class Snapshot implements MetaQueryPlanStatistic {
static class Snapshot implements MetaOrmQueryMetric {
private final CQueryPlan queryPlan;
private final long count;
private final long totalTime;
private final long totalBeans;
private final long maxTime;
private final long startTime;
private final TimedMetricStats metrics;
private final long lastQueryTime;
private final List<MetaQueryPlanOriginCount> origins;
Snapshot(CQueryPlan queryPlan, long count, long totalTime, long totalBeans, long maxTime, long startTime, long lastQueryTime,
List<MetaQueryPlanOriginCount> origins) {
private final List<MetaOrmQueryOrigin> origins;
Snapshot(CQueryPlan queryPlan, TimedMetricStats metrics, long lastQueryTime, List<MetaOrmQueryOrigin> origins) {
this.queryPlan = queryPlan;
this.count = count;
this.totalTime = totalTime;
this.totalBeans = totalBeans;
this.maxTime = maxTime;
this.startTime = startTime;
this.metrics = metrics;
this.lastQueryTime = lastQueryTime;
this.origins = origins;
}
@Override
public String toString() {
ProfileLocation profileLocation = queryPlan.getProfileLocation();
String loc = (profileLocation == null) ? "" : profileLocation.shortDescription();
return "location:" + loc + " count:" + count + " time:" + totalTime + " maxTime:" + maxTime + " beans:" + totalBeans + " sql:" + getSql();
return "location:" + getLocation() + " metrics:" + metrics + " sql:" + getSql();
}
@Override
public Class<?> getBeanType() {
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 getExecutionCount() {
return count;
public long getBeanCount() {
return metrics.getBeanCount();
}
@Override
public long getTotalTimeMicros() {
return totalTime;
public long getCount() {
return metrics.getCount();
}
@Override
public long getTotalLoadedBeans() {
return totalBeans;
public long getTotal() {
return metrics.getTotal();
}
@Override
public long getMaxTimeMicros() {
return maxTime;
public long getMax() {
return metrics.getMax();
}
@Override
public long getCollectionStart() {
return startTime;
public long getMean() {
return metrics.getMean();
}
@Override
public long getStartTime() {
return metrics.getStartTime();
}
@Override
@@ -257,17 +248,7 @@ public final class CQueryPlanStats {
}
@Override
public long getAvgTimeMicros() {
return count < 1 ? 0 : totalTime / count;
}
@Override
public long getAvgLoadedBeans() {
return count < 1 ? 0 : totalBeans / count;
}
@Override
public List<MetaQueryPlanOriginCount> getOrigins() {
public List<MetaOrmQueryOrigin> getOrigins() {
return origins;
}
@@ -1,32 +0,0 @@
package io.ebeaninternal.server.query;
import io.ebean.meta.MetaQueryPlanStatistic;
import java.util.ArrayList;
import java.util.List;
/**
* Helper to collect query plan execution statistics.
*/
public class CQueryPlanStatsCollector {
private final boolean reset;
List<MetaQueryPlanStatistic> list = new ArrayList<>();
public CQueryPlanStatsCollector(boolean reset) {
this.reset = reset;
}
public boolean isReset() {
return reset;
}
public void add(MetaQueryPlanStatistic planStatistic) {
list.add(planStatistic);
}
public List<MetaQueryPlanStatistic> getList() {
return list;
}
}
@@ -1,7 +1,11 @@
package io.ebeaninternal.server.query;
import io.ebean.SqlRow;
import io.ebean.meta.MetricType;
import io.ebean.meta.MetricVisitor;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.metric.MetricFactory;
import io.ebeaninternal.metric.TimedMetricMap;
import io.ebeaninternal.server.core.Message;
import io.ebeaninternal.server.core.RelationalQueryEngine;
import io.ebeaninternal.server.core.RelationalQueryRequest;
@@ -25,10 +29,23 @@ public class DefaultRelationalQueryEngine implements RelationalQueryEngine {
private final boolean binaryOptimizedUUID;
private final TimedMetricMap timedMetricMap;
public DefaultRelationalQueryEngine(Binder binder, String dbTrueValue, boolean binaryOptimizedUUID) {
this.binder = binder;
this.dbTrueValue = dbTrueValue == null ? "true" : dbTrueValue;
this.binaryOptimizedUUID = binaryOptimizedUUID;
this.timedMetricMap = MetricFactory.get().createTimedMetricMap(MetricType.SQL, "sql.query.");
}
@Override
public void collect(String label, long exeMicros, int rows) {
timedMetricMap.add(label, exeMicros, rows);
}
@Override
public void visitMetrics(MetricVisitor visitor) {
timedMetricMap.visit(visitor);
}
@Override
@@ -51,6 +51,7 @@ public class DefaultDtoQuery<T> implements SpiDtoQuery<T> {
this.server = server;
this.descriptor = descriptor;
this.ormQuery = ormQuery;
this.label = ormQuery.getLabel();
}
/**
@@ -65,7 +66,7 @@ public class DefaultDtoQuery<T> implements SpiDtoQuery<T> {
@Override
public String planKey() {
return sql+":first"+firstRow+":max"+maxRows;
return sql + ":first" + firstRow + ":max" + maxRows;
}
@Override
@@ -96,6 +96,8 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
private Type type;
private String label;
private Mode mode = Mode.NORMAL;
private Object tenantId;
@@ -340,6 +342,17 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
return this;
}
@Override
public String getLabel() {
return label;
}
@Override
public Query<T> setLabel(String label) {
this.label = label;
return this;
}
@Override
public boolean isAutoTunable() {
return nativeSql == null && beanDescriptor.isAutoTunable();
@@ -1,6 +1,7 @@
package io.ebeaninternal.server.querydefn;
import io.ebean.EbeanServer;
import io.ebean.Update;
import io.ebeaninternal.api.BindParams;
import io.ebeaninternal.api.SpiUpdate;
@@ -23,6 +24,8 @@ public final class DefaultOrmUpdate<T> implements SpiUpdate<T>, Serializable {
*/
private final String name;
private String label;
/**
* The parameters used to bind to the sql.
*/
@@ -137,6 +140,17 @@ public final class DefaultOrmUpdate<T> implements SpiUpdate<T>, Serializable {
return name;
}
@Override
public Update<T> setLabel(String label) {
this.label = label;
return this;
}
@Override
public String getLabel() {
return label;
}
@Override
public String getUpdateStatement() {
return updateStatement;
@@ -19,6 +19,8 @@ public class DefaultRelationalQuery implements SpiSqlQuery {
private final transient EbeanServer server;
private String label;
private String query;
private int firstRow;
@@ -122,6 +124,17 @@ public class DefaultRelationalQuery implements SpiSqlQuery {
return this;
}
@Override
public String getLabel() {
return label;
}
@Override
public DefaultRelationalQuery setLabel(String label) {
this.label = label;
return this;
}
@Override
public BindParams getBindParams() {
return bindParams;
@@ -11,7 +11,8 @@ import io.ebean.config.dbplatform.DatabasePlatform.OnQueryOnly;
import io.ebean.event.changelog.ChangeLogListener;
import io.ebean.event.changelog.ChangeLogPrepare;
import io.ebean.event.changelog.ChangeSet;
import io.ebean.meta.MetaTimedMetric;
import io.ebean.meta.MetricType;
import io.ebean.meta.MetricVisitor;
import io.ebeaninternal.api.ScopeTrans;
import io.ebeaninternal.api.ScopedTransaction;
import io.ebeaninternal.api.SpiProfileHandler;
@@ -37,7 +38,6 @@ import javax.persistence.PersistenceException;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -170,9 +170,9 @@ public class TransactionManager implements SpiTransactionManager {
this.transactionFactory = TransactionFactoryBuilder.build(this, dataSourceSupplier, tenantProvider);
MetricFactory metricFactory = MetricFactory.get();
this.txnMain = metricFactory.createTimedMetric("txn.main");
this.txnReadOnly = metricFactory.createTimedMetric("txn.readonly");
this.txnNamed = metricFactory.createTimedMetricMap("txn.named.");
this.txnMain = metricFactory.createTimedMetric(MetricType.TXN, "txn.main");
this.txnReadOnly = metricFactory.createTimedMetric(MetricType.TXN, "txn.readonly");
this.txnNamed = metricFactory.createTimedMetricMap(MetricType.TXN, "txn.named.");
scopeManager.register(this);
}
@@ -528,21 +528,13 @@ public class TransactionManager implements SpiTransactionManager {
txnNamed.add(label, exeMicros);
}
/**
* Collect the transaction execution statistics since the last reset.
*/
public List<MetaTimedMetric> collectTransactionStatistics(boolean reset) {
List<MetaTimedMetric> list = new ArrayList<>();
txnMain.collect(reset, list);
txnReadOnly.collect(reset, list);
public void visitMetrics(MetricVisitor visitor) {
txnMain.visit(visitor);
txnReadOnly.visit(visitor);
txnNamed.visit(visitor);
for (TimedProfileLocation timedLocation : TimedProfileLocationRegistry.registered()) {
timedLocation.collect(reset, list);
timedLocation.visit(visitor);
}
txnNamed.collect(reset, list);
return list;
}
/**
@@ -562,7 +554,7 @@ public class TransactionManager implements SpiTransactionManager {
if (st instanceof ScopedTransaction) {
// can be null for Supports as that can start as a 'No Transaction' and then
// effectively be replaced by transactions inside the scope
((ScopedTransaction)st).complete(returnOrThrowable, opCode);
((ScopedTransaction) st).complete(returnOrThrowable, opCode);
}
}