diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/DmnVerificationService.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/DmnVerificationService.java index 5526d35b5898216c16974d6f821aa7b1436ee60a..bf502e10f3cc5a40f48c95fed16a486c1b95856d 100644 --- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/DmnVerificationService.java +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/DmnVerificationService.java @@ -243,12 +243,18 @@ public class DmnVerificationService { }); LOGGER.info("Verification finished. Id: " + verificationProcessId); + // get the reuslt set + VerifierResultSet resultSet = resultBuilder.build(); + // add execution times to metric statistics - executedVerifier.forEach( - v -> - dmnVerificationMetricsService.addExecutionTime( - v.getVerificationType(), v.getExecutionTime())); + resultSet + .getVerifierResults() + .forEach( + r -> + dmnVerificationMetricsService.addExecutionTime( + r.getVerificationType(), r.getExecutionTime(), r.getAmountOfEntries())); - return resultBuilder.build(); + // return the result set + return resultSet; } } diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/metrics/DmnVerificationMetricsService.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/metrics/DmnVerificationMetricsService.java index 8f4e215fc46405b91286b9a8ea94428caef92553..a5ee89168f8c02e67971155377d8ec19e62f41e9 100644 --- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/metrics/DmnVerificationMetricsService.java +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/metrics/DmnVerificationMetricsService.java @@ -33,7 +33,7 @@ public class DmnVerificationMetricsService { * @param type the {@link VerificationType} * @param timeInNs the time in ns */ - public void addExecutionTime(VerificationType type, long timeInNs) { - metricSet.addExecutionTime(type, timeInNs); + public void addExecutionTime(VerificationType type, long timeInNs, long numberOfElements) { + metricSet.addExecutionTime(type, timeInNs, numberOfElements); } } diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/metrics/Metric.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/metrics/Metric.java index bf99810b4746ac0377b3e8807e2add65f445c74f..37c53e8faf461007bed878f4c97a9fde970ccb29 100644 --- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/metrics/Metric.java +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/metrics/Metric.java @@ -15,6 +15,7 @@ public class Metric implements Serializable { public static final long NANO_SECONDS_PER_SECOND = 1_000_000L; VerificationType type; private List<Long> executionTimes; + private List<Long> numberOfElements; /** * Create a new metric instance @@ -22,6 +23,7 @@ public class Metric implements Serializable { public Metric(VerificationType type) { this.type = type; this.executionTimes = new ArrayList<>(); + this.numberOfElements = new ArrayList<>(); } /** @@ -29,8 +31,8 @@ public class Metric implements Serializable { * * @return the number of executions */ - @JsonbProperty("amountOfExecutions") - public int getAmountOfExecutions() { + @JsonbProperty("numberOfExecutions") + public int getNumberOfExecutions() { return executionTimes.size(); } @@ -81,13 +83,25 @@ public class Metric implements Serializable { return executionTimes.stream().mapToLong(Long::longValue).sum() / NANO_SECONDS_PER_SECOND; } + @JsonbProperty("averageNumberOfElements") + public double getAverageNumberOfElements() { + return numberOfElements.stream().mapToLong(Long::longValue).average().orElseGet(() -> 0); + } + + @JsonbProperty("totalNumberOfElements") + public long getTotalNumberOfElements() { + return numberOfElements.stream().mapToLong(Long::longValue).sum(); + } + /** * Add a new execution time. * * @param timeInMs the time in ns + * @param elements number of elements for the execution */ - void addExecutionTime(long timeInMs) { + void addExecution(long timeInMs, long elements) { executionTimes.add(timeInMs); + numberOfElements.add(elements); } @Override diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/metrics/MetricSet.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/metrics/MetricSet.java index 2d254624ee77a9d914c6d1490456554fc7956ef1..9186e4fddc07151069981a9b7bc9d556f0487897 100644 --- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/metrics/MetricSet.java +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/metrics/MetricSet.java @@ -29,12 +29,14 @@ public class MetricSet implements Serializable { * * @param type the {@link VerificationType} * @param timeInNs the time in ns + * @param numberOfElements the number of elements */ - public synchronized void addExecutionTime(VerificationType type, long timeInNs) { + public synchronized void addExecutionTime( + VerificationType type, long timeInNs, long numberOfElements) { Validate.notNull(type); Metric m = metrics.stream().filter(x -> x.type.equals(type)).findFirst().orElse(new Metric(type)); - m.addExecutionTime(timeInNs); + m.addExecution(timeInNs, numberOfElements); metrics.add(m); } } diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/VerifierResult.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/VerifierResult.java index f493bf9bca95bcd93a534718ca19679a641bd5d2..a4e8c9ae9c1d414b31b55472528a9ea33fbe1af9 100644 --- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/VerifierResult.java +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/result/VerifierResult.java @@ -69,9 +69,9 @@ public class VerifierResult extends AbstractResultObject { } /** - * Get the execution time of the verifier in ms. + * Get the execution time of the verifier in nano seconds. * - * @return the execution time in ms + * @return the execution time in nano seconds */ @JsonbProperty("executionTime") public Long getExecutionTime() { diff --git a/dmnverifierfrontend/src/main/resources/META-INF/resources/metrics.html b/dmnverifierfrontend/src/main/resources/META-INF/resources/metrics.html new file mode 100644 index 0000000000000000000000000000000000000000..197b5bd0c5f53de1cd44f418bcc815d28899760b --- /dev/null +++ b/dmnverifierfrontend/src/main/resources/META-INF/resources/metrics.html @@ -0,0 +1,143 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>Metrics</title> + <style> + body { + font-family: 'Open Sans', sans-serif; + } + + table { + width: 100%; + margin: 20px auto; + table-layout: auto; + } + + th { + text-align: left; + } + + td { + padding: 2px; + padding-right: 10px; + } + + tr > th { + border-bottom: solid 2px #a7a7a7; + } + + tr > td { + border-bottom: solid 1px #a7a7a7; + } + + #myChart { + max-width: 1024px; + } + </style> +</head> +<body> +<canvas id="myChart"></canvas> +<table></table> +<!-- load jquery --> +<script src="https://unpkg.com/jquery@3.4.1/dist/jquery.js" type="text/javascript"></script> +<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script> +<script type="text/javascript"> + + let rootUrl = 'http://' + window.location.hostname + ':8080/'; + let dmnApi = rootUrl + 'api/dmn/'; + $.ajax({ + timeout: 1000, + url: dmnApi + 'verification/metrics', + type: 'GET', + error: function (err) { + alert("No connection."); + }, + success: function (metrics) { + + // Add diagram + var lab = []; + metrics.verificationMetrics.forEach(function (el) { + lab.push(el.type.niceName); + }); + + var vals1 = []; + metrics.verificationMetrics.forEach(function (el) { + vals1.push(el.averageExecutionTimeInMs); + }); + var vals2 = []; + metrics.verificationMetrics.forEach(function (el) { + vals2.push(el.averageNumberOfElements); + }); + var vals3 = []; + metrics.verificationMetrics.forEach(function (el) { + vals3.push(el.totalExecutionTimeInMs); + }); + var vals4 = []; + metrics.verificationMetrics.forEach(function (el) { + vals4.push(el.totalNumberOfElements); + }); + var ctx = document.getElementById('myChart').getContext('2d'); + var chart = new Chart(ctx, { + // The type of chart we want to create + type: 'bar', + + // The data for our dataset + data: { + labels: lab, + datasets: [{ + label: 'Avg Execution Time', + backgroundColor: 'rgb(20, 220, 20)', + borderColor: 'rgb(0, 0, 0)', + data: vals1 + }, { + label: 'Avg Number Of Elements', + backgroundColor: 'rgb(220, 20, 20)', + borderColor: 'rgb(0, 0, 0)', + data: vals2 + }, { + label: 'Total Execution Time', + backgroundColor: 'rgb(14,146,220)', + borderColor: 'rgb(0, 0, 0)', + data: vals3 + }, { + label: 'Total Number Of Elements', + backgroundColor: 'rgb(220,148,21)', + borderColor: 'rgb(0, 0, 0)', + data: vals4 + }] + }, + + // Configuration options go here + options: {} + }); + // Add table + let $table = $('table'); + $table.append($(` + <tr> + <th>Name</th> + <th>Executions</th> + <th>AVG Time</th> + <th>Total</th> + <th>AVG Elements</th> + <th>Total</th> + </tr> + `)); + metrics.verificationMetrics.forEach(function (el) { + $table.append($(` + <tr> + <td>${el.type.niceName}</td> + <td>${el.numberOfExecutions}</td> + <td>${el.averageExecutionTimeInMs.toFixed(5)}</td> + <td>${el.totalExecutionTimeInMs}</td> + <td>${el.averageNumberOfElements.toFixed(5)}</td> + <td>${el.totalNumberOfElements}</td> + </tr> + `)); + + }); + } + }); +</script> +</body> +</html>