mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#1855 - Add MetaInfoManager collectMetricsAsJson()
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user