diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/api/Verification.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/api/Verification.java index afce52aacc773f7b3d0b42479b15af582f666eb2..41163d89cf72f2e000b9caf697a4c5885002bf8c 100644 --- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/api/Verification.java +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/api/Verification.java @@ -1,5 +1,6 @@ package de.unikoblenz.fgbks.api; +import static de.unikoblenz.fgbks.core.dmn.verification.metrics.DmnVerificationMetricsService.PUBLIC_TOKEN; import static javax.ws.rs.core.Response.Status.BAD_REQUEST; import de.unikoblenz.fgbks.core.dmn.verification.DmnVerificationService; @@ -10,6 +11,7 @@ import de.unikoblenz.fgbks.core.dmn.verification.verifier.types.VerificationType import java.util.List; import javax.inject.Inject; import javax.ws.rs.Consumes; +import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; @@ -33,14 +35,16 @@ public class Verification { /** * Method to generate all verifications for a dmn with all registered verifiers. * + * @param token the token for the metric statistics * @param payload the dmn as XML format as * @return a JSON String, which represents a {@link VerifierResultSet} */ @POST @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.TEXT_XML) - public Response verifyAll(String payload) { - return checkResult(dmnVerificationService.generate(payload)); + public Response verifyAll( + @DefaultValue(PUBLIC_TOKEN) @QueryParam("token") String token, String payload) { + return checkResult(dmnVerificationService.generate(payload, token)); } /** @@ -60,6 +64,7 @@ public class Verification { * VerificationType}. The types are listed in the query param "typeName". Multiple typeNames can * be requested. * + * @param token the token for the metric statistics * @param typeNames the "typeName"(s) of a {@link VerificationType} * @param payload the dmn as XML format as * @return a JSON String, which represents a {@link VerifierResultSet} @@ -68,8 +73,11 @@ public class Verification { @Path("/types") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.TEXT_XML) - public Response verifyTypes(@QueryParam("typeName") List<String> typeNames, String payload) { - return checkResult(dmnVerificationService.generateFromTypes(typeNames, payload)); + public Response verifyTypes( + @DefaultValue(PUBLIC_TOKEN) @QueryParam("token") String token, + @QueryParam("typeName") List<String> typeNames, + String payload) { + return checkResult(dmnVerificationService.generateFromTypes(typeNames, payload, token)); } /** @@ -88,6 +96,7 @@ public class Verification { * Method to generate all verifications for a dmn with the given name of a {@link * ClassificationType}. * + * @param token the token for the metric statistics * @param classificationName the name of a {@link ClassificationType} * @param payload the dmn as XML format as * @return a JSON String, which represents a {@link VerifierResultSet} @@ -97,21 +106,24 @@ public class Verification { @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.TEXT_XML) public Response verifyClassification( - @PathParam("classificationName") String classificationName, String payload) { + @DefaultValue(PUBLIC_TOKEN) @QueryParam("token") String token, + @PathParam("classificationName") String classificationName, + String payload) { return checkResult( - dmnVerificationService.generateFromClassification(classificationName, payload)); + dmnVerificationService.generateFromClassification(classificationName, payload, token)); } /** * Method to get all registered classification types. * + * @param token the token for the metric statistics * @return a list of {@link ClassificationType} as a JSON String. */ @GET @Path("/metrics") @Produces(MediaType.APPLICATION_JSON) - public Response metrics() { - return Response.accepted(dmnVerificationMetricsService.getMetrics()).build(); + public Response metrics(@DefaultValue(PUBLIC_TOKEN) @QueryParam("token") String token) { + return Response.accepted(dmnVerificationMetricsService.getMetrics(token)).build(); } private Response checkResult(VerifierResultSet resultSet) { 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 bf502e10f3cc5a40f48c95fed16a486c1b95856d..52f61c5dd4be927650fa0a8833ef30e243cfa5f0 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 @@ -74,10 +74,11 @@ public class DmnVerificationService { * current deployment. * * @param dmnXml the XML of the DMN as String + * @param token the token for metrics * @return a {@link VerifierResultSet} containing all verifications of known verifiers. */ - public VerifierResultSet generate(String dmnXml) { - return generateWithFilter(dmnXml, null, null); + public VerifierResultSet generate(String dmnXml, String token) { + return generateWithFilter(dmnXml, null, null, token); } /** @@ -86,22 +87,27 @@ public class DmnVerificationService { * * @param types the type as string list. Should be the name of a {@link VerificationType}. * @param dmnXml the XML of the DMN as String + * @param token the token for metrics * @return a {@link VerifierResultSet} containing all verifications of the selected verifier. */ - public VerifierResultSet generateFromTypes(List<String> types, String dmnXml) { - return generateWithFilter(dmnXml, types, null); + public VerifierResultSet generateFromTypes(List<String> types, String dmnXml, + String token) { + return generateWithFilter(dmnXml, types, null, token); } /** * Create a {@link VerifierResultSet} by executing the verifiers, which is registered in the * current deployment and has the name of the {@code type} parameter. * + * * @param classification the type as String. Should be the name of a {@link ClassificationType}. * @param dmnXml the XML of the DMN as String + * @param token the token for metrics * @return a {@link VerifierResultSet} containing all verifications of the selected verifier. */ - public VerifierResultSet generateFromClassification(String classification, String dmnXml) { - return generateWithFilter(dmnXml, null, classification); + public VerifierResultSet generateFromClassification( + String classification, String dmnXml, String token) { + return generateWithFilter(dmnXml, null, classification, token); } /** @@ -188,7 +194,7 @@ public class DmnVerificationService { } private VerifierResultSet generateWithFilter( - String dmnXml, List<String> typeNames, String classificationName) { + String dmnXml, List<String> typeNames, String classificationName, String token) { long verificationProcessId = UniqueIdGenerator.getNextId(); LOGGER.info("Start verification process. Id: " + verificationProcessId); LOGGER.info("Parsing dmn. Id: " + verificationProcessId); @@ -251,7 +257,7 @@ public class DmnVerificationService { .getVerifierResults() .forEach( r -> - dmnVerificationMetricsService.addExecutionTime( + dmnVerificationMetricsService.addExecutionTime(token, r.getVerificationType(), r.getExecutionTime(), r.getAmountOfEntries())); // return the result set 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 a5ee89168f8c02e67971155377d8ec19e62f41e9..6eef97ef2a18c690df3af41a8e286084a3a24d48 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 @@ -1,39 +1,53 @@ package de.unikoblenz.fgbks.core.dmn.verification.metrics; import de.unikoblenz.fgbks.core.dmn.verification.verifier.types.VerificationType; +import java.util.HashMap; +import java.util.Map; import javax.enterprise.context.ApplicationScoped; /** * Service class for adding statistics of execution time of {@link VerificationType}s with the * function {@link DmnVerificationMetricsService#addExecutionTime}. The statistic metrics can be - * accessed with {@link DmnVerificationMetricsService#getMetrics()} to get a {@link MetricSet} + * accessed with {@link DmnVerificationMetricsService#getMetrics(String)} to get a {@link MetricSet} * object. */ @ApplicationScoped public class DmnVerificationMetricsService { - MetricSet metricSet; + public static final String PUBLIC_TOKEN = "all"; + private MetricSet publicMetrics; + private Map<String, MetricSet> metricSets; protected DmnVerificationMetricsService() { - metricSet = new MetricSet(); + metricSets = new HashMap<>(); + publicMetrics = new MetricSet(); + metricSets.put(PUBLIC_TOKEN, publicMetrics); } /** * Get the current {@link Metric}s in a {@link MetricSet}. * + * @param token the token for metrics * @return the {@link MetricSet} */ - public MetricSet getMetrics() { - return metricSet; + public MetricSet getMetrics(String token) { + return metricSets.getOrDefault(token, new MetricSet()); } /** * Add a execution time tho the given {@link VerificationType}. * + * @param token the token for different users * @param type the {@link VerificationType} * @param timeInNs the time in ns */ - public void addExecutionTime(VerificationType type, long timeInNs, long numberOfElements) { - metricSet.addExecutionTime(type, timeInNs, numberOfElements); + public void addExecutionTime( + String token, VerificationType type, long timeInNs, long numberOfElements) { + if (!token.equals(PUBLIC_TOKEN)) { + MetricSet metricSet = metricSets.getOrDefault(token, new MetricSet()); + metricSets.put(token, metricSet); + metricSet.addExecutionTime(type, timeInNs, numberOfElements); + } + publicMetrics.addExecutionTime(type, timeInNs, numberOfElements); } } diff --git a/dmnverifierapi/src/main/resources/META-INF/resources/index.html b/dmnverifierapi/src/main/resources/META-INF/resources/index.html index 639c062c74d627b8d0537b606641baeb18e55b55..61df3e44e946e39522a9d261ed63a72e0ff74290 100644 --- a/dmnverifierapi/src/main/resources/META-INF/resources/index.html +++ b/dmnverifierapi/src/main/resources/META-INF/resources/index.html @@ -123,9 +123,10 @@ <h3>Verifications</h3> <h4>Get all verifications from all verifiers with the given dmn table</h4> + The <i>token</i> parameter is optional for some metric statistics. <ul> <li>POST</li> - <li><code>/api/dmn/verification/</code></li> + <li><code>/api/dmn/verification?token={token}</code></li> <li>Consumes: text/xml - the dmn table as xml string</li> <li>Produces: application/json</li> </ul> @@ -141,9 +142,10 @@ </ul> <h4>Get all verifications for the given verification classification</h4> + The <i>token</i> parameter is optional for some metric statistics. <ul> <li>POST</li> - <li><code>/api/dmn/verification/classifications/{classificationName}</code></li> + <li><code>/api/dmn/verification/classifications/{classificationName}?token={token}</code></li> <li>Consumes: text/xml - the dmn table as xml string</li> <li>Produces: application/json</li> </ul> @@ -161,9 +163,10 @@ </ul> <h4>Get all verifications for the given verification types a and b</h4> + The <i>token</i> parameter is optional for some metric statistics. <ul> <li>POST</li> - <li><code>/api/dmn/verification/types?typeName={a}&typeName={b}</code></li> + <li><code>/api/dmn/verification/types?typeName={a}&typeName={b}&token={token}</code></li> <li>Consumes: text/xml - the dmn table as xml string</li> <li>Produces: application/json</li> </ul> @@ -171,11 +174,12 @@ <h3>Metrics</h3> <h4>Get some statistics about execution times</h4> + The <i>token</i> parameter is optional for some metric statistics. The default value is 'all'. <ul> <li>GET</li> <li> <code><a href="/api/dmn/verification/metrics" - target="_blank">/api/dmn/verification/metrics</a></code> + target="_blank">/api/dmn/verification/metrics?token={token}</a></code> </li> <li>Produces: application/json</li> </ul> diff --git a/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnVerifier.js b/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnVerifier.js index ad4f1c00e50cdea2d10f69edc318f6ceadb3ac37..050039bca4e0c4428f8a21c92f705ed5fafaa997 100644 --- a/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnVerifier.js +++ b/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnVerifier.js @@ -136,18 +136,19 @@ function getVerifications() { console.log('Requesting dmn verifications..'); } let apiPath = dmnApi + 'verification'; + // check, if a verifier is preselected - if ($verifierTypes[0].selectedOptions[0] !== undefined) { + if ($verifierTypes[0].selectedOptions[0] === undefined) { + apiPath += '?'; + } else { apiPath += "/types"; for (let i = 0; i < $verifierTypes[0].selectedOptions.length; i++) { - if (i === 0) { - apiPath += '?'; - } else { - apiPath += '&'; - } - apiPath += 'typeName=' + $verifierTypes[0].selectedOptions[i].value; + apiPath += '&typeName=' + $verifierTypes[0].selectedOptions[i].value; } + apiPath += '&'; } + apiPath += 'token=' + getMetricToken(); + $.ajax({ timeout: 0, // ?? url: apiPath, @@ -358,3 +359,17 @@ function findVerifierByName(verifierName) { } return undefined; } + +function getMetricToken() { + var token = localStorage.getItem('metricToken'); + if (token === null || token === 'undefined') { + var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + var charactersLength = characters.length; + token = ''; + for (var i = 0; i < 20; i++) { + token += characters.charAt(Math.floor(Math.random() * charactersLength)); + } + localStorage.setItem('metricToken', token); + } + return token; +} diff --git a/dmnverifierfrontend/src/main/resources/META-INF/resources/metrics.html b/dmnverifierfrontend/src/main/resources/META-INF/resources/metrics.html index 197b5bd0c5f53de1cd44f418bcc815d28899760b..9d3641894d8ac42772027592813bd781c5b52ba3 100644 --- a/dmnverifierfrontend/src/main/resources/META-INF/resources/metrics.html +++ b/dmnverifierfrontend/src/main/resources/META-INF/resources/metrics.html @@ -2,7 +2,7 @@ <html lang="en"> <head> <meta charset="UTF-8"> - <title>Metrics</title> + <title>Metrics - Verification for Decision Model and Notation</title> <style> body { font-family: 'Open Sans', sans-serif; @@ -31,89 +31,128 @@ border-bottom: solid 1px #a7a7a7; } - #myChart { - max-width: 1024px; + #metricContainer { + max-width: 1300px; + padding-left: 0; + padding-right: 0; + margin-left: auto; + margin-right: auto; + display: block; + } + + canvas { + border: solid 2px #a7a7a7; } </style> </head> <body> -<canvas id="myChart"></canvas> -<table></table> +<div id="metricContainer"> + <h1>Metrics - Verification for Decision Model and Notation</h1> + <p>Token: <span id="token"></span></p> + <button id="loadData" onclick="loadData()">Reload statistics</button> + <button id="genToken" onclick="genToken()">Generate new token</button> + <canvas id="myChart"></canvas> + <table></table> +</div> <!-- 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) { + $(document).ready(function () { + loadData(); + }); + + function genToken() { + var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + var charactersLength = characters.length; + var token = ''; + for (var i = 0; i < 20; i++) { + token += characters.charAt(Math.floor(Math.random() * charactersLength)); + } + localStorage.setItem('metricToken', token); + $('#token').text(token); + loadData(); + return token; + } - // Add diagram - var lab = []; - metrics.verificationMetrics.forEach(function (el) { - lab.push(el.type.niceName); - }); + function loadData() { + var token = localStorage.getItem('metricToken'); + if (token === null || token === 'undefined') { + token = genToken(); + } + $('#token').text(token); + let rootUrl = 'http://' + window.location.hostname + ':8080/'; + let dmnApi = rootUrl + 'api/dmn/'; + $.ajax({ + timeout: 1000, + url: dmnApi + 'verification/metrics?token=' + token, + type: 'GET', + error: function (err) { + alert("No connection."); + }, + success: function (metrics) { - 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', + // Add diagram + var lab = []; + metrics.verificationMetrics.forEach(function (el) { + lab.push(el.type.niceName); + }); - // 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 - }] - }, + 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', - // Configuration options go here - options: {} - }); - // Add table - let $table = $('table'); - $table.append($(` + // 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.empty(); + $table.append($(` <tr> <th>Name</th> <th>Executions</th> @@ -123,8 +162,8 @@ <th>Total</th> </tr> `)); - metrics.verificationMetrics.forEach(function (el) { - $table.append($(` + metrics.verificationMetrics.forEach(function (el) { + $table.append($(` <tr> <td>${el.type.niceName}</td> <td>${el.numberOfExecutions}</td> @@ -135,9 +174,10 @@ </tr> `)); - }); - } - }); + }); + } + }); + } </script> </body> </html>