#1855 - Add MetaInfoManager collectMetricsAsJson()

This commit is contained in:
rob bygrave
2019-11-07 16:35:25 +13:00
parent affd720390
commit 01054bf470
5 changed files with 356 additions and 14 deletions
@@ -16,6 +16,18 @@ public interface MetaInfoManager {
*/
ServerMetrics collectMetrics();
/**
* Collect the metrics in raw JSON form.
* <pre>{@code
*
* String metricsJson = database.getMetaInfoManager()
* .collectMetricsAsJson()
* .json();
*
* }</pre>
*/
ServerMetricsAsJson collectMetricsAsJson();
/**
* Collect query plans.
*/
@@ -0,0 +1,40 @@
package io.ebean.meta;
import java.util.Comparator;
/**
* Collect the metrics in raw JSON form.
*/
public interface ServerMetricsAsJson {
/**
* Set to false to exclude profile location.
*/
ServerMetricsAsJson withLocation(boolean withLocation);
/**
* Set to false to exclude SQL for query metrics.
*/
ServerMetricsAsJson withSql(boolean withSql);
/**
* Set to false to exclude SQL hash.
*/
ServerMetricsAsJson withHash(boolean withHash);
/**
* Set the sort property - see SortMetric
* @see SortMetric
*/
ServerMetricsAsJson withSort(Comparator<MetaTimedMetric> sortBy);
/**
* Set the new line character to use.
*/
ServerMetricsAsJson withNewLine(boolean withNewLine);
/**
* Return the metrics in raw JSON.
*/
String json();
}
@@ -12,6 +12,7 @@ import io.ebean.meta.MetaTimedMetric;
import io.ebean.meta.MetricVisitor;
import io.ebean.meta.QueryPlanRequest;
import io.ebean.meta.ServerMetrics;
import io.ebean.meta.ServerMetricsAsJson;
import java.util.ArrayList;
import java.util.List;
@@ -42,6 +43,11 @@ public class DefaultMetaInfoManager implements MetaInfoManager {
return visitBasic();
}
@Override
public ServerMetricsAsJson collectMetricsAsJson() {
return new DumpMetricsJson(server);
}
@Override
public BasicMetricVisitor visitBasic() {
BasicMetricVisitor basic = new BasicMetricVisitor();
@@ -0,0 +1,232 @@
package io.ebeaninternal.server.core;
import io.ebean.Database;
import io.ebean.ProfileLocation;
import io.ebean.meta.MetaCountMetric;
import io.ebean.meta.MetaOrmQueryMetric;
import io.ebean.meta.MetaQueryMetric;
import io.ebean.meta.MetaTimedMetric;
import io.ebean.meta.ServerMetrics;
import io.ebean.meta.ServerMetricsAsJson;
import io.ebean.meta.SortMetric;
import java.io.StringWriter;
import java.util.Comparator;
import java.util.List;
class DumpMetricsJson implements ServerMetricsAsJson {
private final Database database;
private final StringWriter writer = new StringWriter();
private boolean dumpHash = true;
private boolean dumpSql = true;
private boolean dumpLoc = true;
private Comparator<MetaTimedMetric> sortBy = SortMetric.NAME;
private int listCounter;
private int objKeyCounter;
private String newLine = "\n";
DumpMetricsJson(Database database) {
this.database = database;
}
@Override
public ServerMetricsAsJson withLocation(boolean withLocation) {
this.dumpLoc = withLocation;
return this;
}
@Override
public ServerMetricsAsJson withSql(boolean withSql) {
this.dumpSql = withSql;
return this;
}
@Override
public ServerMetricsAsJson withHash(boolean withHash) {
this.dumpHash = withHash;
return this;
}
@Override
public ServerMetricsAsJson withSort(Comparator<MetaTimedMetric> sortBy) {
this.sortBy = sortBy;
return this;
}
@Override
public ServerMetricsAsJson withNewLine(boolean withNewLine) {
this.newLine = withNewLine ? "\n" : "";
return this;
}
@Override
public String json() {
collect(database.getMetaInfoManager().collectMetrics());
return writer.toString();
}
private void collect(ServerMetrics serverMetrics) {
start();
for (MetaTimedMetric metric : serverMetrics.getTimedMetrics()) {
log(metric);
}
List<MetaCountMetric> countMetrics = serverMetrics.getCountMetrics();
if (!countMetrics.isEmpty()) {
if (sortBy != null) {
countMetrics.sort(SortMetric.COUNT_NAME);
}
for (MetaCountMetric metric : countMetrics) {
logCount(metric);
}
}
List<MetaOrmQueryMetric> ormQueryMetrics = serverMetrics.getOrmQueryMetrics();
if (!ormQueryMetrics.isEmpty()) {
if (sortBy != null) {
ormQueryMetrics.sort(sortBy);
}
for (MetaOrmQueryMetric metric : ormQueryMetrics) {
logQuery(metric);
}
}
List<MetaQueryMetric> dtoQueryMetrics = serverMetrics.getDtoQueryMetrics();
if (!dtoQueryMetrics.isEmpty()) {
if (sortBy != null) {
dtoQueryMetrics.sort(sortBy);
}
for (MetaQueryMetric metric : dtoQueryMetrics) {
logDtoQuery(metric);
}
}
end();
}
private void start() {
objStart();
key("db");
val(database.getName());
key("metrics");
listStart();
}
private void end() {
listEnd();
objEnd();
}
private void objStart() {
objKeyCounter = 0;
writer.append("{");
}
private void objEnd() {
writer.append("}");
}
private void listStart() {
listCounter = 0;
writer.append("[");
writer.append(newLine);
}
private void listEnd() {
writer.append("]");
}
private void key(String key) {
if (objKeyCounter++ > 0) {
writer.append(", ");
}
writer.append("\"").append(key).append("\":");
}
private void val(long count) {
writer.append(Long.toString(count));
}
private void val(String val) {
writer.append("\"").append(val).append("\"");
}
private void log(MetaTimedMetric metric) {
metricStart();
key("name");
val(metric.getName());
appendCounters(metric);
objEnd();
}
private void metricStart() {
if (listCounter++ > 0) {
writer.append(",").append(newLine);
}
objStart();
}
private void logCount(MetaCountMetric metric) {
metricStart();
key("name");
val(metric.getName());
key("count");
val(metric.getCount());
objEnd();
}
private void logQuery(MetaOrmQueryMetric metric) {
metricStart();
key("name");
val(metric.getName());
appendCounters(metric);
if (dumpHash) {
key("hash");
val(metric.getSqlHash());
}
appendProfileAndSql(metric);
objEnd();
}
private void logDtoQuery(MetaQueryMetric metric) {
metricStart();
key("name");
val(metric.getName());
appendCounters(metric);
appendProfileAndSql(metric);
objEnd();
}
private void appendProfileAndSql(MetaQueryMetric metric) {
ProfileLocation profileLocation = metric.getProfileLocation();
if (dumpLoc && profileLocation != null) {
key("loc");
val(profileLocation.shortDescription());
}
if (dumpSql) {
key("sql");
val(metric.getSql());
}
}
private void appendCounters(MetaTimedMetric timedMetric) {
key("count");
val(timedMetric.getCount());
key("total");
val(timedMetric.getTotal());
key("mean");
val(timedMetric.getMean());
key("max");
val(timedMetric.getMax());
}
}
@@ -8,6 +8,7 @@ import io.ebean.meta.MetaQueryPlan;
import io.ebean.meta.MetaTimedMetric;
import io.ebean.meta.QueryPlanRequest;
import io.ebean.meta.ServerMetrics;
import io.ebean.meta.SortMetric;
import org.ebeantest.LoggedSqlCollector;
import org.junit.Test;
import org.tests.model.basic.Customer;
@@ -138,20 +139,7 @@ public class TestCustomerFinder extends BaseTestCase {
ResetBasicData.reset();
resetAllMetrics();
List<Customer> customers = Customer.find.all();
assertThat(customers).isNotEmpty();
Customer customer = Customer.find.byId(1);
assertThat(customer).isNotNull();
Customer.find.byId(2);
Customer.find.namesStartingWith("F");
Customer.find.byNameStatus("Rob", Customer.Status.ACTIVE);
Customer.find.totalCount();
Customer.find.updateNames("Junk", 2000);
Customer.find.byId(3);
runQueries();
ServerMetrics metrics = server().getMetaInfoManager().collectMetrics();
@@ -172,7 +160,71 @@ public class TestCustomerFinder extends BaseTestCase {
for (MetaQueryPlan plan : plans) {
System.out.println(plan);
}
}
@Test
public void test_metricsAsJson_withAll() {
ResetBasicData.reset();
runQueries();
String metricsJson = server().getMetaInfoManager()
.collectMetricsAsJson()
.withHash(true)
.withLocation(true)
.withNewLine(true)
.withSql(true)
.withSort(SortMetric.TOTAL)
.json();
System.out.println(metricsJson);
assertThat(metricsJson).contains("\"name\":\"txn.main\"");
assertThat(metricsJson).contains("\"name\":\"Customer.findList\"");
assertThat(metricsJson).contains("\"loc\":\"CustomerFinder.byNameStatus(CustomerFinder.java:44)\"");
assertThat(metricsJson).contains("\"hash\":\"4d648ce0542aedfb042ad68746342730\"");
assertThat(metricsJson).contains("\"sql\":\"select t0.id, t0.status,");
}
@Test
public void test_metricsAsJson_minimal() {
ResetBasicData.reset();
runQueries();
String metricsJson = server().getMetaInfoManager()
.collectMetricsAsJson()
.withHash(false)
.withLocation(false)
.withNewLine(false)
.withSql(false)
.withSort(null)
.json();
System.out.println(metricsJson);
assertThat(metricsJson).contains("\"name\":\"txn.main\"");
assertThat(metricsJson).contains("\"name\":\"Customer.findList\"");
assertThat(metricsJson).doesNotContain("\"loc\":");
assertThat(metricsJson).doesNotContain("\"hash\":");
assertThat(metricsJson).doesNotContain("\"sql\":");
}
private void runQueries() {
resetAllMetrics();
List<Customer> customers = Customer.find.all();
assertThat(customers).isNotEmpty();
Customer customer = Customer.find.byId(1);
assertThat(customer).isNotNull();
Customer.find.byId(2);
Customer.find.namesStartingWith("F");
Customer.find.byNameStatus("Rob", Customer.Status.ACTIVE);
Customer.find.totalCount();
Customer.find.updateNames("Junk", 2000);
Customer.find.byId(3);
}
}