From 67c2e1d24c0f55907f45fb467456e0584eb3992b Mon Sep 17 00:00:00 2001 From: rob bygrave Date: Fri, 29 Nov 2019 17:19:01 +1300 Subject: [PATCH] #1871 - Add ability to write metrics in JSON form to Appendable --- .../io/ebean/meta/ServerMetricsAsJson.java | 12 ++ .../server/core/DumpMetricsJson.java | 134 ++++++++++-------- .../query/finder/TestCustomerFinder.java | 39 ++++- 3 files changed, 127 insertions(+), 58 deletions(-) diff --git a/src/main/java/io/ebean/meta/ServerMetricsAsJson.java b/src/main/java/io/ebean/meta/ServerMetricsAsJson.java index a85c072cb..5716730a6 100644 --- a/src/main/java/io/ebean/meta/ServerMetricsAsJson.java +++ b/src/main/java/io/ebean/meta/ServerMetricsAsJson.java @@ -33,6 +33,18 @@ public interface ServerMetricsAsJson { */ ServerMetricsAsJson withNewLine(boolean withNewLine); + /** + * Set to include a heading of the database name. + *

+ * When this is false the metrics are written without json array start or array end. + */ + ServerMetricsAsJson withHeader(boolean withHeader); + + /** + * Collect and write metrics as JSON to the given buffer. + */ + void write(Appendable buffer); + /** * Return the metrics in raw JSON. */ diff --git a/src/main/java/io/ebeaninternal/server/core/DumpMetricsJson.java b/src/main/java/io/ebeaninternal/server/core/DumpMetricsJson.java index d0ed03c12..fba6559ff 100644 --- a/src/main/java/io/ebeaninternal/server/core/DumpMetricsJson.java +++ b/src/main/java/io/ebeaninternal/server/core/DumpMetricsJson.java @@ -10,6 +10,7 @@ import io.ebean.meta.ServerMetrics; import io.ebean.meta.ServerMetricsAsJson; import io.ebean.meta.SortMetric; +import java.io.IOException; import java.io.StringWriter; import java.util.Comparator; import java.util.List; @@ -18,8 +19,9 @@ class DumpMetricsJson implements ServerMetricsAsJson { private final Database database; - private final StringWriter writer = new StringWriter(); + private Appendable writer; + private boolean withHeader = true; private boolean withHash = true; private boolean withSql = true; private boolean withLocation = true; @@ -34,6 +36,12 @@ class DumpMetricsJson implements ServerMetricsAsJson { this.database = database; } + @Override + public ServerMetricsAsJson withHeader(boolean withHeader) { + this.withHeader = withHeader; + return this; + } + @Override public ServerMetricsAsJson withLocation(boolean withLocation) { this.withLocation = withLocation; @@ -66,97 +74,111 @@ class DumpMetricsJson implements ServerMetricsAsJson { @Override public String json() { + writer = new StringWriter(); collect(database.getMetaInfoManager().collectMetrics()); return writer.toString(); } + @Override + public void write(Appendable buffer) { + writer = buffer; + collect(database.getMetaInfoManager().collectMetrics()); + } + private void collect(ServerMetrics serverMetrics) { + try { + start(); + for (MetaTimedMetric metric : serverMetrics.getTimedMetrics()) { + log(metric); + } - start(); - for (MetaTimedMetric metric : serverMetrics.getTimedMetrics()) { - log(metric); - } + List countMetrics = serverMetrics.getCountMetrics(); + if (!countMetrics.isEmpty()) { + if (sortBy != null) { + countMetrics.sort(SortMetric.COUNT_NAME); + } + for (MetaCountMetric metric : countMetrics) { + logCount(metric); + } + } - List countMetrics = serverMetrics.getCountMetrics(); - if (!countMetrics.isEmpty()) { - if (sortBy != null) { - countMetrics.sort(SortMetric.COUNT_NAME); + List ormQueryMetrics = serverMetrics.getOrmQueryMetrics(); + if (!ormQueryMetrics.isEmpty()) { + if (sortBy != null) { + ormQueryMetrics.sort(sortBy); + } + for (MetaOrmQueryMetric metric : ormQueryMetrics) { + logQuery(metric); + } } - for (MetaCountMetric metric : countMetrics) { - logCount(metric); - } - } - List ormQueryMetrics = serverMetrics.getOrmQueryMetrics(); - if (!ormQueryMetrics.isEmpty()) { - if (sortBy != null) { - ormQueryMetrics.sort(sortBy); - } - for (MetaOrmQueryMetric metric : ormQueryMetrics) { - logQuery(metric); + List dtoQueryMetrics = serverMetrics.getDtoQueryMetrics(); + if (!dtoQueryMetrics.isEmpty()) { + if (sortBy != null) { + dtoQueryMetrics.sort(sortBy); + } + for (MetaQueryMetric metric : dtoQueryMetrics) { + logDtoQuery(metric); + } } + end(); + } catch (IOException e) { + throw new RuntimeException("Error writing metrics as JSON", e); } - - List 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 start() throws IOException { + if (withHeader) { + objStart(); + key("db"); + val(database.getName()); + key("metrics"); + listStart(); + } } - private void end() { - listEnd(); - objEnd(); + private void end() throws IOException { + if (withHeader) { + listEnd(); + objEnd(); + } } - private void objStart() { + private void objStart() throws IOException { objKeyCounter = 0; writer.append("{"); } - private void objEnd() { + private void objEnd() throws IOException { writer.append("}"); } - private void listStart() { + private void listStart() throws IOException { listCounter = 0; writer.append("["); writer.append(newLine); } - private void listEnd() { + private void listEnd() throws IOException { writer.append("]"); } - private void key(String key) { + private void key(String key) throws IOException { if (objKeyCounter++ > 0) { writer.append(", "); } writer.append("\"").append(key).append("\":"); } - private void val(long count) { + private void val(long count) throws IOException { writer.append(Long.toString(count)); } - private void val(String val) { + private void val(String val) throws IOException { writer.append("\"").append(val).append("\""); } - private void metricStart(MetaMetric metric) { + private void metricStart(MetaMetric metric) throws IOException { if (listCounter++ > 0) { writer.append(",").append(newLine); } @@ -167,11 +189,11 @@ class DumpMetricsJson implements ServerMetricsAsJson { val(metric.getMetricType().name()); } - private void metricEnd() { + private void metricEnd() throws IOException { objEnd(); } - private void log(MetaTimedMetric metric) { + private void log(MetaTimedMetric metric) throws IOException { metricStart(metric); appendCounters(metric); if (withLocation) { @@ -180,14 +202,14 @@ class DumpMetricsJson implements ServerMetricsAsJson { metricEnd(); } - private void logCount(MetaCountMetric metric) { + private void logCount(MetaCountMetric metric) throws IOException { metricStart(metric); key("count"); val(metric.getCount()); metricEnd(); } - private void logQuery(MetaOrmQueryMetric metric) { + private void logQuery(MetaOrmQueryMetric metric) throws IOException { metricStart(metric); appendCounters(metric); if (withHash) { @@ -198,14 +220,14 @@ class DumpMetricsJson implements ServerMetricsAsJson { metricEnd(); } - private void logDtoQuery(MetaQueryMetric metric) { + private void logDtoQuery(MetaQueryMetric metric) throws IOException { metricStart(metric); appendCounters(metric); appendLocationAndSql(metric); metricEnd(); } - private void appendLocationAndSql(MetaQueryMetric metric) { + private void appendLocationAndSql(MetaQueryMetric metric) throws IOException { if (withLocation) { appendLocation(metric.getLocation()); } @@ -215,14 +237,14 @@ class DumpMetricsJson implements ServerMetricsAsJson { } } - private void appendLocation(String location) { + private void appendLocation(String location) throws IOException { if (location != null) { key("loc"); val(location); } } - private void appendCounters(MetaTimedMetric timedMetric) { + private void appendCounters(MetaTimedMetric timedMetric) throws IOException { key("count"); val(timedMetric.getCount()); key("total"); diff --git a/src/test/java/org/tests/query/finder/TestCustomerFinder.java b/src/test/java/org/tests/query/finder/TestCustomerFinder.java index e9a82abbc..50a9c48d8 100644 --- a/src/test/java/org/tests/query/finder/TestCustomerFinder.java +++ b/src/test/java/org/tests/query/finder/TestCustomerFinder.java @@ -178,7 +178,6 @@ public class TestCustomerFinder extends BaseTestCase { .withSort(SortMetric.TOTAL) .json(); - System.out.println(metricsJson); assertThat(metricsJson).contains("\"name\":\"txn.main\", \"type\":\"TXN\""); assertThat(metricsJson).contains("\"name\":\"Customer.findList\""); assertThat(metricsJson).contains("\"loc\":\"CustomerFinder.byNameStatus(CustomerFinder.java:44)\""); @@ -202,7 +201,6 @@ public class TestCustomerFinder extends BaseTestCase { .withSort(null) .json(); - System.out.println(metricsJson); assertThat(metricsJson).contains("\"name\":\"txn.main\""); assertThat(metricsJson).contains("\"name\":\"Customer.findList\""); assertThat(metricsJson).doesNotContain("\"loc\":"); @@ -210,6 +208,43 @@ public class TestCustomerFinder extends BaseTestCase { assertThat(metricsJson).doesNotContain("\"sql\":"); } + @Test + public void test_metricsAsJson_write() { + + ResetBasicData.reset(); + + runQueries(); + + StringBuilder buffer = new StringBuilder(); + server().getMetaInfoManager() + .collectMetricsAsJson() + .withHeader(false) + .write(buffer); + + String metricsJson = buffer.toString(); + assertThat(metricsJson).contains("\"name\":\"txn.main\""); + assertThat(metricsJson).contains("\"name\":\"Customer.findList\""); + } + + @Test + public void test_metricsAsJson_writeWithHeader() { + + ResetBasicData.reset(); + + runQueries(); + + StringBuilder buffer = new StringBuilder(); + server().getMetaInfoManager() + .collectMetricsAsJson() + .withHeader(true) + .write(buffer); + + String metricsJson = buffer.toString(); + assertThat(metricsJson).contains("{\"db\":\"h2\", \"metrics\":["); + assertThat(metricsJson).contains("\"name\":\"txn.main\""); + assertThat(metricsJson).contains("\"name\":\"Customer.findList\""); + } + private void runQueries() { resetAllMetrics();