From e59bd5ca130b3b273cca5138614a99b074a8a6ee Mon Sep 17 00:00:00 2001 From: rh-appservices-perf Date: Mon, 2 Sep 2024 10:36:54 +0200 Subject: [PATCH] Apply formatting --- .../tools/horreum/api/SortDirection.java | 4 +- .../hyperfoil/tools/horreum/api/Version.java | 24 +- .../tools/horreum/api/alerting/Change.java | 20 +- .../horreum/api/alerting/ChangeDetection.java | 39 +- .../tools/horreum/api/alerting/DataPoint.java | 8 +- .../horreum/api/alerting/DatasetLog.java | 23 +- .../horreum/api/alerting/MissingDataRule.java | 23 +- .../api/alerting/MissingDataRuleResult.java | 13 +- .../api/alerting/NotificationSettings.java | 11 +- .../horreum/api/alerting/RunExpectation.java | 5 +- .../api/alerting/TransformationLog.java | 10 +- .../tools/horreum/api/alerting/Variable.java | 18 +- .../tools/horreum/api/alerting/Watch.java | 16 +- .../tools/horreum/api/changes/Dashboard.java | 113 +- .../tools/horreum/api/changes/Target.java | 26 +- .../tools/horreum/api/changes/TimeRange.java | 4 +- .../tools/horreum/api/data/Access.java | 87 +- .../tools/horreum/api/data/Action.java | 33 +- .../api/data/ActionConfig/ActionType.java | 7 +- .../GithubIssueCreateActionConfig.java | 3 +- .../tools/horreum/api/data/ActionLog.java | 12 +- .../tools/horreum/api/data/AllowedSite.java | 3 +- .../tools/horreum/api/data/Banner.java | 7 +- .../horreum/api/data/ConditionConfig.java | 372 +-- .../tools/horreum/api/data/Dataset.java | 41 +- .../api/data/ExperimentComparison.java | 11 +- .../horreum/api/data/ExperimentProfile.java | 25 +- .../horreum/api/data/ExportedLabelValues.java | 67 +- .../tools/horreum/api/data/Extractor.java | 14 +- .../horreum/api/data/FingerprintValue.java | 18 +- .../tools/horreum/api/data/Fingerprints.java | 14 +- .../api/data/IndexedLabelValueMap.java | 28 +- .../tools/horreum/api/data/Label.java | 37 +- .../tools/horreum/api/data/LabelValueMap.java | 17 +- .../tools/horreum/api/data/PersistentLog.java | 85 +- .../horreum/api/data/ProtectedTimeType.java | 20 +- .../tools/horreum/api/data/ProtectedType.java | 10 +- .../tools/horreum/api/data/QueryResult.java | 2 +- .../hyperfoil/tools/horreum/api/data/Run.java | 16 +- .../tools/horreum/api/data/Schema.java | 30 +- .../tools/horreum/api/data/SchemaExport.java | 7 +- .../tools/horreum/api/data/Test.java | 49 +- .../tools/horreum/api/data/TestExport.java | 38 +- .../tools/horreum/api/data/TestToken.java | 33 +- .../tools/horreum/api/data/Transformer.java | 29 +- .../horreum/api/data/ValidationError.java | 12 +- .../tools/horreum/api/data/View.java | 11 +- .../tools/horreum/api/data/ViewComponent.java | 9 +- .../ChangeDetectionModelType.java | 28 +- .../EDivisiveDetectionConfig.java | 5 +- .../changeDetection/FixThresholdConfig.java | 9 +- .../FixedThresholdDetectionConfig.java | 9 +- .../RelativeDifferenceDetectionConfig.java | 19 +- .../datastore/BaseChangeDetectionConfig.java | 3 +- .../data/datastore/BaseDatastoreConfig.java | 3 +- .../horreum/api/data/datastore/Datastore.java | 32 +- .../api/data/datastore/DatastoreType.java | 18 +- .../ElasticsearchDatastoreConfig.java | 28 +- .../datastore/PostgresDatastoreConfig.java | 4 +- .../api/internal/services/ActionService.java | 67 +- .../internal/services/AlertingService.java | 343 +-- .../api/internal/services/BannerService.java | 13 +- .../api/internal/services/ChangesService.java | 175 +- .../api/internal/services/LogService.java | 113 +- .../services/NotificationService.java | 41 +- .../api/internal/services/ReportService.java | 155 +- .../api/internal/services/SqlService.java | 63 +- .../services/SubscriptionService.java | 46 +- .../api/internal/services/UIService.java | 8 +- .../api/internal/services/UserService.java | 238 +- .../horreum/api/report/ReportComment.java | 7 +- .../horreum/api/report/ReportComponent.java | 12 +- .../tools/horreum/api/report/ReportLog.java | 8 +- .../tools/horreum/api/report/TableReport.java | 16 +- .../horreum/api/report/TableReportConfig.java | 28 +- .../horreum/api/services/ConfigService.java | 158 +- .../horreum/api/services/DatasetService.java | 264 +- .../api/services/ExperimentService.java | 345 +-- .../horreum/api/services/RunService.java | 415 ++- .../horreum/api/services/SchemaService.java | 850 +++--- .../horreum/api/services/TestService.java | 717 +++-- .../ReactiveUrlConfigSourceFactory.java | 28 +- .../tools/horreum/action/ActionPlugin.java | 8 +- .../tools/horreum/action/ActionUtil.java | 37 +- .../tools/horreum/action/BodyFormatter.java | 5 +- .../horreum/action/ChangeToMarkdown.java | 68 +- .../action/ExperimentResultToMarkdown.java | 50 +- .../tools/horreum/action/GitHubClient.java | 30 +- .../action/GitHubIssueCommentAction.java | 117 +- .../action/GitHubIssueCreateAction.java | 88 +- .../horreum/action/GitHubPluginBase.java | 94 +- .../tools/horreum/action/HttpAction.java | 152 +- .../action/SlackChannelMessageAction.java | 132 +- .../tools/horreum/action/SlackClient.java | 30 +- .../tools/horreum/action/SlackPluginBase.java | 108 +- .../horreum/action/TestToSlackMarkdown.java | 57 +- .../horreum/bus/BlockingTaskDispatcher.java | 108 +- .../ChangeDetectionException.java | 2 - .../changedetection/ChangeDetectionModel.java | 12 +- .../ChangeDetectionModelResolver.java | 20 +- .../changedetection/FixedThresholdModel.java | 125 +- .../changedetection/HunterEDivisiveModel.java | 115 +- ...elativeDifferenceChangeDetectionModel.java | 46 +- .../horreum/converter/JavaTimeCustomizer.java | 13 +- .../converter/JsonToEventConverter.java | 11 +- .../horreum/datastore/BackendResolver.java | 12 +- .../tools/horreum/datastore/Datastore.java | 17 +- .../datastore/ElasticsearchDatastore.java | 106 +- .../horreum/datastore/PostgresDatastore.java | 21 +- .../tools/horreum/entity/ActionLogDAO.java | 47 +- .../tools/horreum/entity/BannerDAO.java | 36 +- .../entity/CustomSequenceGenerator.java | 64 +- .../entity/ExperimentComparisonDAO.java | 45 +- .../horreum/entity/ExperimentProfileDAO.java | 68 +- .../tools/horreum/entity/FingerprintDAO.java | 45 +- .../horreum/entity/PersistentLogDAO.java | 70 +- .../tools/horreum/entity/SeqIdGenerator.java | 86 +- .../horreum/entity/ValidationErrorDAO.java | 85 +- .../horreum/entity/alerting/ChangeDAO.java | 96 +- .../entity/alerting/ChangeDetectionDAO.java | 76 +- .../horreum/entity/alerting/DataPointDAO.java | 72 +- .../entity/alerting/DatasetLogDAO.java | 78 +- .../entity/alerting/MissingDataRuleDAO.java | 107 +- .../alerting/MissingDataRuleResultDAO.java | 143 +- .../alerting/NotificationSettingsDAO.java | 64 +- .../entity/alerting/RunExpectationDAO.java | 35 +- .../entity/alerting/TransformationLogDAO.java | 70 +- .../horreum/entity/alerting/VariableDAO.java | 128 +- .../horreum/entity/alerting/WatchDAO.java | 85 +- .../entity/backend/DatastoreConfigDAO.java | 26 +- .../ChangeDetectionLogDAO.java | 74 +- .../tools/horreum/entity/data/ActionDAO.java | 117 +- .../horreum/entity/data/AllowedSiteDAO.java | 20 +- .../tools/horreum/entity/data/DatasetDAO.java | 300 +- .../horreum/entity/data/ExtractorDAO.java | 44 +- .../tools/horreum/entity/data/LabelDAO.java | 80 +- .../horreum/entity/data/LabelValueDAO.java | 19 +- .../horreum/entity/data/OwnedEntityBase.java | 17 +- .../tools/horreum/entity/data/RunDAO.java | 125 +- .../tools/horreum/entity/data/SchemaDAO.java | 98 +- .../tools/horreum/entity/data/TestDAO.java | 167 +- .../horreum/entity/data/TestTokenDAO.java | 124 +- .../horreum/entity/data/TransformerDAO.java | 131 +- .../horreum/entity/data/ViewComponentDAO.java | 120 +- .../tools/horreum/entity/data/ViewDAO.java | 73 +- .../entity/report/ReportCommentDAO.java | 38 +- .../entity/report/ReportComponentDAO.java | 62 +- .../horreum/entity/report/ReportLogDAO.java | 52 +- .../entity/report/TableReportConfigDAO.java | 106 +- .../horreum/entity/report/TableReportDAO.java | 146 +- .../tools/horreum/entity/user/Team.java | 28 +- .../horreum/entity/user/TeamMembership.java | 14 +- .../tools/horreum/entity/user/TeamRole.java | 5 +- .../tools/horreum/entity/user/UserInfo.java | 55 +- .../tools/horreum/entity/user/UserRole.java | 12 +- .../tools/horreum/events/DatasetChanges.java | 79 +- .../experiment/ExperimentConditionModel.java | 4 +- .../RelativeDifferenceExperimentModel.java | 66 +- .../tools/horreum/hibernate/IntArrayType.java | 22 +- .../horreum/hibernate/JsonBinaryType.java | 25 +- .../tools/horreum/hibernate/JsonbSetType.java | 37 +- .../tools/horreum/mapper/ActionLogMapper.java | 2 +- .../tools/horreum/mapper/ActionMapper.java | 2 +- .../horreum/mapper/AllowedSiteMapper.java | 2 +- .../tools/horreum/mapper/BannerMapper.java | 4 +- .../tools/horreum/mapper/ChangeMapper.java | 2 +- .../tools/horreum/mapper/DataPointMapper.java | 6 +- .../horreum/mapper/DatasetLogMapper.java | 4 +- .../tools/horreum/mapper/DatasetMapper.java | 16 +- .../mapper/ExperimentProfileMapper.java | 18 +- .../tools/horreum/mapper/LabelMapper.java | 12 +- .../horreum/mapper/MissingDataRuleMapper.java | 2 +- .../mapper/NotificationSettingsMapper.java | 6 +- .../horreum/mapper/ReportCommentMapper.java | 2 +- .../horreum/mapper/ReportComponentMapper.java | 2 +- .../tools/horreum/mapper/ReportLogMapper.java | 2 +- .../horreum/mapper/RunExpectationMapper.java | 2 +- .../tools/horreum/mapper/RunMapper.java | 49 +- .../tools/horreum/mapper/SchemaMapper.java | 2 +- .../horreum/mapper/TableReportMapper.java | 32 +- .../tools/horreum/mapper/TestMapper.java | 20 +- .../tools/horreum/mapper/TestTokenMapper.java | 2 +- .../mapper/TransformationLogMapper.java | 2 +- .../horreum/mapper/TransformerMapper.java | 12 +- .../horreum/mapper/ValidationErrorMapper.java | 5 +- .../tools/horreum/mapper/VariableMapper.java | 26 +- .../tools/horreum/mapper/ViewMapper.java | 12 +- .../tools/horreum/mapper/WatchMapper.java | 2 +- .../horreum/notification/EmailPlugin.java | 291 +- .../horreum/notification/Notification.java | 28 +- .../notification/NotificationPlugin.java | 7 +- .../tools/horreum/server/CloseMe.java | 4 +- .../ConstraintViolationExceptionMapper.java | 34 +- .../horreum/server/EncryptionManager.java | 69 +- .../server/HorreumAuthorizationFilter.java | 110 +- .../server/JDBCConnectionInterceptor.java | 34 +- .../tools/horreum/server/RoleManager.java | 106 +- .../tools/horreum/server/RolesAugmentor.java | 18 +- .../horreum/server/RolesInterceptor.java | 127 +- .../tools/horreum/server/RouteFilter.java | 30 +- .../horreum/server/SecurityBootstrap.java | 80 +- .../horreum/server/TokenInterceptor.java | 87 +- .../tools/horreum/server/WithRoles.java | 25 +- .../tools/horreum/server/WithToken.java | 5 +- .../tools/horreum/svc/ActionServiceImpl.java | 608 ++-- .../horreum/svc/AlertingServiceImpl.java | 2454 +++++++-------- .../tools/horreum/svc/BannerServiceImpl.java | 102 +- .../horreum/svc/CachedSecurityIdentity.java | 104 +- .../tools/horreum/svc/ChangesServiceImpl.java | 343 ++- .../tools/horreum/svc/ConfigServiceImpl.java | 54 +- .../tools/horreum/svc/CountDownFuture.java | 30 +- .../tools/horreum/svc/DatasetServiceImpl.java | 853 +++--- .../tools/horreum/svc/EventAggregator.java | 74 +- .../horreum/svc/ExperimentServiceImpl.java | 540 ++-- .../tools/horreum/svc/LogServiceImpl.java | 313 +- .../tools/horreum/svc/MissingValuesEvent.java | 20 +- .../horreum/svc/NotificationServiceImpl.java | 260 +- .../tools/horreum/svc/ProxyJackson.java | 11 +- .../tools/horreum/svc/ProxyJacksonArray.java | 27 +- .../tools/horreum/svc/ProxyJacksonObject.java | 29 +- .../tools/horreum/svc/ReportServiceImpl.java | 1329 ++++---- .../io/hyperfoil/tools/horreum/svc/Roles.java | 171 +- .../tools/horreum/svc/RunServiceImpl.java | 2705 +++++++++-------- .../tools/horreum/svc/SchemaServiceImpl.java | 1792 +++++------ .../tools/horreum/svc/ServiceException.java | 32 +- .../tools/horreum/svc/ServiceMediator.java | 59 +- .../tools/horreum/svc/SqlServiceImpl.java | 272 +- .../horreum/svc/SubscriptionServiceImpl.java | 403 ++- .../tools/horreum/svc/TestServiceImpl.java | 1870 ++++++------ .../tools/horreum/svc/TimeService.java | 6 +- .../hyperfoil/tools/horreum/svc/Tokens.java | 20 +- .../tools/horreum/svc/UIServiceImpl.java | 27 +- .../tools/horreum/svc/UserServiceImpl.java | 118 +- .../io/hyperfoil/tools/horreum/svc/Util.java | 1640 +++++----- .../horreum/svc/user/DatabaseUserBackend.java | 118 +- .../horreum/svc/user/KeycloakUserBackend.java | 146 +- .../tools/horreum/svc/user/UserBackEnd.java | 6 +- .../changedetection/EdivisiveTests.java | 54 +- .../tools/horreum/svc/ActionServiceTest.java | 267 +- .../horreum/svc/AlertingServiceTest.java | 1550 +++++----- .../tools/horreum/svc/BannerServiceTest.java | 14 +- .../horreum/svc/BaseServiceNoRestTest.java | 155 +- .../tools/horreum/svc/BaseServiceTest.java | 2071 ++++++------- .../tools/horreum/svc/BasicAuthTest.java | 23 +- .../tools/horreum/svc/ConfigServiceTest.java | 32 +- .../tools/horreum/svc/DatasetServiceTest.java | 873 +++--- .../tools/horreum/svc/DatasourceTest.java | 61 +- .../horreum/svc/KeycloakUserServiceTest.java | 12 +- .../tools/horreum/svc/LogServiceTest.java | 77 +- .../horreum/svc/NotificationPluginTest.java | 78 +- .../tools/horreum/svc/ReportServiceTest.java | 282 +- .../tools/horreum/svc/RunServiceTest.java | 2390 +++++++-------- .../horreum/svc/SchemaServiceNoRestTest.java | 1431 ++++----- .../tools/horreum/svc/SchemaServiceTest.java | 1508 ++++----- .../tools/horreum/svc/SlackDummyService.java | 8 +- .../horreum/svc/TestServiceNoRestTest.java | 1705 ++++++----- .../tools/horreum/svc/TestServiceTest.java | 1587 +++++----- .../tools/horreum/svc/TokenAuthTest.java | 38 +- .../horreum/svc/UserServiceAbstractTest.java | 173 +- .../hyperfoil/tools/horreum/svc/UtilTest.java | 186 +- .../test/DatabaseRolesTestProfile.java | 3 +- .../test/ElasticsearchTestProfile.java | 3 +- ...mKeycloakTestResourceLifecycleManager.java | 39 +- .../horreum/test/HorreumTestProfile.java | 49 +- .../horreum/test/KeycloakTestProfile.java | 21 +- .../tools/horreum/test/PostgresResource.java | 101 +- .../tools/horreum/test/TestUtil.java | 94 +- .../tools/CustomResteasyJackson2Provider.java | 14 +- .../io/hyperfoil/tools/HorreumClient.java | 102 +- .../hyperfoil/tools/RunServiceExtension.java | 284 +- .../auth/KeycloakClientRequestFilter.java | 134 +- .../tools/horreum/api/client/RunService.java | 260 +- .../tools/horreum/it/HorreumClientIT.java | 89 +- .../tools/horreum/it/ItResource.java | 21 +- .../it/profile/InContainerProfile.java | 12 +- .../HorreumDevServicesConfigBuildItem.java | 6 +- .../HorreumDevServicesProcessor.java | 77 +- .../deployment/config/DevServicesConfig.java | 2 +- .../HorreumDevServicesKeycloakConfig.java | 10 +- .../HorreumDevServicesPostgresConfig.java | 6 +- .../infra/common/HorreumResources.java | 77 +- .../common/ResourceLifecycleManager.java | 7 +- .../horreum/infra/common/SelfSignedCert.java | 46 +- .../resources/HorreumPostgreSQLContainer.java | 23 +- .../common/resources/KeycloakResource.java | 63 +- .../common/resources/PostgresResource.java | 81 +- .../infra/common/utils/RoleBuilder.java | 7 +- .../infra/common/utils/UserBuilder.java | 38 +- 288 files changed, 22916 insertions(+), 22309 deletions(-) diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/SortDirection.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/SortDirection.java index 08de0040e..96ee9b910 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/SortDirection.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/SortDirection.java @@ -1,6 +1,6 @@ package io.hyperfoil.tools.horreum.api; public enum SortDirection { - Ascending, - Descending + Ascending, + Descending } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/Version.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/Version.java index b65cd9c4c..2522e7ad2 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/Version.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/Version.java @@ -1,19 +1,19 @@ package io.hyperfoil.tools.horreum.api; -import io.quarkus.logging.Log; - import java.io.IOException; import java.util.Properties; +import io.quarkus.logging.Log; + public class Version { - public static final String getVersion(){ - final Properties properties = new Properties(); - try { - properties.load(Version.class.getClassLoader().getResourceAsStream("build.properties")); - return properties.getProperty("horreum.version"); - } catch (IOException e) { - Log.error("Failed to load version.properties",e); - } - return null; - } + public static final String getVersion() { + final Properties properties = new Properties(); + try { + properties.load(Version.class.getClassLoader().getResourceAsStream("build.properties")); + return properties.getProperty("horreum.version"); + } catch (IOException e) { + Log.error("Failed to load version.properties", e); + } + return null; + } } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/Change.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/Change.java index 19f85de84..a286bc714 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/Change.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/Change.java @@ -1,25 +1,27 @@ package io.hyperfoil.tools.horreum.api.alerting; +import java.time.Instant; + +import jakarta.validation.constraints.NotNull; + import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; -import io.hyperfoil.tools.horreum.api.data.Dataset; -import jakarta.validation.constraints.NotNull; -import java.time.Instant; +import io.hyperfoil.tools.horreum.api.data.Dataset; public class Change { - @JsonProperty( required = true ) + @JsonProperty(required = true) public int id; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public Variable variable; @JsonIgnore public Dataset dataset; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public Instant timestamp; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public boolean confirmed; public String description; @@ -32,7 +34,9 @@ public Dataset.Info getDatasetId() { } public String toString() { - return "Change{id=" + this.id + ", variable=" + this.variable.id + ", dataset=" + this.dataset.id + " (" + this.dataset.runId + "/" + this.dataset.ordinal + "), timestamp=" + this.timestamp + ", confirmed=" + this.confirmed + ", description='" + this.description + '\'' + '}'; + return "Change{id=" + this.id + ", variable=" + this.variable.id + ", dataset=" + this.dataset.id + " (" + + this.dataset.runId + "/" + this.dataset.ordinal + "), timestamp=" + this.timestamp + ", confirmed=" + + this.confirmed + ", description='" + this.description + '\'' + '}'; } public static class Event { diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/ChangeDetection.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/ChangeDetection.java index 6227364d2..be360f6fa 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/ChangeDetection.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/ChangeDetection.java @@ -1,37 +1,36 @@ package io.hyperfoil.tools.horreum.api.alerting; +import jakarta.validation.constraints.NotNull; + +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.media.DiscriminatorMapping; +import org.eclipse.microprofile.openapi.annotations.media.Schema; + import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.node.ObjectNode; + import io.hyperfoil.tools.horreum.api.data.changeDetection.ChangeDetectionModelType; import io.hyperfoil.tools.horreum.api.data.changeDetection.EDivisiveDetectionConfig; import io.hyperfoil.tools.horreum.api.data.changeDetection.FixedThresholdDetectionConfig; import io.hyperfoil.tools.horreum.api.data.changeDetection.RelativeDifferenceDetectionConfig; -import jakarta.validation.constraints.NotNull; -import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; -import org.eclipse.microprofile.openapi.annotations.media.DiscriminatorMapping; -import org.eclipse.microprofile.openapi.annotations.media.Schema; public class ChangeDetection { - - @JsonProperty( required = true ) + @JsonProperty(required = true) public Integer id; - @JsonProperty( required = true ) + @JsonProperty(required = true) public String model; @NotNull - @JsonProperty( required = true ) - @Schema(type = SchemaType.OBJECT, discriminatorProperty = "model", - discriminatorMapping = { - @DiscriminatorMapping(schema = RelativeDifferenceDetectionConfig.class, value = ChangeDetectionModelType.names.RELATIVE_DIFFERENCE), - @DiscriminatorMapping(schema = FixedThresholdDetectionConfig.class, value = ChangeDetectionModelType.names.FIXED_THRESHOLD), - @DiscriminatorMapping(schema = EDivisiveDetectionConfig.class, value = ChangeDetectionModelType.names.EDIVISIVE) - }, - oneOf = { - RelativeDifferenceDetectionConfig.class, - FixedThresholdDetectionConfig.class, - EDivisiveDetectionConfig.class - } - ) + @JsonProperty(required = true) + @Schema(type = SchemaType.OBJECT, discriminatorProperty = "model", discriminatorMapping = { + @DiscriminatorMapping(schema = RelativeDifferenceDetectionConfig.class, value = ChangeDetectionModelType.names.RELATIVE_DIFFERENCE), + @DiscriminatorMapping(schema = FixedThresholdDetectionConfig.class, value = ChangeDetectionModelType.names.FIXED_THRESHOLD), + @DiscriminatorMapping(schema = EDivisiveDetectionConfig.class, value = ChangeDetectionModelType.names.EDIVISIVE) + }, oneOf = { + RelativeDifferenceDetectionConfig.class, + FixedThresholdDetectionConfig.class, + EDivisiveDetectionConfig.class + }) public ObjectNode config; public ChangeDetection() { diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/DataPoint.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/DataPoint.java index b297bce16..6088f4fd9 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/DataPoint.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/DataPoint.java @@ -1,10 +1,12 @@ package io.hyperfoil.tools.horreum.api.alerting; -import com.fasterxml.jackson.annotation.JsonProperty; -import io.hyperfoil.tools.horreum.api.data.Dataset; +import java.time.Instant; + import jakarta.validation.constraints.NotNull; -import java.time.Instant; +import com.fasterxml.jackson.annotation.JsonProperty; + +import io.hyperfoil.tools.horreum.api.data.Dataset; public class DataPoint { public Integer id; diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/DatasetLog.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/DatasetLog.java index 610ad4134..27bac87bd 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/DatasetLog.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/DatasetLog.java @@ -1,35 +1,38 @@ package io.hyperfoil.tools.horreum.api.alerting; -import com.fasterxml.jackson.annotation.JsonProperty; -import io.hyperfoil.tools.horreum.api.data.PersistentLog; import jakarta.validation.constraints.NotNull; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -@Schema( type = SchemaType.OBJECT, description = "Dataset Log", name = "DatasetLog", allOf = PersistentLog.class) +import com.fasterxml.jackson.annotation.JsonProperty; + +import io.hyperfoil.tools.horreum.api.data.PersistentLog; + +@Schema(type = SchemaType.OBJECT, description = "Dataset Log", name = "DatasetLog", allOf = PersistentLog.class) public class DatasetLog extends PersistentLog { @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public String source; - @JsonProperty( value = "testId", required = true ) + @JsonProperty(value = "testId", required = true) private Integer testId; - @JsonProperty( value = "runId", required = true ) + @JsonProperty(value = "runId", required = true) private Integer runId; - @JsonProperty( value = "datasetId", required = true ) + @JsonProperty(value = "datasetId", required = true) private Integer datasetId; - @JsonProperty( value = "datasetOrdinal", required = true ) + @JsonProperty(value = "datasetOrdinal", required = true) private Integer datasetOrdinal; public DatasetLog() { - super(0, (String)null); + super(0, (String) null); } public DatasetLog(Integer testId, Integer datasetId, Integer datasetOrdinal, Integer runId, - int level, String source, String message) { + int level, String source, String message) { super(level, message); this.testId = testId; this.datasetId = datasetId; diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/MissingDataRule.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/MissingDataRule.java index 1b2d68867..07a7fd8b0 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/MissingDataRule.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/MissingDataRule.java @@ -1,26 +1,28 @@ package io.hyperfoil.tools.horreum.api.alerting; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.node.ArrayNode; +import java.time.Instant; +import java.util.Objects; + import jakarta.validation.constraints.NotNull; + import org.eclipse.microprofile.openapi.annotations.media.Schema; -import java.time.Instant; -import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.node.ArrayNode; public class MissingDataRule { - @JsonProperty( required = true ) + @JsonProperty(required = true) public Integer id; public String name; @Schema(implementation = String[].class) public ArrayNode labels; public String condition; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public long maxStaleness; public Instant lastNotification; - @JsonProperty( value = "testId", required = true ) + @JsonProperty(value = "testId", required = true) public Integer testId; public MissingDataRule() { @@ -30,14 +32,15 @@ public boolean equals(Object o) { if (this == o) { return true; } else if (o != null && this.getClass() == o.getClass()) { - MissingDataRule that = (MissingDataRule)o; - return this.maxStaleness == that.maxStaleness && Objects.equals(this.labels, that.labels) && Objects.equals(this.condition, that.condition); + MissingDataRule that = (MissingDataRule) o; + return this.maxStaleness == that.maxStaleness && Objects.equals(this.labels, that.labels) + && Objects.equals(this.condition, that.condition); } else { return false; } } public int hashCode() { - return Objects.hash(new Object[]{this.labels, this.condition, this.maxStaleness}); + return Objects.hash(new Object[] { this.labels, this.condition, this.maxStaleness }); } } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/MissingDataRuleResult.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/MissingDataRuleResult.java index 3ff2de695..94135fd47 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/MissingDataRuleResult.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/MissingDataRuleResult.java @@ -1,11 +1,11 @@ package io.hyperfoil.tools.horreum.api.alerting; -import jakarta.validation.constraints.NotNull; - -import java.time.Instant; import java.io.Serializable; +import java.time.Instant; import java.util.Objects; +import jakarta.validation.constraints.NotNull; + public class MissingDataRuleResult { private Pk pk; @NotNull @@ -31,7 +31,8 @@ public int datasetId() { } public String toString() { - return "MissingDataRuleResult{dataset_id=" + this.pk.datasetId + ", rule_id=" + this.pk.ruleId + ", timestamp=" + this.timestamp + '}'; + return "MissingDataRuleResult{dataset_id=" + this.pk.datasetId + ", rule_id=" + this.pk.ruleId + ", timestamp=" + + this.timestamp + '}'; } public static class Pk implements Serializable { @@ -45,7 +46,7 @@ public boolean equals(Object o) { if (this == o) { return true; } else if (o != null && this.getClass() == o.getClass()) { - Pk pk = (Pk)o; + Pk pk = (Pk) o; return this.ruleId == pk.ruleId && this.datasetId == pk.datasetId; } else { return false; @@ -53,7 +54,7 @@ public boolean equals(Object o) { } public int hashCode() { - return Objects.hash(new Object[]{this.ruleId, this.datasetId}); + return Objects.hash(new Object[] { this.ruleId, this.datasetId }); } } } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/NotificationSettings.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/NotificationSettings.java index e24e11f21..4b640363f 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/NotificationSettings.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/NotificationSettings.java @@ -1,21 +1,22 @@ package io.hyperfoil.tools.horreum.api.alerting; -import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotNull; +import com.fasterxml.jackson.annotation.JsonProperty; + public class NotificationSettings { public Integer id; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public String name; - @JsonProperty( required = true ) + @JsonProperty(required = true) public boolean isTeam; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public String method; public String data; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public boolean disabled; } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/RunExpectation.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/RunExpectation.java index 255903f08..803b60a76 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/RunExpectation.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/RunExpectation.java @@ -1,9 +1,10 @@ package io.hyperfoil.tools.horreum.api.alerting; -import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; + import jakarta.validation.constraints.NotNull; -import java.time.Instant; +import com.fasterxml.jackson.annotation.JsonProperty; public class RunExpectation { public Long id; diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/TransformationLog.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/TransformationLog.java index 2aefea16d..dab3fce51 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/TransformationLog.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/TransformationLog.java @@ -1,11 +1,13 @@ package io.hyperfoil.tools.horreum.api.alerting; -import com.fasterxml.jackson.annotation.JsonProperty; -import io.hyperfoil.tools.horreum.api.data.PersistentLog; import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -@Schema( type = SchemaType.OBJECT, description = "Transformation Log", name = "TransformationLog") +import com.fasterxml.jackson.annotation.JsonProperty; + +import io.hyperfoil.tools.horreum.api.data.PersistentLog; + +@Schema(type = SchemaType.OBJECT, description = "Transformation Log", name = "TransformationLog") public class TransformationLog extends PersistentLog { @JsonProperty("testId") private Integer testId; @@ -14,7 +16,7 @@ public class TransformationLog extends PersistentLog { private Integer runId; public TransformationLog() { - super(0, (String)null); + super(0, (String) null); } public TransformationLog(Integer testId, Integer runId, int level, String message) { diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/Variable.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/Variable.java index 732a8b0d5..ca23393f9 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/Variable.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/Variable.java @@ -1,15 +1,17 @@ package io.hyperfoil.tools.horreum.api.alerting; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; +import java.util.Set; + import jakarta.validation.constraints.NotNull; + import org.eclipse.microprofile.openapi.annotations.media.Schema; -import java.util.List; -import java.util.Set; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; public class Variable { - @JsonProperty( required = true ) + @JsonProperty(required = true) public Integer id; @NotNull @JsonProperty(required = true) @@ -33,7 +35,7 @@ public Variable() { } public Variable(Integer id, int testId, String name, String group, int order, List labels, String calculation, - Set changeDetection) { + Set changeDetection) { this.id = id; this.testId = testId; this.name = name; @@ -45,7 +47,9 @@ public Variable(Integer id, int testId, String name, String group, int order, Li } public String toString() { - return "Variable{id=" + this.id + ", testId=" + this.testId + ", name='" + this.name + '\'' + ", group='" + this.group + '\'' + ", order=" + this.order + ", labels=" + this.labels + ", calculation='" + this.calculation + '\'' + ", changeDetection=" + this.changeDetection + '}'; + return "Variable{id=" + this.id + ", testId=" + this.testId + ", name='" + this.name + '\'' + ", group='" + this.group + + '\'' + ", order=" + this.order + ", labels=" + this.labels + ", calculation='" + this.calculation + '\'' + + ", changeDetection=" + this.changeDetection + '}'; } } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/Watch.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/Watch.java index 378b52f7d..45b238387 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/Watch.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/alerting/Watch.java @@ -1,28 +1,30 @@ package io.hyperfoil.tools.horreum.api.alerting; -import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; + import jakarta.validation.constraints.NotNull; -import java.util.List; +import com.fasterxml.jackson.annotation.JsonProperty; public class Watch { public Integer id; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public List users; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public List optout; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public List teams; - @JsonProperty( value = "testId", required = true ) + @JsonProperty(value = "testId", required = true) public Integer testId; public Watch() { } public String toString() { - return "Watch{id=" + this.id + ", test=" + this.testId + ", users=" + this.users + ", optout=" + this.optout + ", teams=" + this.teams + '}'; + return "Watch{id=" + this.id + ", test=" + this.testId + ", users=" + this.users + ", optout=" + this.optout + + ", teams=" + this.teams + '}'; } } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/changes/Dashboard.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/changes/Dashboard.java index 6ff8ebd0d..3950c77c4 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/changes/Dashboard.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/changes/Dashboard.java @@ -4,59 +4,62 @@ import java.util.List; public class Dashboard { - public Integer id; - public String uid; - public String title; - public TimeRange time = new TimeRange(); - public Annotations annotations = new Annotations(); - public List panels = new ArrayList<>(); - public List tags = new ArrayList<>(); - - public static class Annotations { - public List list = new ArrayList<>(); - } - - public static class Annotation { - public String name; - public String datasource = "Horreum"; - public String query; - public boolean enable = true; - public String iconColor = "rgba(255, 96, 96, 1)"; - - public Annotation() {} - - public Annotation(String name, String query) { - this.name = name; - this.query = query; - } - } - - public static class Panel { - public String title; - public String type = "graph"; - public String renderer = "flot"; - public String datasource = "Horreum"; - public GridPos gridPos; - public List targets = new ArrayList<>(); - - public Panel() {} - - public Panel(String title, GridPos gridPos) { - this.title = title; - this.gridPos = gridPos; - } - } - - public static class GridPos { - public int x, y, w, h; - - public GridPos() {} - - public GridPos(int x, int y, int w, int h) { - this.x = x; - this.y = y; - this.w = w; - this.h = h; - } - } + public Integer id; + public String uid; + public String title; + public TimeRange time = new TimeRange(); + public Annotations annotations = new Annotations(); + public List panels = new ArrayList<>(); + public List tags = new ArrayList<>(); + + public static class Annotations { + public List list = new ArrayList<>(); + } + + public static class Annotation { + public String name; + public String datasource = "Horreum"; + public String query; + public boolean enable = true; + public String iconColor = "rgba(255, 96, 96, 1)"; + + public Annotation() { + } + + public Annotation(String name, String query) { + this.name = name; + this.query = query; + } + } + + public static class Panel { + public String title; + public String type = "graph"; + public String renderer = "flot"; + public String datasource = "Horreum"; + public GridPos gridPos; + public List targets = new ArrayList<>(); + + public Panel() { + } + + public Panel(String title, GridPos gridPos) { + this.title = title; + this.gridPos = gridPos; + } + } + + public static class GridPos { + public int x, y, w, h; + + public GridPos() { + } + + public GridPos(int x, int y, int w, int h) { + this.x = x; + this.y = y; + this.w = w; + this.h = h; + } + } } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/changes/Target.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/changes/Target.java index e9770a7a3..3120101e4 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/changes/Target.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/changes/Target.java @@ -3,19 +3,19 @@ import com.fasterxml.jackson.databind.node.ObjectNode; public class Target { - //concatenated simicolons varibleID;{fingeprintJson} - public String target; - public String type; - public String refId; - public String data = ""; - public ObjectNode payload = null; + //concatenated simicolons varibleID;{fingeprintJson} + public String target; + public String type; + public String refId; + public String data = ""; + public ObjectNode payload = null; - public Target() { - } + public Target() { + } - public Target(String target, String type, String refId) { - this.target = target; - this.type = type; - this.refId = refId; - } + public Target(String target, String type, String refId) { + this.target = target; + this.type = type; + this.refId = refId; + } } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/changes/TimeRange.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/changes/TimeRange.java index 952ee6ca1..b7253809b 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/changes/TimeRange.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/changes/TimeRange.java @@ -1,6 +1,6 @@ package io.hyperfoil.tools.horreum.api.changes; public class TimeRange { - public String from = "now-30d"; - public String to = "now"; + public String from = "now-30d"; + public String to = "now"; } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Access.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Access.java index 5f26ab2de..244f648cc 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Access.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Access.java @@ -11,48 +11,49 @@ * * Do not change unless changing constants in SQL policies. */ -@Schema(type = SchemaType.STRING, required = true, - description = "Resources have different visibility within the UI. 'PUBLIC', 'PROTECTED' and 'PRIVATE'. Restricted resources are not visible to users who do not have the correct permissions") +@Schema(type = SchemaType.STRING, required = true, description = "Resources have different visibility within the UI. 'PUBLIC', 'PROTECTED' and 'PRIVATE'. Restricted resources are not visible to users who do not have the correct permissions") public enum Access { - /** Anyone can see */ - PUBLIC ("PUBLIC"), - /** Anyone who is authenticated (logged in) can see */ - PROTECTED ("PROTECTED"), - /** Only the owner can see */ - PRIVATE ("PRIVATE"), - ; - private static final Access[] VALUES = values(); - - private final String name; - - private Access(String s) { - name = s; - } - - public boolean equalsName(String otherName) { - // (otherName == null) check is not needed because name.equals(null) returns false - return name.equals(otherName); - } - - @JsonValue - public String toString() { - return this.name; - } - -// @JsonValue -// public int serialize() { -// return ordinal(); -// } - - @JsonCreator - public static Access fromString(String str) { - try { - return VALUES[Integer.parseInt(str)]; - } catch (NumberFormatException e) { - return Access.valueOf(str); - } - } - public static Access fromInt(int a) { - return VALUES[a]; - } + /** Anyone can see */ + PUBLIC("PUBLIC"), + /** Anyone who is authenticated (logged in) can see */ + PROTECTED("PROTECTED"), + /** Only the owner can see */ + PRIVATE("PRIVATE"), + ; + + private static final Access[] VALUES = values(); + + private final String name; + + private Access(String s) { + name = s; + } + + public boolean equalsName(String otherName) { + // (otherName == null) check is not needed because name.equals(null) returns false + return name.equals(otherName); + } + + @JsonValue + public String toString() { + return this.name; + } + + // @JsonValue + // public int serialize() { + // return ordinal(); + // } + + @JsonCreator + public static Access fromString(String str) { + try { + return VALUES[Integer.parseInt(str)]; + } catch (NumberFormatException e) { + return Access.valueOf(str); + } + } + + public static Access fromInt(int a) { + return VALUES[a]; + } } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Action.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Action.java index 9fb0b19c5..9163e42f1 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Action.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Action.java @@ -1,5 +1,11 @@ package io.hyperfoil.tools.horreum.api.data; +import jakarta.validation.constraints.NotNull; + +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.media.DiscriminatorMapping; +import org.eclipse.microprofile.openapi.annotations.media.Schema; + import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; @@ -10,11 +16,6 @@ import io.hyperfoil.tools.horreum.api.data.ActionConfig.GithubIssueCreateActionConfig; import io.hyperfoil.tools.horreum.api.data.ActionConfig.HttpActionConfig; import io.hyperfoil.tools.horreum.api.data.ActionConfig.SlackChannelMessageActionConfig; -import jakarta.validation.constraints.NotNull; - -import org.eclipse.microprofile.openapi.annotations.media.DiscriminatorMapping; -import org.eclipse.microprofile.openapi.annotations.media.Schema; -import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; public class Action { @@ -23,13 +24,13 @@ public static class Secret { public boolean modified; } - @JsonProperty( required = true ) + @JsonProperty(required = true) public Integer id; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public String event; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public String type; @NotNull @@ -49,27 +50,25 @@ public static class Secret { @NotNull @JsonIgnore - @Schema(type = SchemaType.OBJECT, - allOf = { - Action.Secret.class - } - ) + @Schema(type = SchemaType.OBJECT, allOf = { + Action.Secret.class + }) public ObjectNode secrets; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public Integer testId; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public boolean active = true; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public boolean runAlways; public Action() { } public Action(Integer id, String event, String type, ObjectNode config, ObjectNode secrets, - Integer testId, boolean active, boolean runAlways) { + Integer testId, boolean active, boolean runAlways) { this.id = id; this.event = event; this.type = type; diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ActionConfig/ActionType.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ActionConfig/ActionType.java index f33a10644..e1c2bd6ed 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ActionConfig/ActionType.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ActionConfig/ActionType.java @@ -1,11 +1,12 @@ package io.hyperfoil.tools.horreum.api.data.ActionConfig; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.core.type.TypeReference; +import java.util.Arrays; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -import java.util.Arrays; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.core.type.TypeReference; @Schema(type = SchemaType.STRING, required = true, description = "Type of Action") public enum ActionType { diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ActionConfig/GithubIssueCreateActionConfig.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ActionConfig/GithubIssueCreateActionConfig.java index 7996b3420..a75b8280d 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ActionConfig/GithubIssueCreateActionConfig.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ActionConfig/GithubIssueCreateActionConfig.java @@ -19,4 +19,5 @@ public class GithubIssueCreateActionConfig extends BaseActionConfig { public GithubIssueCreateActionConfig() { this.type = ActionType.GITHUB_ISSUE_CREATE.toString(); - }} + } +} diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ActionLog.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ActionLog.java index ee75906e1..0ed4cd62f 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ActionLog.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ActionLog.java @@ -1,22 +1,24 @@ package io.hyperfoil.tools.horreum.api.data; -import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotNull; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -@Schema( type = SchemaType.OBJECT, description = "Action Log", name = "ActionLog", allOf = PersistentLog.class) +import com.fasterxml.jackson.annotation.JsonProperty; + +@Schema(type = SchemaType.OBJECT, description = "Action Log", name = "ActionLog", allOf = PersistentLog.class) public class ActionLog extends PersistentLog { @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public int testId; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public String event; public String type; public ActionLog() { - super(0, (String)null); + super(0, (String) null); } public ActionLog(int level, int testId, String event, String type, String message) { diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/AllowedSite.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/AllowedSite.java index 71d6f69bf..a962a539c 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/AllowedSite.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/AllowedSite.java @@ -1,8 +1,9 @@ package io.hyperfoil.tools.horreum.api.data; -import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotNull; +import com.fasterxml.jackson.annotation.JsonProperty; + public class AllowedSite { public Long id; diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Banner.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Banner.java index de1871078..f59d6a430 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Banner.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Banner.java @@ -1,9 +1,10 @@ package io.hyperfoil.tools.horreum.api.data; -import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; + import jakarta.validation.constraints.NotNull; -import java.time.Instant; +import com.fasterxml.jackson.annotation.JsonProperty; public class Banner { @@ -12,7 +13,7 @@ public class Banner { public Instant created; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public boolean active; @NotNull @JsonProperty(required = true) diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ConditionConfig.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ConditionConfig.java index 2aabda270..faa174179 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ConditionConfig.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ConditionConfig.java @@ -5,7 +5,6 @@ import java.util.List; import java.util.Map; -import io.hyperfoil.tools.horreum.api.data.changeDetection.ChangeDetectionModelType; import jakarta.validation.constraints.NotNull; import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; @@ -14,191 +13,192 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import io.hyperfoil.tools.horreum.api.data.changeDetection.ChangeDetectionModelType; + @Schema(type = SchemaType.OBJECT, description = "A configuration object for Change detection models") public class ConditionConfig { - @NotNull - @Schema(description = "Name of Change detection model", example = ChangeDetectionModelType.names.FIXED_THRESHOLD) - public String name; - @NotNull - @Schema(description = "UI name for change detection model", example = "Fixed Threshold") - public String title; - @NotNull - @Schema(description = "Change detection model description", example = "This model checks that the datapoint value is within fixed bounds.") - public String description; - @NotNull - @Schema(description = "A list of UI components for dynamically building the UI components") - public List ui = new ArrayList<>(); - @Schema(description = "A dictionary of UI default configuration items for dynamically building the UI components") - public Map defaults = new HashMap<>(); - - public ConditionConfig(String name, String title, String description) { - this.name = name; - this.title = title; - this.description = description; - } - - public Component addComponent(String name, JsonNode defaultValue, ComponentType type, String title, String description) { - defaults.put(name, defaultValue); - Component component = new Component(name, title, description, type); - ui.add(component); - return component; - } - - public ConditionConfig addComponent(String name, ComponentTemplate template, String title, String description) { - Component component = addComponent(name, template.getDefault(), template.getType(), title, description); - template.addProperties(component); - return this; - } - - @Schema(name = "ConditionComponent") - public class Component { - @NotNull - @Schema(description = "Change detection model component name", example = "min") - public String name; - @NotNull - @Schema(description = "Change detection model component title", example = "Minimum") - public String title; - @NotNull - @Schema(description = "Change detection model component description", example = "Lower bound for acceptable datapoint values.") - public String description; - @NotNull - @Schema( type = SchemaType.OBJECT, implementation = ComponentType.class, - description = "UI Component type", example = "\"LOG_SLIDER\"") - public ComponentType type; - @NotNull - @Schema(description = "Map of properties for component", example = "") - public Map properties = new HashMap<>(); - - private Component(String name, String title, String description, ComponentType type) { - this.name = name; - this.title = title; - this.description = description; - this.type = type; - } - - public Component addProperty(String property, Object value) { - if (properties.put(property, value) != null) { - throw new IllegalArgumentException(property + " already set."); - } - return this; - } - - public ConditionConfig end() { - return ConditionConfig.this; - } - } - - public enum ComponentType { - LOG_SLIDER, - ENUM, - NUMBER_BOUND, - SWITCH, - } - - public interface ComponentTemplate { - ComponentType getType(); - - JsonNode getDefault(); - - void addProperties(Component component); - } - - public static class LogSliderComponent implements ComponentTemplate { - private final double scale; - private final double min; - private final double max; - private final double defaultValue; - private final boolean discrete; - private final String unit; - - public LogSliderComponent(double scale, double min, double max, double defaultValue, boolean discrete, String unit) { - this.scale = scale; - this.min = min; - this.max = max; - this.defaultValue = defaultValue; - this.discrete = discrete; - this.unit = unit; - } - - @Override - public ComponentType getType() { - return ComponentType.LOG_SLIDER; - } - - @Override - public JsonNode getDefault() { - return JsonNodeFactory.instance.numberNode(defaultValue); - } - - @Override - public void addProperties(Component component) { - component - .addProperty("scale", scale) - .addProperty("min", min) - .addProperty("max", max) - .addProperty("unit", unit) - .addProperty("discrete", discrete); - } - } - - public static class EnumComponent implements ComponentTemplate { - private final Map options = new HashMap<>(); - private final String defaultValue; - - public EnumComponent(String defaultValue) { - this.defaultValue = defaultValue; - } - - public EnumComponent add(String name, String title) { - options.put(name, title); - return this; - } - - @Override - public ComponentType getType() { - return ComponentType.ENUM; - } - - @Override - public JsonNode getDefault() { - return JsonNodeFactory.instance.textNode(defaultValue); - } - - @Override - public void addProperties(Component component) { - component.addProperty("options", options); - } - } - - public static class NumberBound implements ComponentTemplate { - @Override - public ComponentType getType() { - return ComponentType.NUMBER_BOUND; - } - - @Override - public JsonNode getDefault() { - return JsonNodeFactory.instance.objectNode().put("value", 0).put("inclusive", true).put("enabled", false); - } - - @Override - public void addProperties(Component component) { - } - } - - public static class SwitchComponent implements ComponentTemplate { - @Override - public ComponentType getType() { - return ComponentType.SWITCH; - } - - @Override - public JsonNode getDefault() { - return JsonNodeFactory.instance.booleanNode(true); - } - - @Override - public void addProperties(Component component) { - } - } + @NotNull + @Schema(description = "Name of Change detection model", example = ChangeDetectionModelType.names.FIXED_THRESHOLD) + public String name; + @NotNull + @Schema(description = "UI name for change detection model", example = "Fixed Threshold") + public String title; + @NotNull + @Schema(description = "Change detection model description", example = "This model checks that the datapoint value is within fixed bounds.") + public String description; + @NotNull + @Schema(description = "A list of UI components for dynamically building the UI components") + public List ui = new ArrayList<>(); + @Schema(description = "A dictionary of UI default configuration items for dynamically building the UI components") + public Map defaults = new HashMap<>(); + + public ConditionConfig(String name, String title, String description) { + this.name = name; + this.title = title; + this.description = description; + } + + public Component addComponent(String name, JsonNode defaultValue, ComponentType type, String title, String description) { + defaults.put(name, defaultValue); + Component component = new Component(name, title, description, type); + ui.add(component); + return component; + } + + public ConditionConfig addComponent(String name, ComponentTemplate template, String title, String description) { + Component component = addComponent(name, template.getDefault(), template.getType(), title, description); + template.addProperties(component); + return this; + } + + @Schema(name = "ConditionComponent") + public class Component { + @NotNull + @Schema(description = "Change detection model component name", example = "min") + public String name; + @NotNull + @Schema(description = "Change detection model component title", example = "Minimum") + public String title; + @NotNull + @Schema(description = "Change detection model component description", example = "Lower bound for acceptable datapoint values.") + public String description; + @NotNull + @Schema(type = SchemaType.OBJECT, implementation = ComponentType.class, description = "UI Component type", example = "\"LOG_SLIDER\"") + public ComponentType type; + @NotNull + @Schema(description = "Map of properties for component", example = "") + public Map properties = new HashMap<>(); + + private Component(String name, String title, String description, ComponentType type) { + this.name = name; + this.title = title; + this.description = description; + this.type = type; + } + + public Component addProperty(String property, Object value) { + if (properties.put(property, value) != null) { + throw new IllegalArgumentException(property + " already set."); + } + return this; + } + + public ConditionConfig end() { + return ConditionConfig.this; + } + } + + public enum ComponentType { + LOG_SLIDER, + ENUM, + NUMBER_BOUND, + SWITCH, + } + + public interface ComponentTemplate { + ComponentType getType(); + + JsonNode getDefault(); + + void addProperties(Component component); + } + + public static class LogSliderComponent implements ComponentTemplate { + private final double scale; + private final double min; + private final double max; + private final double defaultValue; + private final boolean discrete; + private final String unit; + + public LogSliderComponent(double scale, double min, double max, double defaultValue, boolean discrete, String unit) { + this.scale = scale; + this.min = min; + this.max = max; + this.defaultValue = defaultValue; + this.discrete = discrete; + this.unit = unit; + } + + @Override + public ComponentType getType() { + return ComponentType.LOG_SLIDER; + } + + @Override + public JsonNode getDefault() { + return JsonNodeFactory.instance.numberNode(defaultValue); + } + + @Override + public void addProperties(Component component) { + component + .addProperty("scale", scale) + .addProperty("min", min) + .addProperty("max", max) + .addProperty("unit", unit) + .addProperty("discrete", discrete); + } + } + + public static class EnumComponent implements ComponentTemplate { + private final Map options = new HashMap<>(); + private final String defaultValue; + + public EnumComponent(String defaultValue) { + this.defaultValue = defaultValue; + } + + public EnumComponent add(String name, String title) { + options.put(name, title); + return this; + } + + @Override + public ComponentType getType() { + return ComponentType.ENUM; + } + + @Override + public JsonNode getDefault() { + return JsonNodeFactory.instance.textNode(defaultValue); + } + + @Override + public void addProperties(Component component) { + component.addProperty("options", options); + } + } + + public static class NumberBound implements ComponentTemplate { + @Override + public ComponentType getType() { + return ComponentType.NUMBER_BOUND; + } + + @Override + public JsonNode getDefault() { + return JsonNodeFactory.instance.objectNode().put("value", 0).put("inclusive", true).put("enabled", false); + } + + @Override + public void addProperties(Component component) { + } + } + + public static class SwitchComponent implements ComponentTemplate { + @Override + public ComponentType getType() { + return ComponentType.SWITCH; + } + + @Override + public JsonNode getDefault() { + return JsonNodeFactory.instance.booleanNode(true); + } + + @Override + public void addProperties(Component component) { + } + } } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Dataset.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Dataset.java index d8246d553..b26ee907c 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Dataset.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Dataset.java @@ -1,17 +1,19 @@ package io.hyperfoil.tools.horreum.api.data; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.JsonNode; +import java.util.List; +import java.util.Objects; + import jakarta.validation.constraints.NotNull; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -import java.util.List; -import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; -@Schema(type = SchemaType.OBJECT, allOf = { ProtectedType.class, ProtectedTimeType.class } , -description = "A dataset is the JSON document used as the basis for all comparisons and reporting") +@Schema(type = SchemaType.OBJECT, allOf = { ProtectedType.class, + ProtectedTimeType.class }, description = "A dataset is the JSON document used as the basis for all comparisons and reporting") public class Dataset extends ProtectedTimeType { @Schema(description = "Dataset Unique ID", example = "101") @@ -25,8 +27,7 @@ public class Dataset extends ProtectedTimeType { public Integer testid; @NotNull - @Schema(implementation = JsonNode.class, type = SchemaType.STRING, - description = "Data payload") + @Schema(implementation = JsonNode.class, type = SchemaType.STRING, description = "Data payload") public JsonNode data; @NotNull @Schema(description = "Dataset ordinal for ordered list of Datasets derived from a Run", example = "1") @@ -38,6 +39,7 @@ public class Dataset extends ProtectedTimeType { @JsonProperty("runId") @Schema(description = "Run ID that Dataset relates to", example = "101") public Integer runId; + @JsonIgnore public Info getInfo() { return new Info(this.id, this.runId, this.ordinal, this.testid); @@ -59,18 +61,18 @@ public Dataset(Run run, int ordinal, String description, JsonNode data) { this.data = data; } - @Schema( name = "DatasetInfo" ) + @Schema(name = "DatasetInfo") public static class Info { - @JsonProperty( required = true ) + @JsonProperty(required = true) @Schema(description = "Dataset ID for Dataset", example = "101") public int id; - @JsonProperty( required = true ) + @JsonProperty(required = true) @Schema(description = "Run ID that Dataset relates to", example = "101") public int runId; - @JsonProperty( required = true ) + @JsonProperty(required = true) @Schema(description = "Ordinal position in ordered list", example = "2") public int ordinal; - @JsonProperty( required = true ) + @JsonProperty(required = true) @Schema(description = "Test ID that Dataset relates to", example = "103") public int testId; @@ -88,19 +90,21 @@ public boolean equals(Object o) { if (this == o) { return true; } else if (o != null && this.getClass() == o.getClass()) { - Info info = (Info)o; - return this.id == info.id && this.runId == info.runId && this.ordinal == info.ordinal && this.testId == info.testId; + Info info = (Info) o; + return this.id == info.id && this.runId == info.runId && this.ordinal == info.ordinal + && this.testId == info.testId; } else { return false; } } public int hashCode() { - return Objects.hash(new Object[]{this.id, this.runId, this.ordinal, this.testId}); + return Objects.hash(new Object[] { this.id, this.runId, this.ordinal, this.testId }); } public String toString() { - return "DatasetInfo{id=" + this.id + ", runId=" + this.runId + ", ordinal=" + this.ordinal + ", testId=" + this.testId + '}'; + return "DatasetInfo{id=" + this.id + ", runId=" + this.runId + ", ordinal=" + this.ordinal + ", testId=" + + this.testId + '}'; } } @@ -145,6 +149,7 @@ public EventNew(Dataset dataSet, boolean isRecalculation) { this.runId = dataSet.runId; this.isRecalculation = isRecalculation; } + public EventNew(int datasetId, int testId, int runId, int labelId, boolean isRecalculation) { this.datasetId = datasetId; this.testId = testId; diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ExperimentComparison.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ExperimentComparison.java index a71aa2dd0..436ee601c 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ExperimentComparison.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ExperimentComparison.java @@ -1,20 +1,23 @@ package io.hyperfoil.tools.horreum.api.data; +import jakarta.validation.constraints.NotNull; + +import org.eclipse.microprofile.openapi.annotations.media.Schema; + import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.node.ObjectNode; + import io.hyperfoil.tools.horreum.api.data.changeDetection.ChangeDetectionModelType; -import jakarta.validation.constraints.NotNull; -import org.eclipse.microprofile.openapi.annotations.media.Schema; public class ExperimentComparison { @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) @Schema(description = "Name of comparison model", example = ChangeDetectionModelType.names.RELATIVE_DIFFERENCE) public String model; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) @Schema(implementation = String.class, description = "Model JSON configuration") public ObjectNode config; diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ExperimentProfile.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ExperimentProfile.java index 4e217bbb2..5122ba26a 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ExperimentProfile.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ExperimentProfile.java @@ -1,19 +1,21 @@ package io.hyperfoil.tools.horreum.api.data; -import com.fasterxml.jackson.annotation.JsonIdentityInfo; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.ObjectIdGenerators; -import com.fasterxml.jackson.databind.JsonNode; +import java.util.Collection; + import jakarta.validation.constraints.NotNull; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -import java.util.Collection; +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; +import com.fasterxml.jackson.databind.JsonNode; -@JsonIdentityInfo( property = "id", generator = ObjectIdGenerators.PropertyGenerator.class) +@JsonIdentityInfo(property = "id", generator = ObjectIdGenerators.PropertyGenerator.class) @Schema(description = "An Experiment Profile defines the labels and filters for the dataset and baseline") public class ExperimentProfile { - @JsonProperty(required = true ) + @JsonProperty(required = true) @Schema(description = "Experiment Profile unique ID", example = "101") public Integer id; @NotNull @@ -25,14 +27,11 @@ public class ExperimentProfile { // before the test is saved, therefore the test might not have an ID @Schema(description = "Test ID that Experiment Profile relates to", example = "101") public Integer testId; - @Schema(type = SchemaType.ARRAY, implementation = String.class, required = true, description = "Array of selector labels", - example = "[\"Framework\"]") + @Schema(type = SchemaType.ARRAY, implementation = String.class, required = true, description = "Array of selector labels", example = "[\"Framework\"]") public JsonNode selectorLabels; - @Schema(description = "Selector filter to apply to Selector label values", - example = "value => value === 'quarkus-resteasy-reactive-hibernate-reactive'") + @Schema(description = "Selector filter to apply to Selector label values", example = "value => value === 'quarkus-resteasy-reactive-hibernate-reactive'") public String selectorFilter; - @Schema(type = SchemaType.ARRAY, implementation = String.class, required = true, - description = "Array of selector labels for comparison Baseline", example = "[\"timestamp\"]") + @Schema(type = SchemaType.ARRAY, implementation = String.class, required = true, description = "Array of selector labels for comparison Baseline", example = "[\"timestamp\"]") public JsonNode baselineLabels; @Schema(description = "Selector filter to apply to Baseline label values", example = "value => value === 1666955225547") public String baselineFilter; diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ExportedLabelValues.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ExportedLabelValues.java index 2d368c061..261f32b97 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ExportedLabelValues.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ExportedLabelValues.java @@ -1,66 +1,57 @@ package io.hyperfoil.tools.horreum.api.data; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.util.DefaultIndenter; -import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.databind.node.ObjectNode; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + import jakarta.validation.constraints.NotNull; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -import java.time.Instant; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; +import com.fasterxml.jackson.databind.node.ObjectNode; -@Schema(type = SchemaType.OBJECT, - description = "A map of label names to label values with the associated datasetId and runId") +@Schema(type = SchemaType.OBJECT, description = "A map of label names to label values with the associated datasetId and runId") public class ExportedLabelValues { @Schema public LabelValueMap values; - @Schema(type = SchemaType.INTEGER,description = "the run id that created the dataset",example = "101") + @Schema(type = SchemaType.INTEGER, description = "the run id that created the dataset", example = "101") public Integer runId; - @Schema(type = SchemaType.INTEGER,description = "the unique dataset id",example = "101") + @Schema(type = SchemaType.INTEGER, description = "the unique dataset id", example = "101") public Integer datasetId; @NotNull - @Schema(type = SchemaType.STRING, implementation = Instant.class, - description = "Start timestamp", example = "2019-09-26T07:58:30.996+0200") + @Schema(type = SchemaType.STRING, implementation = Instant.class, description = "Start timestamp", example = "2019-09-26T07:58:30.996+0200") public Instant start; @NotNull - @Schema(type = SchemaType.STRING, implementation = Instant.class, - description = "Stop timestamp", example = "2019-09-26T07:58:30.996+0200") + @Schema(type = SchemaType.STRING, implementation = Instant.class, description = "Stop timestamp", example = "2019-09-26T07:58:30.996+0200") public Instant stop; - public ExportedLabelValues() {} + public ExportedLabelValues() { + } - public ExportedLabelValues(LabelValueMap v, Integer runId, Integer datasetId,Instant start,Instant stop) { - this.values = v; - this.runId = runId; - this.datasetId = datasetId; - this.start = start; - this.stop = stop; + public ExportedLabelValues(LabelValueMap v, Integer runId, Integer datasetId, Instant start, Instant stop) { + this.values = v; + this.runId = runId; + this.datasetId = datasetId; + this.start = start; + this.stop = stop; } public static List parse(List nodes) { - if(nodes == null || nodes.isEmpty()) + if (nodes == null || nodes.isEmpty()) return new ArrayList<>(); List fps = new ArrayList<>(); - nodes.forEach(objects->{ - ObjectNode node = (ObjectNode)objects[0]; - Integer runId = Integer.parseInt(objects[1]==null?"-1":objects[1].toString()); - Integer datasetId = Integer.parseInt(objects[2]==null?"-1":objects[2].toString()); - Instant start = (Instant)objects[3]; - Instant stop = (Instant)objects[4]; - if(node.isObject()){ - fps.add(new ExportedLabelValues(LabelValueMap.fromObjectNode(node),runId,datasetId,start,stop)); - }else{ + nodes.forEach(objects -> { + ObjectNode node = (ObjectNode) objects[0]; + Integer runId = Integer.parseInt(objects[1] == null ? "-1" : objects[1].toString()); + Integer datasetId = Integer.parseInt(objects[2] == null ? "-1" : objects[2].toString()); + Instant start = (Instant) objects[3]; + Instant stop = (Instant) objects[4]; + if (node.isObject()) { + fps.add(new ExportedLabelValues(LabelValueMap.fromObjectNode(node), runId, datasetId, start, stop)); + } else { //TODO alert that something is wrong in the db response } }); diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Extractor.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Extractor.java index 12923afb9..fcc30031a 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Extractor.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Extractor.java @@ -1,24 +1,24 @@ package io.hyperfoil.tools.horreum.api.data; -import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotNull; + import org.eclipse.microprofile.openapi.annotations.media.Schema; +import com.fasterxml.jackson.annotation.JsonProperty; + @Schema(description = "An Extractor defines how values are extracted from a JSON document, for use in Labels etc.") public class Extractor { @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) @Schema(description = "Name of extractor. This name is used in Combination Functions to refer to values by name", example = "buildID") public String name; @NotNull - @JsonProperty( required = true ) - @Schema(description = "JSON path expression defining the location of the extractor value in the JSON document. This is a pSQL json path expression", - example = "$.buildInfo.buildID") + @JsonProperty(required = true) + @Schema(description = "JSON path expression defining the location of the extractor value in the JSON document. This is a pSQL json path expression", example = "$.buildInfo.buildID") public String jsonpath; @NotNull @JsonProperty(value = "isarray", required = true) - @Schema(description = "Does the JSON path expression reference an Array?", - example = "false") + @Schema(description = "Does the JSON path expression reference an Array?", example = "false") public boolean isArray; public Extractor() { diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/FingerprintValue.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/FingerprintValue.java index 7db65a0ec..b3f9c31cb 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/FingerprintValue.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/FingerprintValue.java @@ -1,15 +1,15 @@ package io.hyperfoil.tools.horreum.api.data; -import com.fasterxml.jackson.databind.JsonNode; +import java.util.ArrayList; +import java.util.List; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -import java.util.ArrayList; -import java.util.List; +import com.fasterxml.jackson.databind.JsonNode; -@Schema(type = SchemaType.OBJECT, - description = "Representation of Fingerprint. If the Fingerprint has children the value will be null.") -public class FingerprintValue { +@Schema(type = SchemaType.OBJECT, description = "Representation of Fingerprint. If the Fingerprint has children the value will be null.") +public class FingerprintValue { @Schema(description = "Fingerprint name", example = "Mode") public String name; @Schema(description = "Fingerprint name", example = "Library") @@ -22,11 +22,11 @@ public FingerprintValue() { public static List parse(JsonNode base) { List fpvs = new ArrayList<>(); - base.fieldNames().forEachRemaining( name -> { + base.fieldNames().forEachRemaining(name -> { FingerprintValue v; JsonNode node = base.path(name); - if(node.isValueNode()) { - switch (base.path(name).getNodeType()){ + if (node.isValueNode()) { + switch (base.path(name).getNodeType()) { case BINARY: v = new FingerprintValue(); break; diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Fingerprints.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Fingerprints.java index 40caf6ba5..77e3f583a 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Fingerprints.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Fingerprints.java @@ -1,14 +1,14 @@ package io.hyperfoil.tools.horreum.api.data; -import com.fasterxml.jackson.databind.JsonNode; +import java.util.ArrayList; +import java.util.List; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -import java.util.ArrayList; -import java.util.List; +import com.fasterxml.jackson.databind.JsonNode; -@Schema(type = SchemaType.OBJECT, - description = "A list of Fingerprints representing one dataset") +@Schema(type = SchemaType.OBJECT, description = "A list of Fingerprints representing one dataset") public class Fingerprints { @Schema(type = SchemaType.ARRAY, implementation = FingerprintValue.class) @@ -23,11 +23,11 @@ public Fingerprints(List parse) { } public static List parse(List nodes) { - if(nodes == null || nodes.isEmpty()) + if (nodes == null || nodes.isEmpty()) return new ArrayList<>(); List fps = new ArrayList<>(); - nodes.forEach( n -> fps.add( new Fingerprints( FingerprintValue.parse(n)))); + nodes.forEach(n -> fps.add(new Fingerprints(FingerprintValue.parse(n)))); return fps; } } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/IndexedLabelValueMap.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/IndexedLabelValueMap.java index 09524ce90..ee7b204f7 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/IndexedLabelValueMap.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/IndexedLabelValueMap.java @@ -1,26 +1,26 @@ package io.hyperfoil.tools.horreum.api.data; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import org.eclipse.microprofile.openapi.annotations.media.Schema; - import java.util.HashMap; import java.util.Map; +import org.eclipse.microprofile.openapi.annotations.media.Schema; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; @Schema(description = "a map of view component Id to the label values necessary to render the component") public class IndexedLabelValueMap extends HashMap { - public static IndexedLabelValueMap fromObjectNode(ObjectNode node){ + public static IndexedLabelValueMap fromObjectNode(ObjectNode node) { Map rtrn = new HashMap<>(); - if(node != null){ - node.fields().forEachRemaining(entry->{ + if (node != null) { + node.fields().forEachRemaining(entry -> { String entryKey = entry.getKey(); JsonNode entryNode = entry.getValue(); - if(entryNode.isObject()){ + if (entryNode.isObject()) { LabelValueMap map = LabelValueMap.fromObjectNode((ObjectNode) entryNode); - rtrn.put(entryKey,map); - }else{//this should not happen + rtrn.put(entryKey, map); + } else {//this should not happen } }); @@ -28,9 +28,11 @@ public static IndexedLabelValueMap fromObjectNode(ObjectNode node){ return new IndexedLabelValueMap(rtrn); } - public IndexedLabelValueMap(){} - public IndexedLabelValueMap(Map values){ + public IndexedLabelValueMap() { + } + + public IndexedLabelValueMap(Map values) { super(); this.putAll(values); } -} \ No newline at end of file +} diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Label.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Label.java index 15263006b..ddf258d88 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Label.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Label.java @@ -1,43 +1,43 @@ package io.hyperfoil.tools.horreum.api.data; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.JsonNode; +import java.io.Serializable; +import java.util.Collection; +import java.util.Objects; + import jakarta.validation.constraints.NotNull; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -import java.io.Serializable; -import java.util.Collection; -import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; -@Schema(type = SchemaType.OBJECT, allOf = ProtectedType.class, - description = "A Label is a core component of Horreum, defining which components of the JSON document are part of a KPI and how the metric values are calculated") +@Schema(type = SchemaType.OBJECT, allOf = ProtectedType.class, description = "A Label is a core component of Horreum, defining which components of the JSON document are part of a KPI and how the metric values are calculated") public class Label extends ProtectedType { - @JsonProperty( required = true ) + @JsonProperty(required = true) @Schema(description = "Unique ID for Label", example = "101") public Integer id; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) @Schema(description = "Name for label. NOTE: all Labels are considered to have the same semantic meaning throughout the entire system", example = "Throughput") public String name; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) @Schema(description = "A collection of Extractors, that will be combined in the Combination Function") public Collection extractors; - @Schema(description = "A Combination Function that defines how values from Extractors are combined to produce a Label Value", - example = "value => { return ((value.reduce((a,b) => a+b))/value.length*1000).toFixed(3); }") + @Schema(description = "A Combination Function that defines how values from Extractors are combined to produce a Label Value", example = "value => { return ((value.reduce((a,b) => a+b))/value.length*1000).toFixed(3); }") public String function; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) @Schema(description = "Is Label a filtering label? Filtering labels contains values that are used to filter datasets for comparison", example = "true") public boolean filtering = true; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) @Schema(description = "Is Label a metrics label? Metrics labels are contain Metrics that are used for comparison", example = "true") public boolean metrics = true; @NotNull - @JsonProperty( value = "schemaId", required = true ) + @JsonProperty(value = "schemaId", required = true) @Schema(description = "Schema ID that the Label relates to", example = "101") public int schemaId; @@ -62,15 +62,16 @@ public boolean equals(Object o) { if (this == o) { return true; } else if (o != null && this.getClass() == o.getClass()) { - Value value1 = (Value)o; - return this.datasetId == value1.datasetId && this.labelId == value1.labelId && Objects.equals(this.value, value1.value); + Value value1 = (Value) o; + return this.datasetId == value1.datasetId && this.labelId == value1.labelId + && Objects.equals(this.value, value1.value); } else { return false; } } public int hashCode() { - return Objects.hash(new Object[]{this.datasetId, this.labelId, this.value}); + return Objects.hash(new Object[] { this.datasetId, this.labelId, this.value }); } public String toString() { diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/LabelValueMap.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/LabelValueMap.java index 1d8b1dcf2..a6a11ab41 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/LabelValueMap.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/LabelValueMap.java @@ -1,23 +1,24 @@ package io.hyperfoil.tools.horreum.api.data; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; +import java.util.HashMap; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -import java.util.HashMap; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; /** * */ -@Schema(type = SchemaType.OBJECT, description = "a map of label name to value",example = "{ \"[labelName]\": labelValue}") +@Schema(type = SchemaType.OBJECT, description = "a map of label name to value", example = "{ \"[labelName]\": labelValue}") public class LabelValueMap extends HashMap { - public static LabelValueMap fromObjectNode(ObjectNode node){ + public static LabelValueMap fromObjectNode(ObjectNode node) { LabelValueMap rtrn = new LabelValueMap(); - if(node != null){ - node.fields().forEachRemaining(field->{ - rtrn.put(field.getKey(),field.getValue()); + if (node != null) { + node.fields().forEachRemaining(field -> { + rtrn.put(field.getKey(), field.getValue()); }); } return rtrn; diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/PersistentLog.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/PersistentLog.java index 74e7df8fc..4ac45a810 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/PersistentLog.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/PersistentLog.java @@ -1,53 +1,54 @@ package io.hyperfoil.tools.horreum.api.data; +import java.time.Instant; + import jakarta.validation.constraints.NotNull; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; import org.jboss.logging.Logger; import com.fasterxml.jackson.annotation.JsonProperty; -import java.time.Instant; - -@Schema( type = SchemaType.OBJECT, description = "Persistent Log", name = "PersistentLog") +@Schema(type = SchemaType.OBJECT, description = "Persistent Log", name = "PersistentLog") public abstract class PersistentLog { - public static final int DEBUG = 0; - public static final int INFO = 1; - public static final int WARN = 2; - public static final int ERROR = 3; - - @JsonProperty(required = true) - public Long id; - - @NotNull - @JsonProperty(required = true) - public int level; - - @NotNull - @JsonProperty(required = true) - public Instant timestamp; - - @NotNull - @JsonProperty(required = true) - public String message; - - public PersistentLog(int level, String message) { - this.level = level; - this.message = message; - this.timestamp = Instant.now(); - } - - public static Logger.Level logLevel(int level) { - switch (level) { - case DEBUG: - return Logger.Level.DEBUG; - case INFO: - return Logger.Level.INFO; - case WARN: - return Logger.Level.WARN; - case ERROR: - default: - return Logger.Level.ERROR; - } - } + public static final int DEBUG = 0; + public static final int INFO = 1; + public static final int WARN = 2; + public static final int ERROR = 3; + + @JsonProperty(required = true) + public Long id; + + @NotNull + @JsonProperty(required = true) + public int level; + + @NotNull + @JsonProperty(required = true) + public Instant timestamp; + + @NotNull + @JsonProperty(required = true) + public String message; + + public PersistentLog(int level, String message) { + this.level = level; + this.message = message; + this.timestamp = Instant.now(); + } + + public static Logger.Level logLevel(int level) { + switch (level) { + case DEBUG: + return Logger.Level.DEBUG; + case INFO: + return Logger.Level.INFO; + case WARN: + return Logger.Level.WARN; + case ERROR: + default: + return Logger.Level.ERROR; + } + } } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ProtectedTimeType.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ProtectedTimeType.java index bef2ad5fc..cd27128b5 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ProtectedTimeType.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ProtectedTimeType.java @@ -1,28 +1,26 @@ package io.hyperfoil.tools.horreum.api.data; -import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.Instant; + import jakarta.validation.constraints.NotNull; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -import java.time.Instant; +import com.fasterxml.jackson.annotation.JsonProperty; @Schema(type = SchemaType.OBJECT) -public class ProtectedTimeType extends ProtectedType{ +public class ProtectedTimeType extends ProtectedType { @NotNull @JsonProperty(required = true) - @Schema(implementation = Instant.class, type = SchemaType.INTEGER, format = "int64", - description = "Run Start timestamp", example = "1704965908267") + @Schema(implementation = Instant.class, type = SchemaType.INTEGER, format = "int64", description = "Run Start timestamp", example = "1704965908267") public Instant start; @NotNull @JsonProperty(required = true) - @Schema(implementation = Instant.class, type = SchemaType.INTEGER, format = "int64", - description = "Run Stop timestamp", example = "1704965908267") + @Schema(implementation = Instant.class, type = SchemaType.INTEGER, format = "int64", description = "Run Stop timestamp", example = "1704965908267") public Instant stop; - public ProtectedTimeType() {} - + public ProtectedTimeType() { + } } - - diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ProtectedType.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ProtectedType.java index f10e1927d..a4ed446b8 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ProtectedType.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ProtectedType.java @@ -1,23 +1,23 @@ package io.hyperfoil.tools.horreum.api.data; -import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotNull; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; +import com.fasterxml.jackson.annotation.JsonProperty; + @Schema(type = SchemaType.OBJECT) public class ProtectedType { @NotNull @JsonProperty(required = true) - @Schema( description = "Access rights for the test. This defines the visibility of the Test in the UI", - example = "PUBLIC", required = true, type = SchemaType.STRING, implementation = Access.class, allOf = Access.class) + @Schema(description = "Access rights for the test. This defines the visibility of the Test in the UI", example = "PUBLIC", required = true, type = SchemaType.STRING, implementation = Access.class, allOf = Access.class) public Access access; @NotNull @JsonProperty(required = true) - @Schema(description="Name of the team that owns the test. Users must belong to the team that owns a test to make modifications", - example="performance-team") + @Schema(description = "Name of the team that owns the test. Users must belong to the team that owns a test to make modifications", example = "performance-team") public String owner; public ProtectedType() { diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/QueryResult.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/QueryResult.java index c7a3a42f6..63f7d709e 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/QueryResult.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/QueryResult.java @@ -1,5 +1,5 @@ package io.hyperfoil.tools.horreum.api.data; public class QueryResult extends JsonpathValidation { - public String value; + public String value; } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Run.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Run.java index 9f0bb7a3b..f600a0d0d 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Run.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Run.java @@ -1,13 +1,15 @@ package io.hyperfoil.tools.horreum.api.data; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.JsonNode; +import java.util.Collection; + import jakarta.validation.constraints.NotNull; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -import java.util.Collection; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; @Schema(type = SchemaType.OBJECT) public class Run extends ProtectedTimeType { @@ -21,12 +23,10 @@ public class Run extends ProtectedTimeType { @Schema(description = "Test ID run relates to", example = "101") public Integer testid; @NotNull - @Schema(implementation = JsonNode.class, type = SchemaType.STRING, - description = "Run result payload") + @Schema(implementation = JsonNode.class, type = SchemaType.STRING, description = "Run result payload") @JsonProperty(required = true) public JsonNode data; - @Schema(implementation = JsonNode.class, type = SchemaType.STRING, - description = "JSON metadata related to run, can be tool configuration etc") + @Schema(implementation = JsonNode.class, type = SchemaType.STRING, description = "JSON metadata related to run, can be tool configuration etc") public JsonNode metadata; @NotNull @JsonProperty(required = true) diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Schema.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Schema.java index d8d333187..913ae4f1b 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Schema.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Schema.java @@ -1,35 +1,32 @@ package io.hyperfoil.tools.horreum.api.data; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.JsonNode; +import java.util.Collection; + import jakarta.validation.constraints.NotNull; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; -import java.util.Collection; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; -@org.eclipse.microprofile.openapi.annotations.media.Schema(name = "Schema", type = SchemaType.OBJECT, allOf = ProtectedType.class, - description = "Data object that describes the schema definition for a test" ) +@org.eclipse.microprofile.openapi.annotations.media.Schema(name = "Schema", type = SchemaType.OBJECT, allOf = ProtectedType.class, description = "Data object that describes the schema definition for a test") public class Schema extends ProtectedType { - @org.eclipse.microprofile.openapi.annotations.media.Schema(required = true, - description = "Unique Schema ID", example = "101") + @org.eclipse.microprofile.openapi.annotations.media.Schema(required = true, description = "Unique Schema ID", example = "101") @JsonProperty(required = true) public Integer id; @NotNull - @org.eclipse.microprofile.openapi.annotations.media.Schema(required = true, - description = "Unique, versioned schema URI", example = "uri:my-schema:0.1") + @org.eclipse.microprofile.openapi.annotations.media.Schema(required = true, description = "Unique, versioned schema URI", example = "uri:my-schema:0.1") @JsonProperty(required = true) public String uri; @NotNull - @org.eclipse.microprofile.openapi.annotations.media.Schema(required = true, - description = "Schema name", example = "My benchmark schema") + @org.eclipse.microprofile.openapi.annotations.media.Schema(required = true, description = "Schema name", example = "My benchmark schema") @JsonProperty(required = true) public String name; - @org.eclipse.microprofile.openapi.annotations.media.Schema( - description = "Schema Description", example = "Schema for processing my benchmark") + @org.eclipse.microprofile.openapi.annotations.media.Schema(description = "Schema Description", example = "Schema for processing my benchmark") public String description; - @org.eclipse.microprofile.openapi.annotations.media.Schema(implementation = String.class, description = "JSON validation schema. Used to validate uploaded JSON documents", - example = "{" + + @org.eclipse.microprofile.openapi.annotations.media.Schema(implementation = String.class, description = "JSON validation schema. Used to validate uploaded JSON documents", example = "{" + + " \"$schema\": \"https://json-schema.org/draft/2020-12/schema\"," + " \"$id\": \"https://example.com/product.schema.json\"," + " \"title\": \"Product\"," + @@ -38,8 +35,7 @@ public class Schema extends ProtectedType { "}") public JsonNode schema; - @org.eclipse.microprofile.openapi.annotations.media.Schema(description = "Array of API tokens associated with test", - example = "") + @org.eclipse.microprofile.openapi.annotations.media.Schema(description = "Array of API tokens associated with test", example = "") public String token; public Schema() { diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/SchemaExport.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/SchemaExport.java index 80707f3e8..74596ca4d 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/SchemaExport.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/SchemaExport.java @@ -1,11 +1,10 @@ package io.hyperfoil.tools.horreum.api.data; -import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; - import java.util.List; -@org.eclipse.microprofile.openapi.annotations.media.Schema(type = SchemaType.OBJECT, allOf = Schema.class, - description = "Represents a Schema with all associated data used for export/import operations.") +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; + +@org.eclipse.microprofile.openapi.annotations.media.Schema(type = SchemaType.OBJECT, allOf = Schema.class, description = "Represents a Schema with all associated data used for export/import operations.") public class SchemaExport extends Schema { @org.eclipse.microprofile.openapi.annotations.media.Schema(description = "Array of Labels associated with schema") diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Test.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Test.java index 0048fc271..02692116b 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Test.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Test.java @@ -1,32 +1,27 @@ package io.hyperfoil.tools.horreum.api.data; -import com.fasterxml.jackson.annotation.JsonIdentityInfo; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.ObjectIdGenerators; -import com.fasterxml.jackson.databind.JsonNode; +import java.util.Collection; + import jakarta.validation.constraints.NotNull; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -import java.util.Collection; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; -@Schema(type = SchemaType.OBJECT, allOf = ProtectedType.class, - description = "Represents a Test. Tests are typically equivalent to a particular benchmark") +@Schema(type = SchemaType.OBJECT, allOf = ProtectedType.class, description = "Represents a Test. Tests are typically equivalent to a particular benchmark") public class Test extends ProtectedType { @JsonProperty(required = true) - @Schema(description="Unique Test id", - example="101") + @Schema(description = "Unique Test id", example = "101") public Integer id; @NotNull @JsonProperty(required = true) - @Schema(description="Test name", - example="my-comprehensive-benchmark") + @Schema(description = "Test name", example = "my-comprehensive-benchmark") public String name; - @Schema(description="Name of folder that the test is stored in. Folders allow tests to be organised in the UI", - example="My Team Folder") + @Schema(description = "Name of folder that the test is stored in. Folders allow tests to be organised in the UI", example = "My Team Folder") public String folder; - @Schema(description="Description of the test", - example="Comprehensive benchmark to tests the limits of any system it is run against") + @Schema(description = "Description of the test", example = "Comprehensive benchmark to tests the limits of any system it is run against") public String description; @NotNull @@ -35,30 +30,22 @@ public class Test extends ProtectedType { @Schema(description = "Array of API tokens associated with test") public Collection tokens; - @Schema(type = SchemaType.ARRAY, implementation = String.class, - description = "List of label names that are used for determining metric to use as the time series", - example = "[ \"timestamp\" ]") + @Schema(type = SchemaType.ARRAY, implementation = String.class, description = "List of label names that are used for determining metric to use as the time series", example = "[ \"timestamp\" ]") public JsonNode timelineLabels; - @Schema(description = "Label function to modify timeline labels to a produce a value used for ordering datapoints", - example = "timestamp => timestamp") + @Schema(description = "Label function to modify timeline labels to a produce a value used for ordering datapoints", example = "timestamp => timestamp") public String timelineFunction; - @Schema(type = SchemaType.ARRAY, implementation = String.class, - description = "Array of Label names that are used to create a fingerprint ", - example = "[ \"build_tag\" ]") + @Schema(type = SchemaType.ARRAY, implementation = String.class, description = "Array of Label names that are used to create a fingerprint ", example = "[ \"build_tag\" ]") public JsonNode fingerprintLabels; - @Schema(description = "Filter function to filter out datasets that are comparable for the purpose of change detection", - example = "value => value === \"true\"") + @Schema(description = "Filter function to filter out datasets that are comparable for the purpose of change detection", example = "value => value === \"true\"") public String fingerprintFilter; - @Schema(description = "URL to external service that can be called to compare runs. This is typically an external reporting/visulization service", - example = "(ids, token) => 'http://repoting.example.com/report/specj?q=' + ids.join('&q=') + \"&token=\"+token") + @Schema(description = "URL to external service that can be called to compare runs. This is typically an external reporting/visulization service", example = "(ids, token) => 'http://repoting.example.com/report/specj?q=' + ids.join('&q=') + \"&token=\"+token") public String compareUrl; @Schema(description = "Array for transformers defined for the Test") public Collection transformers; @NotNull @JsonProperty(required = true) - @Schema(description = "Are notifications enabled for the test", - example = "true") + @Schema(description = "Are notifications enabled for the test", example = "true") public Boolean notificationsEnabled; public Test() { @@ -105,7 +92,7 @@ public String toString() { public void clearIds() { id = null; - if(tokens != null) - tokens.stream().forEach( t -> t.clearId()); + if (tokens != null) + tokens.stream().forEach(t -> t.clearId()); } } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/TestExport.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/TestExport.java index 7a6f0b228..fc63dba96 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/TestExport.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/TestExport.java @@ -1,16 +1,16 @@ package io.hyperfoil.tools.horreum.api.data; +import java.util.List; + +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.media.Schema; + import io.hyperfoil.tools.horreum.api.alerting.MissingDataRule; import io.hyperfoil.tools.horreum.api.alerting.Variable; import io.hyperfoil.tools.horreum.api.alerting.Watch; import io.hyperfoil.tools.horreum.api.data.datastore.Datastore; -import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; -import org.eclipse.microprofile.openapi.annotations.media.Schema; - -import java.util.List; -@Schema(type = SchemaType.OBJECT, allOf = Test.class, - description = "Represents a Test with all associated data used for export/import operations.") +@Schema(type = SchemaType.OBJECT, allOf = Test.class, description = "Represents a Test with all associated data used for export/import operations.") public class TestExport extends Test { @Schema(description = "Array of Variables associated with test") @@ -30,6 +30,7 @@ public class TestExport extends Test { public TestExport() { super(); } + public TestExport(Test t) { super(t); } @@ -41,34 +42,35 @@ public void update(Test newTest) { public void updateRefs() { //need to make sure the correct variables are used by experiments - if(variables != null && !variables.isEmpty()) + if (variables != null && !variables.isEmpty()) variables.forEach(variable -> variable.testId = id); - if(experiments != null && !experiments.isEmpty()) { - for(ExperimentProfile experiment : experiments) { + if (experiments != null && !experiments.isEmpty()) { + for (ExperimentProfile experiment : experiments) { experiment.testId = id; } } - if(actions != null && !actions.isEmpty()) { - for(Action action : actions) { + if (actions != null && !actions.isEmpty()) { + for (Action action : actions) { action.testId = id; } } - if(subscriptions != null) { + if (subscriptions != null) { subscriptions.testId = id; } - if(missingDataRules != null && !missingDataRules.isEmpty()) { - for(MissingDataRule rule : missingDataRules) { + if (missingDataRules != null && !missingDataRules.isEmpty()) { + for (MissingDataRule rule : missingDataRules) { rule.testId = id; } } } + public void updateExperimentsVariableId(int oldVarId, int newVarId) { - if(experiments != null && !experiments.isEmpty()) { - for(ExperimentProfile experiment : experiments) { - if(experiment.comparisons != null && !experiment.comparisons.isEmpty()) { + if (experiments != null && !experiments.isEmpty()) { + for (ExperimentProfile experiment : experiments) { + if (experiment.comparisons != null && !experiment.comparisons.isEmpty()) { experiment.comparisons.forEach(c -> { - if(c.variableId == oldVarId) + if (c.variableId == oldVarId) c.variableId = newVarId; }); } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/TestToken.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/TestToken.java index 9edf485cd..38d4c9030 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/TestToken.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/TestToken.java @@ -1,41 +1,38 @@ package io.hyperfoil.tools.horreum.api.data; -import com.fasterxml.jackson.annotation.JsonGetter; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonSetter; +import java.util.function.Function; + import jakarta.validation.constraints.NotNull; -import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; + import org.eclipse.microprofile.openapi.annotations.media.Schema; -import java.util.function.Function; +import com.fasterxml.jackson.annotation.JsonGetter; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; public class TestToken { public static final int READ = 1; public static final int MODIFY = 2; public static final int UPLOAD = 4; @JsonProperty(required = true) - @Schema(description="Unique Token id", - example="101") + @Schema(description = "Unique Token id", example = "101") public Integer id; - @Schema(description="Test ID to apply Token", - example="201") + @Schema(description = "Test ID to apply Token", example = "201") public Integer testId; @NotNull @JsonProperty(required = true) - @Schema(description="Test value", - example="094678029a2aaf9a2847502273099bb3a1b2338c2b9c618ed09aef0181666e38") + @Schema(description = "Test value", example = "094678029a2aaf9a2847502273099bb3a1b2338c2b9c618ed09aef0181666e38") private String value; @NotNull @JsonProperty(required = true) //TODO: this should map to an Access object -// @Schema( type = SchemaType.INTEGER, implementation = Access.class, -// description = "Access rights for the test. This defines the visibility of the Test in the UI", -// example = "0") + // @Schema( type = SchemaType.INTEGER, implementation = Access.class, + // description = "Access rights for the test. This defines the visibility of the Test in the UI", + // example = "0") public int permissions; @NotNull @JsonProperty(required = true) - @Schema(description="Token description", - example="my reporting service token") + @Schema(description = "Token description", example = "my reporting service token") public String description; public TestToken() { @@ -68,11 +65,11 @@ public boolean valueEquals(String value) { } public String getEncryptedValue(Function encrypt) { - return (String)encrypt.apply(this.value); + return (String) encrypt.apply(this.value); } public void decryptValue(Function decrypt) { - this.value = (String)decrypt.apply(this.value); + this.value = (String) decrypt.apply(this.value); } @Override diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Transformer.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Transformer.java index 71d738bd0..726cab19c 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Transformer.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/Transformer.java @@ -1,46 +1,43 @@ package io.hyperfoil.tools.horreum.api.data; -import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Collection; + import jakarta.validation.constraints.NotNull; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -import java.util.Collection; +import com.fasterxml.jackson.annotation.JsonProperty; -@Schema(type = SchemaType.OBJECT, allOf = ProtectedType.class, -description = "A transformer extracts labals and applies a Function to convert a Run into one or more Datasets") +@Schema(type = SchemaType.OBJECT, allOf = ProtectedType.class, description = "A transformer extracts labals and applies a Function to convert a Run into one or more Datasets") public class Transformer extends ProtectedType { @JsonProperty(required = true) - @Schema(description="Unique Transformer id", - example="101") + @Schema(description = "Unique Transformer id", example = "101") public Integer id; @NotNull @JsonProperty(required = true) - @Schema(description="Transformer name", - example="normalize-techempower-result") + @Schema(description = "Transformer name", example = "normalize-techempower-result") public String name; - @Schema(description="Transformer description", - example="Normalizers a techempower output file to separate each framework into a dataset and normalize the JSON structure") + @Schema(description = "Transformer description", example = "Normalizers a techempower output file to separate each framework into a dataset and normalize the JSON structure") public String description; - @Schema(description="The schema associated with the calculated Datasets. Where a transformer creates a new JSON object with a new structure, this Schema is used to extafct values from the new Dataset JSON document", - example="uri:normalized-techempower:0.1") + @Schema(description = "The schema associated with the calculated Datasets. Where a transformer creates a new JSON object with a new structure, this Schema is used to extafct values from the new Dataset JSON document", example = "uri:normalized-techempower:0.1") public String targetSchemaUri; @NotNull @JsonProperty(required = true) - @Schema(description="A collection of extractors to extract JSON values to create new Dataset JSON document") + @Schema(description = "A collection of extractors to extract JSON values to create new Dataset JSON document") public Collection extractors; public String function; @NotNull @JsonProperty(value = "schemaId", required = true) - @Schema(description="Schema ID that the transform is registered against", example = "101") + @Schema(description = "Schema ID that the transform is registered against", example = "101") public Integer schemaId; @JsonProperty(value = "schemaUri", required = true) - @Schema(description="Schema Uri that the transform is registered against", example = "urn:techempower:0.1") + @Schema(description = "Schema Uri that the transform is registered against", example = "urn:techempower:0.1") public String schemaUri; @JsonProperty(value = "schemaName", required = true) - @Schema(description="Schema name that the transform is registered against", example = "techempower") + @Schema(description = "Schema name that the transform is registered against", example = "techempower") public String schemaName; public Transformer() { diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ValidationError.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ValidationError.java index ce7d66df4..4186e453a 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ValidationError.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ValidationError.java @@ -1,12 +1,10 @@ package io.hyperfoil.tools.horreum.api.data; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; import jakarta.validation.constraints.NotNull; + import org.eclipse.microprofile.openapi.annotations.media.Schema; -import java.util.Map; +import com.fasterxml.jackson.annotation.JsonProperty; public class ValidationError { @Schema(description = "Schema ID that Validation Error relates to", example = "101") @@ -18,17 +16,17 @@ public class ValidationError { public ValidationError() { } - @JsonProperty( value = "schemaId", required = true ) + @JsonProperty(value = "schemaId", required = true) public void setSchema(int id) { this.schemaId = id; } - @JsonProperty( value = "schemaId", required = true ) + @JsonProperty(value = "schemaId", required = true) public Integer getSchemaId() { return schemaId; } - public static class ErrorDetails{ + public static class ErrorDetails { @NotNull @JsonProperty(required = true) @Schema(description = "Validation Error type") diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/View.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/View.java index 85155ed14..e3f2eee76 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/View.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/View.java @@ -1,9 +1,10 @@ package io.hyperfoil.tools.horreum.api.data; -import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; + import jakarta.validation.constraints.NotNull; -import java.util.List; +import com.fasterxml.jackson.annotation.JsonProperty; public class View { @JsonProperty(required = true) @@ -39,7 +40,9 @@ public String toString() { public void clearId() { id = null; - if(components != null) - components.stream().forEach( c -> {c.id = null;}); + if (components != null) + components.stream().forEach(c -> { + c.id = null; + }); } } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ViewComponent.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ViewComponent.java index 2bf11d47e..54d5f0c5b 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ViewComponent.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/ViewComponent.java @@ -1,13 +1,14 @@ package io.hyperfoil.tools.horreum.api.data; +import java.util.Objects; + +import jakarta.validation.constraints.NotNull; + import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import jakarta.validation.constraints.NotNull; - -import java.util.Objects; public class ViewComponent { @JsonProperty(required = true) @@ -42,7 +43,7 @@ public boolean equals(Object o) { if (this == o) { return true; } else if (o != null && this.getClass() == o.getClass()) { - ViewComponent that = (ViewComponent)o; + ViewComponent that = (ViewComponent) o; return this.headerOrder == that.headerOrder && Objects.equals(this.id, that.id) && Objects.equals(this.headerName, that.headerName) && diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/changeDetection/ChangeDetectionModelType.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/changeDetection/ChangeDetectionModelType.java index 789d89d40..4508c2062 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/changeDetection/ChangeDetectionModelType.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/changeDetection/ChangeDetectionModelType.java @@ -1,20 +1,25 @@ package io.hyperfoil.tools.horreum.api.data.changeDetection; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.core.type.TypeReference; -import io.hyperfoil.tools.horreum.api.data.datastore.BaseChangeDetectionConfig; +import java.util.Arrays; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -import java.util.Arrays; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.core.type.TypeReference; -@Schema(type = SchemaType.STRING, required = true, - description = "Type of Change Detection Model") +import io.hyperfoil.tools.horreum.api.data.datastore.BaseChangeDetectionConfig; + +@Schema(type = SchemaType.STRING, required = true, description = "Type of Change Detection Model") public enum ChangeDetectionModelType { - FIXED_THRESHOLD(names.FIXED_THRESHOLD, new TypeReference() {}), - RELATIVE_DIFFERENCE (names.RELATIVE_DIFFERENCE, new TypeReference() {}), - EDIVISIVE(names.EDIVISIVE, new TypeReference() {}); + FIXED_THRESHOLD(names.FIXED_THRESHOLD, new TypeReference() { + }), + RELATIVE_DIFFERENCE(names.RELATIVE_DIFFERENCE, new TypeReference() { + }), + EDIVISIVE(names.EDIVISIVE, new TypeReference() { + }); + private static final ChangeDetectionModelType[] VALUES = values(); private final String name; @@ -25,13 +30,14 @@ private ChangeDetectionModelType(String na this.name = name; } - public TypeReference getTypeReference(){ + public TypeReference getTypeReference() { return (TypeReference) typeReference; } @JsonCreator public static ChangeDetectionModelType fromString(String str) { - return Arrays.stream(VALUES).filter(v -> v.name.equals(str)).findAny().orElseThrow(() -> new IllegalArgumentException("Unknown model: " + str)); + return Arrays.stream(VALUES).filter(v -> v.name.equals(str)).findAny() + .orElseThrow(() -> new IllegalArgumentException("Unknown model: " + str)); } public static class names { diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/changeDetection/EDivisiveDetectionConfig.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/changeDetection/EDivisiveDetectionConfig.java index 784813ac6..7356ad039 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/changeDetection/EDivisiveDetectionConfig.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/changeDetection/EDivisiveDetectionConfig.java @@ -1,11 +1,12 @@ package io.hyperfoil.tools.horreum.api.data.changeDetection; -import io.hyperfoil.tools.horreum.api.data.datastore.BaseChangeDetectionConfig; import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; +import io.hyperfoil.tools.horreum.api.data.datastore.BaseChangeDetectionConfig; + public class EDivisiveDetectionConfig extends BaseChangeDetectionConfig { - @Schema(type = SchemaType.STRING, required = true, enumeration = {ChangeDetectionModelType.names.EDIVISIVE}) + @Schema(type = SchemaType.STRING, required = true, enumeration = { ChangeDetectionModelType.names.EDIVISIVE }) public String model; } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/changeDetection/FixThresholdConfig.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/changeDetection/FixThresholdConfig.java index 67e78be31..73f31e5c5 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/changeDetection/FixThresholdConfig.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/changeDetection/FixThresholdConfig.java @@ -7,14 +7,11 @@ * Concrete configuration type for io.hyperfoil.tools.horreum.changedetection.FixedThresholdModel */ public class FixThresholdConfig { - @Schema(type = SchemaType.INTEGER, required = true, example = "95", - description = "Threshold Value") + @Schema(type = SchemaType.INTEGER, required = true, example = "95", description = "Threshold Value") public Double value; - @Schema(type = SchemaType.BOOLEAN, required = true, example = "true", - description = "Threshold enabled/disabled") + @Schema(type = SchemaType.BOOLEAN, required = true, example = "true", description = "Threshold enabled/disabled") public Boolean enabled; - @Schema(type = SchemaType.BOOLEAN, required = true, example = "false", - description = "Is threshold inclusive of defined value?") + @Schema(type = SchemaType.BOOLEAN, required = true, example = "false", description = "Is threshold inclusive of defined value?") public Boolean inclusive; } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/changeDetection/FixedThresholdDetectionConfig.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/changeDetection/FixedThresholdDetectionConfig.java index 6f59c4e0b..a5e6bce88 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/changeDetection/FixedThresholdDetectionConfig.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/changeDetection/FixedThresholdDetectionConfig.java @@ -1,17 +1,16 @@ package io.hyperfoil.tools.horreum.api.data.changeDetection; -import io.hyperfoil.tools.horreum.api.data.datastore.BaseChangeDetectionConfig; import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; +import io.hyperfoil.tools.horreum.api.data.datastore.BaseChangeDetectionConfig; + public class FixedThresholdDetectionConfig extends BaseChangeDetectionConfig { @Schema(type = SchemaType.STRING, required = true, enumeration = { ChangeDetectionModelType.names.FIXED_THRESHOLD }) public String model; - @Schema(type = SchemaType.OBJECT, required = true, - description = "Lower bound for acceptable datapoint values") + @Schema(type = SchemaType.OBJECT, required = true, description = "Lower bound for acceptable datapoint values") public FixThresholdConfig min; - @Schema(type = SchemaType.OBJECT, required = true, - description = "Upper bound for acceptable datapoint values") + @Schema(type = SchemaType.OBJECT, required = true, description = "Upper bound for acceptable datapoint values") public FixThresholdConfig max; } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/changeDetection/RelativeDifferenceDetectionConfig.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/changeDetection/RelativeDifferenceDetectionConfig.java index 1e493c58d..753abbe0f 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/changeDetection/RelativeDifferenceDetectionConfig.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/changeDetection/RelativeDifferenceDetectionConfig.java @@ -1,26 +1,23 @@ package io.hyperfoil.tools.horreum.api.data.changeDetection; -import io.hyperfoil.tools.horreum.api.data.datastore.BaseChangeDetectionConfig; import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; +import io.hyperfoil.tools.horreum.api.data.datastore.BaseChangeDetectionConfig; + /* * Concrete configuration type for io.hyperfoil.tools.horreum.changedetection.RelativeDifferenceChangeDetectionModel */ -public class RelativeDifferenceDetectionConfig extends BaseChangeDetectionConfig { - @Schema(type = SchemaType.STRING, required = true, enumeration = { ChangeDetectionModelType.names.RELATIVE_DIFFERENCE } ) +public class RelativeDifferenceDetectionConfig extends BaseChangeDetectionConfig { + @Schema(type = SchemaType.STRING, required = true, enumeration = { ChangeDetectionModelType.names.RELATIVE_DIFFERENCE }) public String model; - @Schema(type = SchemaType.STRING, required = true, example = "mean", - description = "Relative Difference Detection filter") + @Schema(type = SchemaType.STRING, required = true, example = "mean", description = "Relative Difference Detection filter") public String filter; - @Schema(type = SchemaType.INTEGER, required = true, example = "5", - description = "Number of most recent datapoints used for aggregating the value for comparison.") + @Schema(type = SchemaType.INTEGER, required = true, example = "5", description = "Number of most recent datapoints used for aggregating the value for comparison.") public Integer window; - @Schema(type = SchemaType.NUMBER, required = true, example = "0.2", - description = "Maximum difference between the aggregated value of last datapoints and the mean of preceding values.") + @Schema(type = SchemaType.NUMBER, required = true, example = "0.2", description = "Maximum difference between the aggregated value of last datapoints and the mean of preceding values.") public Double threshold; - @Schema(type = SchemaType.INTEGER, required = true, example = "5", - description = "Minimal number of preceding datapoints") + @Schema(type = SchemaType.INTEGER, required = true, example = "5", description = "Minimal number of preceding datapoints") public Integer minPrevious; } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/BaseChangeDetectionConfig.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/BaseChangeDetectionConfig.java index 6bf039076..858b30b95 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/BaseChangeDetectionConfig.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/BaseChangeDetectionConfig.java @@ -5,8 +5,7 @@ public abstract class BaseChangeDetectionConfig { - @Schema(type = SchemaType.BOOLEAN, required = true, - description = "Built In") + @Schema(type = SchemaType.BOOLEAN, required = true, description = "Built In") public Boolean builtIn = true; public BaseChangeDetectionConfig() { diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/BaseDatastoreConfig.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/BaseDatastoreConfig.java index 1c75f54ba..929e92ebf 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/BaseDatastoreConfig.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/BaseDatastoreConfig.java @@ -5,8 +5,7 @@ public abstract class BaseDatastoreConfig { - @Schema(type = SchemaType.BOOLEAN, required = true, - description = "Built In") + @Schema(type = SchemaType.BOOLEAN, required = true, description = "Built In") public Boolean builtIn = true; public BaseDatastoreConfig() { diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/Datastore.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/Datastore.java index ae646a634..4f63bb9c6 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/Datastore.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/Datastore.java @@ -1,44 +1,42 @@ package io.hyperfoil.tools.horreum.api.data.datastore; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.node.ObjectNode; -import io.hyperfoil.tools.horreum.api.data.ProtectedType; import jakarta.validation.constraints.NotNull; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -@Schema(type = SchemaType.OBJECT, required = true, - description = "Type of backend datastore") +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import io.hyperfoil.tools.horreum.api.data.ProtectedType; + +@Schema(type = SchemaType.OBJECT, required = true, description = "Type of backend datastore") public class Datastore extends ProtectedType { @JsonProperty(required = true) - @Schema(description="Unique Datastore id", - example="101") + @Schema(description = "Unique Datastore id", example = "101") public Integer id; @NotNull @JsonProperty(required = true) - @Schema(description="Name of the datastore, used to identify the datastore in the Test definition", - example="Perf Elasticsearch") + @Schema(description = "Name of the datastore, used to identify the datastore in the Test definition", example = "Perf Elasticsearch") public String name; @NotNull @JsonProperty(required = true) - @Schema(description="Is this a built-in datastore? Built-in datastores cannot be deleted or modified", - example="false") + @Schema(description = "Is this a built-in datastore? Built-in datastores cannot be deleted or modified", example = "false") public Boolean builtIn; @NotNull - @JsonProperty( required = true ) - @Schema(type = SchemaType.OBJECT, - oneOf = { - ElasticsearchDatastoreConfig.class, - PostgresDatastoreConfig.class + @JsonProperty(required = true) + @Schema(type = SchemaType.OBJECT, oneOf = { + ElasticsearchDatastoreConfig.class, + PostgresDatastoreConfig.class }) public ObjectNode config; @NotNull @JsonProperty(required = true) - @Schema( type = SchemaType.STRING, implementation = DatastoreType.class, example = "ELASTICSEARCH") + @Schema(type = SchemaType.STRING, implementation = DatastoreType.class, example = "ELASTICSEARCH") public DatastoreType type; public void pruneSecrets() { diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/DatastoreType.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/DatastoreType.java index 4776f9fd7..b967e4a5f 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/DatastoreType.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/DatastoreType.java @@ -1,16 +1,18 @@ package io.hyperfoil.tools.horreum.api.data.datastore; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -@Schema(type = SchemaType.STRING, required = true, - description = "Type of backend datastore") +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.core.type.TypeReference; + +@Schema(type = SchemaType.STRING, required = true, description = "Type of backend datastore") public enum DatastoreType { - POSTGRES("POSTGRES", new TypeReference() {}), - ELASTICSEARCH ("ELASTICSEARCH", new TypeReference() {}); + POSTGRES("POSTGRES", new TypeReference() { + }), + ELASTICSEARCH("ELASTICSEARCH", new TypeReference() { + }); + private static final DatastoreType[] VALUES = values(); private final String name; @@ -21,7 +23,7 @@ private DatastoreType(String name, TypeReference this.name = name; } - public TypeReference getTypeReference(){ + public TypeReference getTypeReference() { return (TypeReference) typeReference; } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/ElasticsearchDatastoreConfig.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/ElasticsearchDatastoreConfig.java index 440968646..6544e163f 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/ElasticsearchDatastoreConfig.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/ElasticsearchDatastoreConfig.java @@ -1,37 +1,31 @@ package io.hyperfoil.tools.horreum.api.data.datastore; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -@Schema(type = SchemaType.OBJECT, required = true, - description = "Type of backend datastore") +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +@Schema(type = SchemaType.OBJECT, required = true, description = "Type of backend datastore") public class ElasticsearchDatastoreConfig extends BaseDatastoreConfig { public ElasticsearchDatastoreConfig() { super(false); } - @Schema(type = SchemaType.STRING, - description = "Elasticsearch API KEY") + @Schema(type = SchemaType.STRING, description = "Elasticsearch API KEY") public String apiKey; - @Schema(type = SchemaType.STRING, required = true, - description = "Elasticsearch url") + @Schema(type = SchemaType.STRING, required = true, description = "Elasticsearch url") public String url; - - @Schema(type = SchemaType.STRING, - description = "Elasticsearch username") + @Schema(type = SchemaType.STRING, description = "Elasticsearch username") public String username; - @Schema(type = SchemaType.STRING, - description = "Elasticsearch password") + @Schema(type = SchemaType.STRING, description = "Elasticsearch password") @JsonIgnore public String password; - @JsonProperty("password") public void setSecrets(String password) { this.password = password; @@ -45,18 +39,18 @@ public String getMaskedSecrets() { return null; } } + @Override public String validateConfig() { - if ( "".equals(apiKey) && ( "".equals(username) || "".equals(password)) ) { + if ("".equals(apiKey) && ("".equals(username) || "".equals(password))) { return "Either apiKey or username and password must be set"; } - if( !"".equals(apiKey) && !( "".equals(username) || "".equals(password) ) ) { + if (!"".equals(apiKey) && !("".equals(username) || "".equals(password))) { return "Only apiKey or username and password can be set"; } return null; } - } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/PostgresDatastoreConfig.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/PostgresDatastoreConfig.java index f023fdfb4..2082f764d 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/PostgresDatastoreConfig.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/data/datastore/PostgresDatastoreConfig.java @@ -1,11 +1,9 @@ package io.hyperfoil.tools.horreum.api.data.datastore; - import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -@Schema(type = SchemaType.OBJECT, required = true, - description = "Built in backend datastore") +@Schema(type = SchemaType.OBJECT, required = true, description = "Built in backend datastore") public class PostgresDatastoreConfig extends BaseDatastoreConfig { @Override diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/ActionService.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/ActionService.java index 12770fe23..ae1781a73 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/ActionService.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/ActionService.java @@ -13,53 +13,54 @@ import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; +import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; +import org.eclipse.microprofile.openapi.annotations.tags.Tag; + import io.hyperfoil.tools.horreum.api.SortDirection; import io.hyperfoil.tools.horreum.api.data.Action; import io.hyperfoil.tools.horreum.api.data.AllowedSite; -import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; -import org.eclipse.microprofile.openapi.annotations.tags.Tag; @Path("/api/action") -@Consumes({ MediaType.APPLICATION_JSON}) +@Consumes({ MediaType.APPLICATION_JSON }) @Produces(MediaType.APPLICATION_JSON) @Tag(name = "action", description = "Manage Actions") public interface ActionService { - @POST - Action add(Action action); + @POST + Action add(Action action); - @GET - @Path("{id}") - Action get(@PathParam("id") int id); + @GET + @Path("{id}") + Action get(@PathParam("id") int id); - @DELETE - @Path("{id}") - void delete(@PathParam("id") int id); + @DELETE + @Path("{id}") + void delete(@PathParam("id") int id); - @POST - @Path("update") - Action update(@RequestBody(required = true) Action action); + @POST + @Path("update") + Action update(@RequestBody(required = true) Action action); - @GET - @Path("list") - List list(@QueryParam("limit") Integer limit, - @QueryParam("page") Integer page, - @QueryParam("sort") @DefaultValue("id") String sort, - @QueryParam("direction") @DefaultValue("Ascending") SortDirection direction); + @GET + @Path("list") + List list(@QueryParam("limit") Integer limit, + @QueryParam("page") Integer page, + @QueryParam("sort") @DefaultValue("id") String sort, + @QueryParam("direction") @DefaultValue("Ascending") SortDirection direction); - @GET - @Path("test/{id}") - List getTestActions(@PathParam("id") int testId); + @GET + @Path("test/{id}") + List getTestActions(@PathParam("id") int testId); - @GET - @Path("allowedSites") - List allowedSites(); + @GET + @Path("allowedSites") + List allowedSites(); - @Consumes("text/plain") - @POST - @Path("allowedSites") - AllowedSite addSite(@RequestBody(required = true) String prefix); + @Consumes("text/plain") + @POST + @Path("allowedSites") + AllowedSite addSite(@RequestBody(required = true) String prefix); - @DELETE - @Path("allowedSites/{id}") - void deleteSite(@PathParam("id") long id); + @DELETE + @Path("allowedSites/{id}") + void deleteSite(@PathParam("id") long id); } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/AlertingService.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/AlertingService.java index 0da0b195a..6ba5a15ad 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/AlertingService.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/AlertingService.java @@ -15,183 +15,186 @@ import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; -import io.hyperfoil.tools.horreum.api.data.ConditionConfig; -import io.hyperfoil.tools.horreum.api.alerting.*; -import io.hyperfoil.tools.horreum.api.data.Dataset; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; +import org.eclipse.microprofile.openapi.annotations.tags.Tag; import com.fasterxml.jackson.annotation.JsonProperty; -import org.eclipse.microprofile.openapi.annotations.tags.Tag; -@Consumes({ MediaType.APPLICATION_JSON}) +import io.hyperfoil.tools.horreum.api.alerting.*; +import io.hyperfoil.tools.horreum.api.data.ConditionConfig; +import io.hyperfoil.tools.horreum.api.data.Dataset; + +@Consumes({ MediaType.APPLICATION_JSON }) @Produces(MediaType.APPLICATION_JSON) @Path("/api/alerting") @Tag(name = "alerting", description = "Manage alerts") public interface AlertingService { - @GET - @Path("variables") - List variables(@QueryParam("test") Integer testId); - - @POST - @Path("variables") - void updateVariables(@Parameter(required = true) @QueryParam("test") int testId, - @RequestBody(required = true) List variables); - - @GET - @Path("dashboard") - DashboardInfo dashboard(@Parameter(required = true) @QueryParam("test") int testId, - @QueryParam("fingerprint") String fingerprint); - - @GET - @Path("changes") - List changes(@Parameter(required = true) @QueryParam("var") int varId, - @QueryParam("fingerprint") String fingerprint); - - @POST - @Path("change/{id}") - void updateChange(@Parameter(required = true) @PathParam("id") int id, - @RequestBody(required = true) Change change); - - @DELETE - @Path("change/{id}") - void deleteChange(@PathParam("id") int id); - - @POST - @Path("recalculate") - void recalculateDatapoints(@Parameter(required = true) @QueryParam("test") int testId, - @QueryParam("notify") boolean notify, - @QueryParam("debug") boolean debug, - @QueryParam("clear") Boolean clearDatapoints, - @QueryParam("from") Long from, @QueryParam("to") Long to); - - @GET - @Path("recalculate") - DatapointRecalculationStatus getRecalculationStatus(@Parameter(required = true) @QueryParam("test") int testId); - - @POST - @Path("/datapoint/last") - List findLastDatapoints(@RequestBody(required = true) LastDatapointsParams params); - - @POST - @Path("/expectRun") - void expectRun(@Parameter(required = true) @QueryParam("test") String test, - @Parameter(required = true) @QueryParam("timeout") Long timeoutSeconds, - @QueryParam("expectedby") String expectedBy, - @QueryParam("backlink") String backlink); - - // Test mode only - @GET - @Path("/expectations") - List expectations(); - - @POST - @Path("/changeDetection") - void updateChangeDetection(@QueryParam("testId") @Parameter(required = true) int testId, @RequestBody(required = true) AlertingService.ChangeDetectionUpdate update); - - @GET - @Path("/changeDetectionModels") - List changeDetectionModels(); - - @GET - @Path("/defaultChangeDetectionConfigs") - List defaultChangeDetectionConfigs(); - - @GET - @Path("/missingdatarule") - List missingDataRules(@Parameter(required = true) @QueryParam("testId") int testId); - - @POST - @Path("/missingdatarule") - int updateMissingDataRule( - @Parameter(required = true) @QueryParam("testId") int testId, - @RequestBody(required = true) MissingDataRule rule); - - @DELETE - @Path("/missingdatarule/{id}") - void deleteMissingDataRule(@PathParam("id") int id); - - class DashboardInfo { - @JsonProperty(required = true) - public int testId; - @NotNull - public String uid; - @NotNull - public String url; - @NotNull - public List panels = new ArrayList<>(); - } - - class PanelInfo { - @NotNull - public String name; - @NotNull - public List variables; - - public PanelInfo(String name, List variables) { - this.name = name; - this.variables = variables; - } - } - - class AccessorInfo { - public final String schema; - public final String jsonpath; - - public AccessorInfo(String schema, String jsonpath) { - this.schema = schema; - this.jsonpath = jsonpath; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AccessorInfo that = (AccessorInfo) o; - return schema.equals(that.schema); - } - - @Override - public int hashCode() { - return schema.hashCode(); - } - } - - class DatapointRecalculationStatus { - @JsonProperty(required = true) - public int percentage; - @JsonProperty(required = true) - public boolean done; - public Integer totalDatasets; - public Integer errors; - @NotNull - public Collection datasetsWithoutValue; - } - - - class DatapointLastTimestamp { - @JsonProperty(required = true) - public int variable; - @NotNull - public Number timestamp; - - public DatapointLastTimestamp(int variable, Number timestamp) { - this.variable = variable; - this.timestamp = timestamp; - } - } - - class LastDatapointsParams { - @NotNull - public int[] variables; - @NotNull - public String fingerprint; - } - - class ChangeDetectionUpdate { - public List timelineLabels; - public String timelineFunction; - public List fingerprintLabels; - public String fingerprintFilter; - } + @GET + @Path("variables") + List variables(@QueryParam("test") Integer testId); + + @POST + @Path("variables") + void updateVariables(@Parameter(required = true) @QueryParam("test") int testId, + @RequestBody(required = true) List variables); + + @GET + @Path("dashboard") + DashboardInfo dashboard(@Parameter(required = true) @QueryParam("test") int testId, + @QueryParam("fingerprint") String fingerprint); + + @GET + @Path("changes") + List changes(@Parameter(required = true) @QueryParam("var") int varId, + @QueryParam("fingerprint") String fingerprint); + + @POST + @Path("change/{id}") + void updateChange(@Parameter(required = true) @PathParam("id") int id, + @RequestBody(required = true) Change change); + + @DELETE + @Path("change/{id}") + void deleteChange(@PathParam("id") int id); + + @POST + @Path("recalculate") + void recalculateDatapoints(@Parameter(required = true) @QueryParam("test") int testId, + @QueryParam("notify") boolean notify, + @QueryParam("debug") boolean debug, + @QueryParam("clear") Boolean clearDatapoints, + @QueryParam("from") Long from, @QueryParam("to") Long to); + + @GET + @Path("recalculate") + DatapointRecalculationStatus getRecalculationStatus(@Parameter(required = true) @QueryParam("test") int testId); + + @POST + @Path("/datapoint/last") + List findLastDatapoints(@RequestBody(required = true) LastDatapointsParams params); + + @POST + @Path("/expectRun") + void expectRun(@Parameter(required = true) @QueryParam("test") String test, + @Parameter(required = true) @QueryParam("timeout") Long timeoutSeconds, + @QueryParam("expectedby") String expectedBy, + @QueryParam("backlink") String backlink); + + // Test mode only + @GET + @Path("/expectations") + List expectations(); + + @POST + @Path("/changeDetection") + void updateChangeDetection(@QueryParam("testId") @Parameter(required = true) int testId, + @RequestBody(required = true) AlertingService.ChangeDetectionUpdate update); + + @GET + @Path("/changeDetectionModels") + List changeDetectionModels(); + + @GET + @Path("/defaultChangeDetectionConfigs") + List defaultChangeDetectionConfigs(); + + @GET + @Path("/missingdatarule") + List missingDataRules(@Parameter(required = true) @QueryParam("testId") int testId); + + @POST + @Path("/missingdatarule") + int updateMissingDataRule( + @Parameter(required = true) @QueryParam("testId") int testId, + @RequestBody(required = true) MissingDataRule rule); + + @DELETE + @Path("/missingdatarule/{id}") + void deleteMissingDataRule(@PathParam("id") int id); + + class DashboardInfo { + @JsonProperty(required = true) + public int testId; + @NotNull + public String uid; + @NotNull + public String url; + @NotNull + public List panels = new ArrayList<>(); + } + + class PanelInfo { + @NotNull + public String name; + @NotNull + public List variables; + + public PanelInfo(String name, List variables) { + this.name = name; + this.variables = variables; + } + } + + class AccessorInfo { + public final String schema; + public final String jsonpath; + + public AccessorInfo(String schema, String jsonpath) { + this.schema = schema; + this.jsonpath = jsonpath; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + AccessorInfo that = (AccessorInfo) o; + return schema.equals(that.schema); + } + + @Override + public int hashCode() { + return schema.hashCode(); + } + } + + class DatapointRecalculationStatus { + @JsonProperty(required = true) + public int percentage; + @JsonProperty(required = true) + public boolean done; + public Integer totalDatasets; + public Integer errors; + @NotNull + public Collection datasetsWithoutValue; + } + + class DatapointLastTimestamp { + @JsonProperty(required = true) + public int variable; + @NotNull + public Number timestamp; + + public DatapointLastTimestamp(int variable, Number timestamp) { + this.variable = variable; + this.timestamp = timestamp; + } + } + + class LastDatapointsParams { + @NotNull + public int[] variables; + @NotNull + public String fingerprint; + } + + class ChangeDetectionUpdate { + public List timelineLabels; + public String timelineFunction; + public List fingerprintLabels; + public String fingerprintFilter; + } } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/BannerService.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/BannerService.java index 3a9395fde..e22ed04ba 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/BannerService.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/BannerService.java @@ -7,19 +7,20 @@ import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; -import io.hyperfoil.tools.horreum.api.data.Banner; import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; import org.eclipse.microprofile.openapi.annotations.tags.Tag; +import io.hyperfoil.tools.horreum.api.data.Banner; + @Path("/api/banner") -@Consumes({ MediaType.APPLICATION_JSON}) +@Consumes({ MediaType.APPLICATION_JSON }) @Produces(MediaType.APPLICATION_JSON) @Tag(name = "banner", description = "Manage banner") public interface BannerService { - @POST - void set(@RequestBody(required = true) Banner banner); + @POST + void set(@RequestBody(required = true) Banner banner); - @GET - Banner get(); + @GET + Banner get(); } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/ChangesService.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/ChangesService.java index 6b1a0ecf5..742fb8471 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/ChangesService.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/ChangesService.java @@ -11,11 +11,11 @@ import org.eclipse.microprofile.openapi.annotations.Operation; import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; +import org.eclipse.microprofile.openapi.annotations.tags.Tag; import com.fasterxml.jackson.annotation.JsonProperty; import io.hyperfoil.tools.horreum.api.changes.Target; -import org.eclipse.microprofile.openapi.annotations.tags.Tag; @Path("/api/changes") @Consumes(MediaType.APPLICATION_JSON) @@ -23,90 +23,91 @@ @Tag(name = "changes", description = "Manage changes") public interface ChangesService { - - @GET - @Path("/") - default Response healthcheck() { - return Response.ok().build(); - } - @POST - @Path("/search") - String[] search(@RequestBody(required = true) Target query); - - @POST - @Path("/query") - List query(@RequestBody(required = true) Query query); - - @Operation(hidden = true) - @OPTIONS - @Path("/annotations") - Response annotations(@HeaderParam("Origin") String origin); - - @POST - @Path("/annotations") - List annotations(@RequestBody(required = true) AnnotationsQuery query); - - class Query { - @NotNull - public Range range; - @NotNull - public List targets; - } - - class Range { - @NotNull - public Instant from; - @NotNull - public Instant to; - // custom field used by UI to display lines coming into view and out of that - public boolean oneBeforeAndAfter; - } - - class TimeseriesTarget { - @NotNull - public String target; - @NotNull - public List datapoints = new ArrayList<>(); - @JsonProperty(required = true) - public int variableId; - } - - class AnnotationsQuery { - public Range range; - public AnnotationQuery annotation; - } - - class AnnotationQuery { - public String name; - public String datasource; - public String iconColor; - public boolean enable; - public String query; - } - - class AnnotationDefinition { - public String title; - public String text; - public boolean isRegion; - public long time; - public long timeEnd; - public String[] tags; - public int changeId; - public int variableId; - public int runId; - public int datasetOrdinal; - - public AnnotationDefinition(String title, String text, boolean isRegion, long time, long timeEnd, String[] tags, int changeId, int variableId, int runId, int datasetOrdinal) { - this.title = title; - this.text = text; - this.isRegion = isRegion; - this.time = time; - this.timeEnd = timeEnd; - this.tags = tags; - this.changeId = changeId; - this.variableId = variableId; - this.runId = runId; - this.datasetOrdinal = datasetOrdinal; - } - } + @GET + @Path("/") + default Response healthcheck() { + return Response.ok().build(); + } + + @POST + @Path("/search") + String[] search(@RequestBody(required = true) Target query); + + @POST + @Path("/query") + List query(@RequestBody(required = true) Query query); + + @Operation(hidden = true) + @OPTIONS + @Path("/annotations") + Response annotations(@HeaderParam("Origin") String origin); + + @POST + @Path("/annotations") + List annotations(@RequestBody(required = true) AnnotationsQuery query); + + class Query { + @NotNull + public Range range; + @NotNull + public List targets; + } + + class Range { + @NotNull + public Instant from; + @NotNull + public Instant to; + // custom field used by UI to display lines coming into view and out of that + public boolean oneBeforeAndAfter; + } + + class TimeseriesTarget { + @NotNull + public String target; + @NotNull + public List datapoints = new ArrayList<>(); + @JsonProperty(required = true) + public int variableId; + } + + class AnnotationsQuery { + public Range range; + public AnnotationQuery annotation; + } + + class AnnotationQuery { + public String name; + public String datasource; + public String iconColor; + public boolean enable; + public String query; + } + + class AnnotationDefinition { + public String title; + public String text; + public boolean isRegion; + public long time; + public long timeEnd; + public String[] tags; + public int changeId; + public int variableId; + public int runId; + public int datasetOrdinal; + + public AnnotationDefinition(String title, String text, boolean isRegion, long time, long timeEnd, String[] tags, + int changeId, int variableId, int runId, int datasetOrdinal) { + this.title = title; + this.text = text; + this.isRegion = isRegion; + this.time = time; + this.timeEnd = timeEnd; + this.tags = tags; + this.changeId = changeId; + this.variableId = variableId; + this.runId = runId; + this.datasetOrdinal = datasetOrdinal; + } + } } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/LogService.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/LogService.java index d2c35d3ab..d8e178947 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/LogService.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/LogService.java @@ -11,75 +11,76 @@ import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; -import io.hyperfoil.tools.horreum.api.data.ActionLog; +import org.eclipse.microprofile.openapi.annotations.tags.Tag; + import io.hyperfoil.tools.horreum.api.alerting.DatasetLog; import io.hyperfoil.tools.horreum.api.alerting.TransformationLog; -import org.eclipse.microprofile.openapi.annotations.tags.Tag; +import io.hyperfoil.tools.horreum.api.data.ActionLog; @Produces(MediaType.APPLICATION_JSON) @Path("/api/log") @Tag(name = "log", description = "Manage processing logs") public interface LogService { - @GET - @Path("dataset/{source}/{testId}") - List getDatasetLog(@PathParam("source") String source, - @PathParam("testId") int testId, - @QueryParam("level") @DefaultValue("1") int level, - @QueryParam("datasetId") Integer datasetId, - @QueryParam("page") Integer page, - @QueryParam("limit") Integer limit); + @GET + @Path("dataset/{source}/{testId}") + List getDatasetLog(@PathParam("source") String source, + @PathParam("testId") int testId, + @QueryParam("level") @DefaultValue("1") int level, + @QueryParam("datasetId") Integer datasetId, + @QueryParam("page") Integer page, + @QueryParam("limit") Integer limit); - @GET - @Path("dataset/{source}/{testId}/count") - long getDatasetLogCount(@PathParam("source") String source, - @PathParam("testId") int testId, - @QueryParam("level") @DefaultValue("1") int level, - @QueryParam("datasetId") Integer datasetId); + @GET + @Path("dataset/{source}/{testId}/count") + long getDatasetLogCount(@PathParam("source") String source, + @PathParam("testId") int testId, + @QueryParam("level") @DefaultValue("1") int level, + @QueryParam("datasetId") Integer datasetId); - @DELETE - @Path("dataset/{source}/{testId}") - void deleteDatasetLogs(@PathParam("source") String source, - @PathParam("testId") int testId, - @QueryParam("datasetId") Integer datasetId, - @QueryParam("from") Long from, - @QueryParam("to") Long to); + @DELETE + @Path("dataset/{source}/{testId}") + void deleteDatasetLogs(@PathParam("source") String source, + @PathParam("testId") int testId, + @QueryParam("datasetId") Integer datasetId, + @QueryParam("from") Long from, + @QueryParam("to") Long to); - @GET - @Path("transformation/{testId}") - List getTransformationLog(@PathParam("testId") int testId, - @QueryParam("level") @DefaultValue("1") int level, - @QueryParam("runId") Integer runId, - @QueryParam("page") Integer page, - @QueryParam("limit") Integer limit); + @GET + @Path("transformation/{testId}") + List getTransformationLog(@PathParam("testId") int testId, + @QueryParam("level") @DefaultValue("1") int level, + @QueryParam("runId") Integer runId, + @QueryParam("page") Integer page, + @QueryParam("limit") Integer limit); - @GET - @Path("transformation/{testId}/count") - long getTransformationLogCount(@PathParam("testId") int testId, - @QueryParam("level") @DefaultValue("1") int level, - @QueryParam("runId") Integer runId); + @GET + @Path("transformation/{testId}/count") + long getTransformationLogCount(@PathParam("testId") int testId, + @QueryParam("level") @DefaultValue("1") int level, + @QueryParam("runId") Integer runId); - @DELETE - @Path("transformation/{testId}") - void deleteTransformationLogs(@PathParam("testId") int testId, - @QueryParam("runId") Integer runId, - @QueryParam("from") Long from, - @QueryParam("to") Long to); + @DELETE + @Path("transformation/{testId}") + void deleteTransformationLogs(@PathParam("testId") int testId, + @QueryParam("runId") Integer runId, + @QueryParam("from") Long from, + @QueryParam("to") Long to); - @GET - @Path("action/{testId}") - List getActionLog(@PathParam("testId") int testId, - @QueryParam("level") @DefaultValue("1") int level, - @QueryParam("page") Integer page, - @QueryParam("limit") Integer limit); + @GET + @Path("action/{testId}") + List getActionLog(@PathParam("testId") int testId, + @QueryParam("level") @DefaultValue("1") int level, + @QueryParam("page") Integer page, + @QueryParam("limit") Integer limit); - @GET - @Path("action/{testId}/count") - long getActionLogCount(@PathParam("testId") int testId, - @QueryParam("level") @DefaultValue("1") int level); + @GET + @Path("action/{testId}/count") + long getActionLogCount(@PathParam("testId") int testId, + @QueryParam("level") @DefaultValue("1") int level); - @DELETE - @Path("action/{testId}") - void deleteActionLogs(@PathParam("testId") int testId, - @QueryParam("from") Long from, - @QueryParam("to") Long to); + @DELETE + @Path("action/{testId}") + void deleteActionLogs(@PathParam("testId") int testId, + @QueryParam("from") Long from, + @QueryParam("to") Long to); } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/NotificationService.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/NotificationService.java index 216b93085..d314d0466 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/NotificationService.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/NotificationService.java @@ -11,33 +11,34 @@ import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; -import io.hyperfoil.tools.horreum.api.alerting.NotificationSettings; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; import org.eclipse.microprofile.openapi.annotations.tags.Tag; +import io.hyperfoil.tools.horreum.api.alerting.NotificationSettings; + @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/api/notifications") @Tag(name = "notifications", description = "Manage reports") public interface NotificationService { - @GET - @Path("/methods") - Collection methods(); - - @GET - @Path("/settings") - List settings(@Parameter(required = true) @QueryParam("name") String name, - @Parameter(required = true) @QueryParam("team") boolean team); - - @POST - @Path("/settings") - void updateSettings(@Parameter(required = true) @QueryParam("name") String name, - @Parameter(required = true) @QueryParam("team") boolean team, - @RequestBody(required = true) NotificationSettings[] settings); - - @POST - @Path("test") - void testNotifications(@QueryParam("method") String method, - @Parameter(required = true) @QueryParam("data") String data); + @GET + @Path("/methods") + Collection methods(); + + @GET + @Path("/settings") + List settings(@Parameter(required = true) @QueryParam("name") String name, + @Parameter(required = true) @QueryParam("team") boolean team); + + @POST + @Path("/settings") + void updateSettings(@Parameter(required = true) @QueryParam("name") String name, + @Parameter(required = true) @QueryParam("team") boolean team, + @RequestBody(required = true) NotificationSettings[] settings); + + @POST + @Path("test") + void testNotifications(@QueryParam("method") String method, + @Parameter(required = true) @QueryParam("data") String data); } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/ReportService.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/ReportService.java index 9a5a4219b..15556e32d 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/ReportService.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/ReportService.java @@ -14,89 +14,90 @@ import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; -import io.hyperfoil.tools.horreum.api.SortDirection; -import io.hyperfoil.tools.horreum.api.report.ReportComment; -import io.hyperfoil.tools.horreum.api.report.TableReportConfig; -import io.hyperfoil.tools.horreum.api.report.TableReport; +import org.eclipse.microprofile.openapi.annotations.tags.Tag; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; -import org.eclipse.microprofile.openapi.annotations.tags.Tag; + +import io.hyperfoil.tools.horreum.api.SortDirection; +import io.hyperfoil.tools.horreum.api.report.ReportComment; +import io.hyperfoil.tools.horreum.api.report.TableReport; +import io.hyperfoil.tools.horreum.api.report.TableReportConfig; @Path("/api/report") @Produces(MediaType.APPLICATION_JSON) -@Consumes({ MediaType.APPLICATION_JSON}) +@Consumes({ MediaType.APPLICATION_JSON }) @Tag(name = "report", description = "Manage reports") public interface ReportService { - @GET - @Path("table") - AllTableReports getTableReports( - @QueryParam("folder") String folder, - @QueryParam("test") Integer testId, - @QueryParam("roles") String roles, - @QueryParam("limit") Integer limit, - @QueryParam("page") Integer page, - @QueryParam("sort") String sort, - @QueryParam("direction") SortDirection direction); - - @GET - @Path("table/config/{id}") - TableReportConfig getTableReportConfig(@PathParam("id") int id); - - @POST - @Path("table/preview") - TableReport previewTableReport(TableReportConfig config, @QueryParam("edit") Integer updatedReportId); - - @POST - @Path("table/config") - TableReport updateTableReportConfig(TableReportConfig config, @QueryParam("edit") Integer updatedReportId); - - @GET - @Path("table/{id}") - TableReport getTableReport(@PathParam("id") int id); - - @DELETE - @Path("table/{id}") - void deleteTableReport(@PathParam("id") int id); - - @POST - @Path("comment/{reportId}") - ReportComment updateComment(@PathParam("reportId") int reportId, ReportComment comment); - - @GET - @Path("table/config/{id}/export") - JsonNode exportTableReportConfig(@PathParam("id") int id); - - @POST - @Path("table/config/import") - void importTableReportConfig(JsonNode config); - - class AllTableReports { - @NotNull - public List reports; - @JsonProperty(required = true) - public long count; - } - - class TableReportSummary { - @JsonProperty(required = true) - public int configId; - @JsonProperty(required = true) - public int testId; - @NotNull - public String testName; - @NotNull - public String title; - @NotNull - public List reports; - } - - class TableReportSummaryItem { - @JsonProperty(required = true) - public int id; - @JsonProperty(required = true) - public int configId; - @JsonProperty(required = true) - public Instant created; - } + @GET + @Path("table") + AllTableReports getTableReports( + @QueryParam("folder") String folder, + @QueryParam("test") Integer testId, + @QueryParam("roles") String roles, + @QueryParam("limit") Integer limit, + @QueryParam("page") Integer page, + @QueryParam("sort") String sort, + @QueryParam("direction") SortDirection direction); + + @GET + @Path("table/config/{id}") + TableReportConfig getTableReportConfig(@PathParam("id") int id); + + @POST + @Path("table/preview") + TableReport previewTableReport(TableReportConfig config, @QueryParam("edit") Integer updatedReportId); + + @POST + @Path("table/config") + TableReport updateTableReportConfig(TableReportConfig config, @QueryParam("edit") Integer updatedReportId); + + @GET + @Path("table/{id}") + TableReport getTableReport(@PathParam("id") int id); + + @DELETE + @Path("table/{id}") + void deleteTableReport(@PathParam("id") int id); + + @POST + @Path("comment/{reportId}") + ReportComment updateComment(@PathParam("reportId") int reportId, ReportComment comment); + + @GET + @Path("table/config/{id}/export") + JsonNode exportTableReportConfig(@PathParam("id") int id); + + @POST + @Path("table/config/import") + void importTableReportConfig(JsonNode config); + + class AllTableReports { + @NotNull + public List reports; + @JsonProperty(required = true) + public long count; + } + + class TableReportSummary { + @JsonProperty(required = true) + public int configId; + @JsonProperty(required = true) + public int testId; + @NotNull + public String testName; + @NotNull + public String title; + @NotNull + public List reports; + } + + class TableReportSummaryItem { + @JsonProperty(required = true) + public int id; + @JsonProperty(required = true) + public int configId; + @JsonProperty(required = true) + public Instant created; + } } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/SqlService.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/SqlService.java index ff8a10216..c6ea2b4fa 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/SqlService.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/SqlService.java @@ -1,7 +1,5 @@ package io.hyperfoil.tools.horreum.api.internal.services; -import io.hyperfoil.tools.horreum.api.data.JsonpathValidation; -import io.hyperfoil.tools.horreum.api.data.QueryResult; import jakarta.ws.rs.Consumes; import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.GET; @@ -15,42 +13,37 @@ import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; import org.eclipse.microprofile.openapi.annotations.tags.Tag; +import io.hyperfoil.tools.horreum.api.data.JsonpathValidation; +import io.hyperfoil.tools.horreum.api.data.QueryResult; + @Path("/api/sql") -@Consumes({ MediaType.APPLICATION_JSON}) +@Consumes({ MediaType.APPLICATION_JSON }) @Produces(MediaType.APPLICATION_JSON) @Tag(name = "sql", description = "Manage sql service") public interface SqlService { - @GET - @Path("testjsonpath") - @Operation(description = "Test a JSONPath for syntax errors using database") - JsonpathValidation testJsonPath(@Parameter(required = true, - name="testjsonpath", - description = "JSONPath to be tested", - example = "$.qdup") @QueryParam("query") String jsonpath); - - @Path("roles") - @GET - @Produces("text/plain") - String roles(@QueryParam("system") @DefaultValue("false") boolean system); - - @GET - @Path("{id}/queryrun") - QueryResult queryRunData(@PathParam("id") int id, - @Parameter(required = true, - name = "query", - description = "JSONPath path executed on the Run", - example = "$.results") @QueryParam("query") String jsonpath, - @QueryParam("uri") String schemaUri, - @QueryParam("array") @DefaultValue("false") boolean array); - - @Path("{id}/querydataset") - @GET - QueryResult queryDatasetData(@PathParam("id") int datasetId, - @Parameter(required = true, - name = "query", - description = "JSONPath path executed on the Dataset", - example = "$.test") @QueryParam("query") String jsonpath, - @QueryParam("array") @DefaultValue("false") boolean array, - @QueryParam("schemaUri") String schemaUri); + @GET + @Path("testjsonpath") + @Operation(description = "Test a JSONPath for syntax errors using database") + JsonpathValidation testJsonPath( + @Parameter(required = true, name = "testjsonpath", description = "JSONPath to be tested", example = "$.qdup") @QueryParam("query") String jsonpath); + + @Path("roles") + @GET + @Produces("text/plain") + String roles(@QueryParam("system") @DefaultValue("false") boolean system); + + @GET + @Path("{id}/queryrun") + QueryResult queryRunData(@PathParam("id") int id, + @Parameter(required = true, name = "query", description = "JSONPath path executed on the Run", example = "$.results") @QueryParam("query") String jsonpath, + @QueryParam("uri") String schemaUri, + @QueryParam("array") @DefaultValue("false") boolean array); + + @Path("{id}/querydataset") + @GET + QueryResult queryDatasetData(@PathParam("id") int datasetId, + @Parameter(required = true, name = "query", description = "JSONPath path executed on the Dataset", example = "$.test") @QueryParam("query") String jsonpath, + @QueryParam("array") @DefaultValue("false") boolean array, + @QueryParam("schemaUri") String schemaUri); } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/SubscriptionService.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/SubscriptionService.java index df389d990..a4cdd7394 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/SubscriptionService.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/SubscriptionService.java @@ -1,8 +1,6 @@ package io.hyperfoil.tools.horreum.api.internal.services; import java.util.List; -import java.util.Map; -import java.util.Set; import jakarta.ws.rs.Consumes; import jakarta.ws.rs.GET; @@ -10,36 +8,36 @@ import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; import jakarta.ws.rs.Produces; -import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; -import io.hyperfoil.tools.horreum.api.alerting.Watch; import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; import org.eclipse.microprofile.openapi.annotations.tags.Tag; +import io.hyperfoil.tools.horreum.api.alerting.Watch; + @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/api/subscriptions") @Tag(name = "subscriptions", description = "Manage subscriptions") public interface SubscriptionService { - @GET - @Path("/{testId}") - Watch get(@PathParam("testId") int testId); - - @POST - @Path("/{testid}") - void update(@PathParam("testid") int testId, @RequestBody(required = true) Watch watch); - - @POST - @Path("/{testid}/add") - @Consumes({ MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN }) - List addUserOrTeam(@PathParam("testid") int testId, - @RequestBody(required = true) String userOrTeam); - - @POST - @Path("/{testid}/remove") - @Consumes({ MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN }) - List removeUserOrTeam(@PathParam("testid") int testId, - @RequestBody(required = true) String userOrTeam); -} \ No newline at end of file + @GET + @Path("/{testId}") + Watch get(@PathParam("testId") int testId); + + @POST + @Path("/{testid}") + void update(@PathParam("testid") int testId, @RequestBody(required = true) Watch watch); + + @POST + @Path("/{testid}/add") + @Consumes({ MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN }) + List addUserOrTeam(@PathParam("testid") int testId, + @RequestBody(required = true) String userOrTeam); + + @POST + @Path("/{testid}/remove") + @Consumes({ MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN }) + List removeUserOrTeam(@PathParam("testid") int testId, + @RequestBody(required = true) String userOrTeam); +} diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/UIService.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/UIService.java index 3794d50aa..e3d7add62 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/UIService.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/UIService.java @@ -1,6 +1,7 @@ package io.hyperfoil.tools.horreum.api.internal.services; -import io.hyperfoil.tools.horreum.api.data.View; +import java.util.List; + import jakarta.ws.rs.Consumes; import jakarta.ws.rs.DELETE; import jakarta.ws.rs.GET; @@ -9,13 +10,14 @@ import jakarta.ws.rs.PathParam; import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; + import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; import org.eclipse.microprofile.openapi.annotations.tags.Tag; -import java.util.List; +import io.hyperfoil.tools.horreum.api.data.View; @Path("/api/ui") -@Consumes({ MediaType.APPLICATION_JSON}) +@Consumes({ MediaType.APPLICATION_JSON }) @Produces(MediaType.APPLICATION_JSON) @Tag(name = "ui", description = "Manage schemas") public interface UIService { diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/UserService.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/UserService.java index 9bb3c9459..857a059a4 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/UserService.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/internal/services/UserService.java @@ -18,6 +18,7 @@ import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; import org.eclipse.microprofile.openapi.annotations.tags.Tag; + import io.smallrye.common.annotation.Blocking; @Path("api/user") @@ -26,122 +27,123 @@ @Tag(name = "user", description = "Manage users") public interface UserService { - @GET - @Path("roles") - @Blocking - List getRoles(); - - @GET - @Path("search") - @Blocking - @Operation(description="Search for user(s) with an optional query condition.") - List searchUsers(@Parameter(required = true, name="query", description = "filter users by username (case insensitive)", example = "user") @QueryParam("query") String query); - - @POST - @Path("info") - @Blocking - List info(@RequestBody(required = true) List usernames); - - @POST - @Path("createUser") - @Blocking - void createUser(@RequestBody(required = true) NewUser user); - - @DELETE - @Path("{username}") - @Blocking - void removeUser(@PathParam("username") String username); - - @GET - @Path("teams") - @Blocking - List getTeams(); - - @GET - @Path("defaultTeam") - @Produces("text/plain") - @Blocking - String defaultTeam(); - - @POST - @Path("defaultTeam") - @Consumes("text/plain") - @Blocking - void setDefaultTeam(@RequestBody(required = true) String team); - - @GET - @Path("team/{team}/members") - @Blocking - Map> teamMembers(@PathParam("team") String team); - - @POST - @Path("team/{team}/members") - @Blocking - void updateTeamMembers(@PathParam("team") String team, @RequestBody(required = true) Map> roles); - - @GET - @Path("allTeams") - @Blocking - List getAllTeams(); - - @Path("team/{team}") - @POST - @Blocking - void addTeam(@PathParam("team") String team); - - @Path("team/{team}") - @DELETE - @Blocking - void deleteTeam(@PathParam("team") String team); - - @GET - @Path("administrators") - @Blocking - List administrators(); - - @POST - @Path("administrators") - @Blocking - void updateAdministrators(@RequestBody(required = true) List administrators); - - @GET - @Path("team/{team}/machine") - @Blocking - List machineAccounts(@PathParam("team") String team); - - @POST - @Path("/team/{team}/reset") - @Consumes("text/plain") - @Produces("text/plain") - @Blocking - String resetPassword(@PathParam("team") String team, @RequestBody(required = true) String username); - - // this is a simplified copy of org.keycloak.representations.idm.UserRepresentation - class UserData { - @NotNull - public String id; - @NotNull - public String username; - public String firstName; - public String lastName; - public String email; - - public UserData() { - } - - public UserData(String id, String username, String firstName, String lastName, String email) { - this.id = id; - this.username = username; - this.firstName = firstName; - this.lastName = lastName; - this.email = email; - } - } - - class NewUser { - public UserData user; - public String password; - public String team; - public List roles; - } + @GET + @Path("roles") + @Blocking + List getRoles(); + + @GET + @Path("search") + @Blocking + @Operation(description = "Search for user(s) with an optional query condition.") + List searchUsers( + @Parameter(required = true, name = "query", description = "filter users by username (case insensitive)", example = "user") @QueryParam("query") String query); + + @POST + @Path("info") + @Blocking + List info(@RequestBody(required = true) List usernames); + + @POST + @Path("createUser") + @Blocking + void createUser(@RequestBody(required = true) NewUser user); + + @DELETE + @Path("{username}") + @Blocking + void removeUser(@PathParam("username") String username); + + @GET + @Path("teams") + @Blocking + List getTeams(); + + @GET + @Path("defaultTeam") + @Produces("text/plain") + @Blocking + String defaultTeam(); + + @POST + @Path("defaultTeam") + @Consumes("text/plain") + @Blocking + void setDefaultTeam(@RequestBody(required = true) String team); + + @GET + @Path("team/{team}/members") + @Blocking + Map> teamMembers(@PathParam("team") String team); + + @POST + @Path("team/{team}/members") + @Blocking + void updateTeamMembers(@PathParam("team") String team, @RequestBody(required = true) Map> roles); + + @GET + @Path("allTeams") + @Blocking + List getAllTeams(); + + @Path("team/{team}") + @POST + @Blocking + void addTeam(@PathParam("team") String team); + + @Path("team/{team}") + @DELETE + @Blocking + void deleteTeam(@PathParam("team") String team); + + @GET + @Path("administrators") + @Blocking + List administrators(); + + @POST + @Path("administrators") + @Blocking + void updateAdministrators(@RequestBody(required = true) List administrators); + + @GET + @Path("team/{team}/machine") + @Blocking + List machineAccounts(@PathParam("team") String team); + + @POST + @Path("/team/{team}/reset") + @Consumes("text/plain") + @Produces("text/plain") + @Blocking + String resetPassword(@PathParam("team") String team, @RequestBody(required = true) String username); + + // this is a simplified copy of org.keycloak.representations.idm.UserRepresentation + class UserData { + @NotNull + public String id; + @NotNull + public String username; + public String firstName; + public String lastName; + public String email; + + public UserData() { + } + + public UserData(String id, String username, String firstName, String lastName, String email) { + this.id = id; + this.username = username; + this.firstName = firstName; + this.lastName = lastName; + this.email = email; + } + } + + class NewUser { + public UserData user; + public String password; + public String team; + public List roles; + } } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/report/ReportComment.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/report/ReportComment.java index 789184ba6..1e5235daf 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/report/ReportComment.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/report/ReportComment.java @@ -1,17 +1,18 @@ package io.hyperfoil.tools.horreum.api.report; -import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotNull; +import com.fasterxml.jackson.annotation.JsonProperty; + public class ReportComment { public Integer id; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public int level; public String category; public int componentId; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public String comment; } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/report/ReportComponent.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/report/ReportComponent.java index 63a7a7452..db56827ea 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/report/ReportComponent.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/report/ReportComponent.java @@ -1,22 +1,24 @@ package io.hyperfoil.tools.horreum.api.report; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.node.ArrayNode; import jakarta.validation.constraints.NotNull; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.node.ArrayNode; + @Schema(type = SchemaType.OBJECT, description = "Report Component", name = "ReportComponent") public class ReportComponent { public Integer id; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public String name; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) public int order; @NotNull - @JsonProperty( required = true ) + @JsonProperty(required = true) @Schema(type = SchemaType.ARRAY, implementation = String.class, description = "Array of labels", example = "[\"Framework\"]") public ArrayNode labels; public String function; diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/report/ReportLog.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/report/ReportLog.java index 4a8634de6..534d1b900 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/report/ReportLog.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/report/ReportLog.java @@ -1,16 +1,18 @@ package io.hyperfoil.tools.horreum.api.report; -import com.fasterxml.jackson.annotation.JsonProperty; -import io.hyperfoil.tools.horreum.api.data.PersistentLog; import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; +import com.fasterxml.jackson.annotation.JsonProperty; + +import io.hyperfoil.tools.horreum.api.data.PersistentLog; + @Schema(type = SchemaType.OBJECT, description = "Report Log", name = "ReportLog", allOf = PersistentLog.class) public class ReportLog extends PersistentLog { private int reportId; public ReportLog() { - super(0, (String)null); + super(0, (String) null); } public ReportLog(int reportId, int level, String message) { diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/report/TableReport.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/report/TableReport.java index 4e9b48a43..859a8d49b 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/report/TableReport.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/report/TableReport.java @@ -1,13 +1,15 @@ package io.hyperfoil.tools.horreum.api.report; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.node.ArrayNode; +import java.time.Instant; +import java.util.Collection; + import jakarta.validation.constraints.NotNull; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -import java.time.Instant; -import java.util.Collection; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.node.ArrayNode; @Schema(type = SchemaType.OBJECT, description = "Table Report", name = "TableReport") public class TableReport { @@ -18,8 +20,7 @@ public class TableReport { @Schema(type = SchemaType.OBJECT, implementation = TableReportConfig.class, description = "Table Report Config", allOf = TableReportConfig.class) public TableReportConfig config; @NotNull - @Schema(type = SchemaType.STRING, implementation = Instant.class, - description = "Created timestamp", example = "2019-09-26T07:58:30.996+0200") + @Schema(type = SchemaType.STRING, implementation = Instant.class, description = "Created timestamp", example = "2019-09-26T07:58:30.996+0200") public Instant created; @NotNull @JsonProperty(required = true) @@ -78,7 +79,8 @@ public DataDTO() { } public String toString() { - return "TableReport.Data{datasetId=" + this.datasetId + ", category='" + this.category + '\'' + ", series='" + this.series + '\'' + ", label='" + this.scale + '\'' + ", values=" + this.values + '}'; + return "TableReport.Data{datasetId=" + this.datasetId + ", category='" + this.category + '\'' + ", series='" + + this.series + '\'' + ", label='" + this.scale + '\'' + ", values=" + this.values + '}'; } } } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/report/TableReportConfig.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/report/TableReportConfig.java index 661cc1751..2e9116367 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/report/TableReportConfig.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/report/TableReportConfig.java @@ -1,13 +1,16 @@ package io.hyperfoil.tools.horreum.api.report; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.node.ArrayNode; -import io.hyperfoil.tools.horreum.api.data.Test; +import java.util.List; + import jakarta.validation.constraints.NotNull; + import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.media.Schema; -import java.util.List; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.node.ArrayNode; + +import io.hyperfoil.tools.horreum.api.data.Test; @Schema(type = SchemaType.OBJECT, description = "Table Report Config", name = "TableReportConfig") public class TableReportConfig { @@ -42,13 +45,14 @@ public class TableReportConfig { public TableReportConfig() { } - public void ensureLinked() { - if (components != null) { - for (ReportComponent c : components) { - c.reportId = id; - } - } - } + + public void ensureLinked() { + if (components != null) { + for (ReportComponent c : components) { + c.reportId = id; + } + } + } @Override public String toString() { @@ -71,4 +75,4 @@ public String toString() { ", components=" + components + '}'; } -} \ No newline at end of file +} diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/ConfigService.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/ConfigService.java index c7b4a7f2e..6949ccf60 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/ConfigService.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/ConfigService.java @@ -1,11 +1,13 @@ package io.hyperfoil.tools.horreum.api.services; -import com.fasterxml.jackson.annotation.JsonProperty; -import io.hyperfoil.tools.horreum.api.data.datastore.Datastore; -import io.quarkus.runtime.Startup; +import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; + +import java.util.List; + import jakarta.annotation.security.PermitAll; import jakarta.validation.constraints.NotNull; import jakarta.ws.rs.*; + import org.eclipse.microprofile.openapi.annotations.Operation; import org.eclipse.microprofile.openapi.annotations.extensions.Extension; import org.eclipse.microprofile.openapi.annotations.media.Schema; @@ -14,9 +16,10 @@ import org.eclipse.microprofile.openapi.annotations.responses.APIResponseSchema; import org.eclipse.microprofile.openapi.annotations.tags.Tag; -import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; +import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; +import io.hyperfoil.tools.horreum.api.data.datastore.Datastore; +import io.quarkus.runtime.Startup; @Startup @PermitAll @@ -25,80 +28,73 @@ @Tag(name = "Config", description = "Endpoint providing configuration for the Horreum System") @Extension(name = "x-smallrye-profile-external", value = "") public interface ConfigService { - long startTimestamp = System.currentTimeMillis(); - String KEYCLOAK_BOOTSTRAP_URL = "/api/config/keycloak"; - - @GET - @Path("keycloak") - @Operation(description="Obtain configuration information about keycloak server securing Horreum instance") - KeycloakConfig keycloak(); - - @GET - @Path("version") - @Operation(description="Obtain version of the running Horreum instance") - VersionInfo version(); - - - @GET - @Path("datastore/{team}") - @Operation(description="Obtain list of configured datastores for particular team") - @Parameters(value = { - @Parameter(name = "team", description = "name of the team to search for defined datastores", example = "perf-team") - }) - List datastores(@PathParam("team") String team); - - @POST - @Path("datastore") - @Operation(description="Create a new Datastore") - @Consumes(APPLICATION_JSON) - @APIResponseSchema(value = Integer.class, - responseDescription = "The ID for the new Datastore", - responseCode = "200") - Integer newDatastore(@NotNull Datastore datastore); - - @PUT - @Path("datastore") - @Operation(description="Update an existing Datastore definition") - @Consumes(APPLICATION_JSON) - @APIResponseSchema(value = Integer.class, - responseDescription = "The ID of the updated Datastore", - responseCode = "200") - Integer updateDatastore(Datastore backend); - - @GET - @Path("datastore/{id}/test") - @Operation(description="Test a Datastore connection") - DatastoreTestResponse testDatastore(@PathParam("id") String datastoreId); - - @DELETE - @Path("datastore/{id}") - @Operation(description="Test a Datastore") - void deleteDatastore(@PathParam("id") String datastoreId); - - - - class VersionInfo { - @Schema(description="Version of Horreum", example="0.9.4") - @NotNull - public String version; - @JsonProperty(required = true) - @Schema(description="Timestamp of server startup", example = "2023-10-18 18:00:57") - public long startTimestamp; - @Schema(description="Privacy statement", example="link/to/external/privacy/statement") - public String privacyStatement; - } - - class KeycloakConfig { - @Schema(description="Keycloak realm securing Horreum instance", example = "horreum") - public String realm; - @Schema(description="URL of Keycloak instance securing Horreum", example = "https://horreum-keycloak.example.com") - public String url; - @Schema(description="Keycloak client ID in Horreum realm for User Interface", example = "horreum-ui") - public String clientId; - } - - class DatastoreTestResponse { - public String msg; - public Boolean success; - } + long startTimestamp = System.currentTimeMillis(); + String KEYCLOAK_BOOTSTRAP_URL = "/api/config/keycloak"; + + @GET + @Path("keycloak") + @Operation(description = "Obtain configuration information about keycloak server securing Horreum instance") + KeycloakConfig keycloak(); + + @GET + @Path("version") + @Operation(description = "Obtain version of the running Horreum instance") + VersionInfo version(); + + @GET + @Path("datastore/{team}") + @Operation(description = "Obtain list of configured datastores for particular team") + @Parameters(value = { + @Parameter(name = "team", description = "name of the team to search for defined datastores", example = "perf-team") + }) + List datastores(@PathParam("team") String team); + + @POST + @Path("datastore") + @Operation(description = "Create a new Datastore") + @Consumes(APPLICATION_JSON) + @APIResponseSchema(value = Integer.class, responseDescription = "The ID for the new Datastore", responseCode = "200") + Integer newDatastore(@NotNull Datastore datastore); + + @PUT + @Path("datastore") + @Operation(description = "Update an existing Datastore definition") + @Consumes(APPLICATION_JSON) + @APIResponseSchema(value = Integer.class, responseDescription = "The ID of the updated Datastore", responseCode = "200") + Integer updateDatastore(Datastore backend); + + @GET + @Path("datastore/{id}/test") + @Operation(description = "Test a Datastore connection") + DatastoreTestResponse testDatastore(@PathParam("id") String datastoreId); + + @DELETE + @Path("datastore/{id}") + @Operation(description = "Test a Datastore") + void deleteDatastore(@PathParam("id") String datastoreId); + + class VersionInfo { + @Schema(description = "Version of Horreum", example = "0.9.4") + @NotNull + public String version; + @JsonProperty(required = true) + @Schema(description = "Timestamp of server startup", example = "2023-10-18 18:00:57") + public long startTimestamp; + @Schema(description = "Privacy statement", example = "link/to/external/privacy/statement") + public String privacyStatement; + } + + class KeycloakConfig { + @Schema(description = "Keycloak realm securing Horreum instance", example = "horreum") + public String realm; + @Schema(description = "URL of Keycloak instance securing Horreum", example = "https://horreum-keycloak.example.com") + public String url; + @Schema(description = "Keycloak client ID in Horreum realm for User Interface", example = "horreum-ui") + public String clientId; + } + + class DatastoreTestResponse { + public String msg; + public Boolean success; + } } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/DatasetService.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/DatasetService.java index a1600330b..82fcf55bd 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/DatasetService.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/DatasetService.java @@ -1,11 +1,5 @@ package io.hyperfoil.tools.horreum.api.services; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.JsonNode; - -import io.hyperfoil.tools.horreum.api.SortDirection; -import io.hyperfoil.tools.horreum.api.data.*; - import java.util.List; import jakarta.validation.constraints.NotNull; @@ -31,139 +25,137 @@ import org.eclipse.microprofile.openapi.annotations.responses.APIResponseSchema; import org.eclipse.microprofile.openapi.annotations.tags.Tag; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; + +import io.hyperfoil.tools.horreum.api.SortDirection; +import io.hyperfoil.tools.horreum.api.data.*; + @Path("/api/dataset") -@Consumes({ MediaType.APPLICATION_JSON}) +@Consumes({ MediaType.APPLICATION_JSON }) @Produces(MediaType.APPLICATION_JSON) @Tag(name = "Dataset", description = "Datasets are used as the basis for all change detection and reporting") @Extension(name = "x-smallrye-profile-external", value = "") public interface DatasetService { - @Path("{id}") - @GET - @Produces(MediaType.APPLICATION_JSON) - @Operation(description="Retrieve Dataset by ID") - @Parameters(value = { - @Parameter(name = "id", description = "Dataset ID to retrieve", example = "101"), - }) - @APIResponse( - responseCode = "404", - description = "No Dataset with the given id was found", - content = @Content(mediaType = "application/json")) - @APIResponseSchema(value = Dataset.class, - responseDescription = "JVM system properties of a particular host.", - responseCode = "200") - Dataset getDataset(@PathParam("id") int datasetId); - - @Path("list/{testId}") - @GET - @Operation(description="Retrieve a paginated list of Datasets, with total count, by Test") - @Parameters(value = { - @Parameter(name = "testId", description = "Test ID of test to retrieve list of Datasets", example = "101"), - @Parameter(name = "filter", description = "JOSN Filter expression to apply to query", example = "{\"buildID\":111111}"), - @Parameter(name = "limit", description = "limit the number of results", example = "20"), - @Parameter(name = "page", description = "filter by page number of a paginated list of Schemas", example = "2"), - @Parameter(name = "sort", description = "Field name to sort results", example = "name"), - @Parameter(name = "direction", description = "Sort direction", example ="Ascending"), - @Parameter(name = "viewId", description = "Optional View ID to filter datasets by view", example ="202"), - }) - DatasetList listByTest(@PathParam("testId") int testId, - @QueryParam("filter") String filter, - @QueryParam("limit") Integer limit, - @QueryParam("page") Integer page, - @QueryParam("sort") String sort, - @QueryParam("direction") SortDirection direction, - @QueryParam("viewId") Integer viewId); - - - @GET - @Path("bySchema") - @Operation(description="Retrieve a paginated list of Datasets, with total count, by Schema") - @Parameters(value = { - @Parameter(name = "uri", required = true, description = "Schema URI", example = "uri:techempower:0.1"), - @Parameter(name = "limit", description = "limit the number of results", example = "20"), - @Parameter(name = "page", description = "filter by page number of a paginated list of Schemas", example = "2"), - @Parameter(name = "sort", description = "Field name to sort results", example = "name"), - @Parameter(name = "direction", description = "Sort direction", example ="Ascending"), - }) - DatasetList listBySchema(@QueryParam("uri") String uri, - @QueryParam("limit") Integer limit, - @QueryParam("page") Integer page, - @QueryParam("sort") @DefaultValue("start") String sort, - @QueryParam("direction") SortDirection direction); - - @GET - @Path("{datasetId}/labelValues") - List labelValues(@PathParam("datasetId") int datasetId); - - @POST - @Path("{datasetId}/previewLabel") - LabelPreview previewLabel(@PathParam("datasetId") int datasetId, @RequestBody(required = true) Label label); - - @GET - @Path("{datasetId}/summary") - DatasetSummary getSummary(@PathParam("datasetId") int datasetId, @QueryParam("viewId") int viewId); - - @Schema(type = SchemaType.OBJECT, allOf = ProtectedTimeType.class) - class DatasetSummary extends ProtectedTimeType { - @JsonProperty(required = true) - @Schema(description = "Unique Dataset ID", example = "101") - public int id; - @JsonProperty(required = true) - @Schema(description = "Run ID that Dataset relates to", example = "202") - public int runId; - @JsonProperty(required = true) - @Schema(description = "Ordinal position of Dataset Summary on returned List", example = "3") - public int ordinal; - @JsonProperty(required = true) - @Schema(description = "Test ID that Dataset relates to", example = "202") - public int testId; - @NotNull - @Schema(description="Test name that the Dataset relates to", - example="my-comprehensive-benchmark") - public String testname; - @Schema(description="Dataset description", - example = "Run on AWS with m7g.large") - public String description; - - @Schema(type = SchemaType.OBJECT, description = "map of view component ids to the LabelValueMap to render the component for this dataset", example = "{ \"[view_component_id]\": { \"[labelName]\": labelValue} }") - public IndexedLabelValueMap view; - - @JsonProperty(required = true) - @Schema(description = "List of Schema usages") - public List schemas; - @Schema(description = "List of Validation Errors") - public List validationErrors; - } - - @Schema(description = "Result containing a subset of Dataset Summaries and the total count of available. Used in paginated tables") - class DatasetList { - @JsonProperty(required = true) - @Schema(description = "Total number of Dataset Summaries available", example = "64") - public long total; - @NotNull - @Schema(description = "List of Dataset Summaries. This is often a subset of total available.") - public List datasets; - } - - @Schema(description = "Label Value derived from Label definition and Dataset Data") - class LabelValue { - @JsonProperty(required = true) - @Schema(description = "Unique ID for Label Value", example = "101") - public int id; - @NotNull - @Schema(description = "Label name", example = "buildID") - public String name; - @NotNull - @Schema(description = "Summary description of Schema") - public SchemaService.SchemaDescriptor schema; - @Schema(implementation = String.class, description = "Value value extracted from Dataset. This can be a scalar, array or JSON object", example = "1724") - public JsonNode value; - } - - @Schema(description = "Preview a Label Value derived from a Dataset Data. A preview allows users to apply a Label to a dataset and preview the Label Value result and processing errors in the UI") - class LabelPreview { - @Schema(implementation = String.class, description = "Value value extracted from Dataset. This can be a scalar, array or JSON object") - public JsonNode value; - @Schema(description = "Description of errors occurred attempting to generate Label Value Preview") - public String output; - } + @Path("{id}") + @GET + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Retrieve Dataset by ID") + @Parameters(value = { + @Parameter(name = "id", description = "Dataset ID to retrieve", example = "101"), + }) + @APIResponse(responseCode = "404", description = "No Dataset with the given id was found", content = @Content(mediaType = "application/json")) + @APIResponseSchema(value = Dataset.class, responseDescription = "JVM system properties of a particular host.", responseCode = "200") + Dataset getDataset(@PathParam("id") int datasetId); + + @Path("list/{testId}") + @GET + @Operation(description = "Retrieve a paginated list of Datasets, with total count, by Test") + @Parameters(value = { + @Parameter(name = "testId", description = "Test ID of test to retrieve list of Datasets", example = "101"), + @Parameter(name = "filter", description = "JOSN Filter expression to apply to query", example = "{\"buildID\":111111}"), + @Parameter(name = "limit", description = "limit the number of results", example = "20"), + @Parameter(name = "page", description = "filter by page number of a paginated list of Schemas", example = "2"), + @Parameter(name = "sort", description = "Field name to sort results", example = "name"), + @Parameter(name = "direction", description = "Sort direction", example = "Ascending"), + @Parameter(name = "viewId", description = "Optional View ID to filter datasets by view", example = "202"), + }) + DatasetList listByTest(@PathParam("testId") int testId, + @QueryParam("filter") String filter, + @QueryParam("limit") Integer limit, + @QueryParam("page") Integer page, + @QueryParam("sort") String sort, + @QueryParam("direction") SortDirection direction, + @QueryParam("viewId") Integer viewId); + + @GET + @Path("bySchema") + @Operation(description = "Retrieve a paginated list of Datasets, with total count, by Schema") + @Parameters(value = { + @Parameter(name = "uri", required = true, description = "Schema URI", example = "uri:techempower:0.1"), + @Parameter(name = "limit", description = "limit the number of results", example = "20"), + @Parameter(name = "page", description = "filter by page number of a paginated list of Schemas", example = "2"), + @Parameter(name = "sort", description = "Field name to sort results", example = "name"), + @Parameter(name = "direction", description = "Sort direction", example = "Ascending"), + }) + DatasetList listBySchema(@QueryParam("uri") String uri, + @QueryParam("limit") Integer limit, + @QueryParam("page") Integer page, + @QueryParam("sort") @DefaultValue("start") String sort, + @QueryParam("direction") SortDirection direction); + + @GET + @Path("{datasetId}/labelValues") + List labelValues(@PathParam("datasetId") int datasetId); + + @POST + @Path("{datasetId}/previewLabel") + LabelPreview previewLabel(@PathParam("datasetId") int datasetId, @RequestBody(required = true) Label label); + + @GET + @Path("{datasetId}/summary") + DatasetSummary getSummary(@PathParam("datasetId") int datasetId, @QueryParam("viewId") int viewId); + + @Schema(type = SchemaType.OBJECT, allOf = ProtectedTimeType.class) + class DatasetSummary extends ProtectedTimeType { + @JsonProperty(required = true) + @Schema(description = "Unique Dataset ID", example = "101") + public int id; + @JsonProperty(required = true) + @Schema(description = "Run ID that Dataset relates to", example = "202") + public int runId; + @JsonProperty(required = true) + @Schema(description = "Ordinal position of Dataset Summary on returned List", example = "3") + public int ordinal; + @JsonProperty(required = true) + @Schema(description = "Test ID that Dataset relates to", example = "202") + public int testId; + @NotNull + @Schema(description = "Test name that the Dataset relates to", example = "my-comprehensive-benchmark") + public String testname; + @Schema(description = "Dataset description", example = "Run on AWS with m7g.large") + public String description; + + @Schema(type = SchemaType.OBJECT, description = "map of view component ids to the LabelValueMap to render the component for this dataset", example = "{ \"[view_component_id]\": { \"[labelName]\": labelValue} }") + public IndexedLabelValueMap view; + + @JsonProperty(required = true) + @Schema(description = "List of Schema usages") + public List schemas; + @Schema(description = "List of Validation Errors") + public List validationErrors; + } + + @Schema(description = "Result containing a subset of Dataset Summaries and the total count of available. Used in paginated tables") + class DatasetList { + @JsonProperty(required = true) + @Schema(description = "Total number of Dataset Summaries available", example = "64") + public long total; + @NotNull + @Schema(description = "List of Dataset Summaries. This is often a subset of total available.") + public List datasets; + } + + @Schema(description = "Label Value derived from Label definition and Dataset Data") + class LabelValue { + @JsonProperty(required = true) + @Schema(description = "Unique ID for Label Value", example = "101") + public int id; + @NotNull + @Schema(description = "Label name", example = "buildID") + public String name; + @NotNull + @Schema(description = "Summary description of Schema") + public SchemaService.SchemaDescriptor schema; + @Schema(implementation = String.class, description = "Value value extracted from Dataset. This can be a scalar, array or JSON object", example = "1724") + public JsonNode value; + } + + @Schema(description = "Preview a Label Value derived from a Dataset Data. A preview allows users to apply a Label to a dataset and preview the Label Value result and processing errors in the UI") + class LabelPreview { + @Schema(implementation = String.class, description = "Value value extracted from Dataset. This can be a scalar, array or JSON object") + public JsonNode value; + @Schema(description = "Description of errors occurred attempting to generate Label Value Preview") + public String output; + } } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/ExperimentService.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/ExperimentService.java index fdff53174..3ab6eb918 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/ExperimentService.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/ExperimentService.java @@ -1,26 +1,9 @@ package io.hyperfoil.tools.horreum.api.services; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.KeyDeserializer; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import io.hyperfoil.tools.horreum.api.data.ConditionConfig; -import io.hyperfoil.tools.horreum.api.alerting.DatasetLog; -import io.hyperfoil.tools.horreum.api.data.Dataset; -import io.hyperfoil.tools.horreum.api.data.ExperimentComparison; -import io.hyperfoil.tools.horreum.api.data.ExperimentProfile; -import org.eclipse.microprofile.openapi.annotations.Operation; -import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; -import org.eclipse.microprofile.openapi.annotations.extensions.Extension; -import org.eclipse.microprofile.openapi.annotations.media.Content; -import org.eclipse.microprofile.openapi.annotations.media.Schema; -import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; -import org.eclipse.microprofile.openapi.annotations.parameters.Parameters; -import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; +import java.io.IOException; +import java.util.Collection; +import java.util.List; +import java.util.Map; import jakarta.ws.rs.Consumes; import jakarta.ws.rs.DELETE; @@ -31,166 +14,186 @@ import jakarta.ws.rs.Produces; import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; + +import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.extensions.Extension; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; +import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; +import org.eclipse.microprofile.openapi.annotations.parameters.Parameters; +import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; import org.eclipse.microprofile.openapi.annotations.tags.Tag; -import java.io.IOException; -import java.util.Collection; -import java.util.List; -import java.util.Map; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.KeyDeserializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import io.hyperfoil.tools.horreum.api.alerting.DatasetLog; +import io.hyperfoil.tools.horreum.api.data.ConditionConfig; +import io.hyperfoil.tools.horreum.api.data.Dataset; +import io.hyperfoil.tools.horreum.api.data.ExperimentComparison; +import io.hyperfoil.tools.horreum.api.data.ExperimentProfile; -@Consumes({ MediaType.APPLICATION_JSON}) +@Consumes({ MediaType.APPLICATION_JSON }) @Produces(MediaType.APPLICATION_JSON) @Path("/api/experiment") @Tag(name = "Experiment", description = "Experiments allow users to apply change detection rules to two different datasets. This allows for pass/fail of KPIS based on A/B testing") @Extension(name = "x-smallrye-profile-external", value = "") public interface ExperimentService { - @GET - @Path("{testId}/profiles") - @Operation(description="Retrieve Experiment Profiles by Test ID") - @Parameters(value = { - @Parameter(name = "testId", description = "Test ID to retrieve Experiment Profiles for", example = "101"), - }) - Collection profiles(@PathParam("testId") int testId); - - @POST - @Path("{testId}/profiles") - @Operation(description="Save new or update existing Experiment Profiles for a Test ") - @Parameters(value = { - @Parameter(name = "testId", description = "Test ID to retrieve Experiment Profiles for", example = "101"), - }) - int addOrUpdateProfile(@PathParam("testId") int testId, - @RequestBody(required = true) ExperimentProfile profile); - - @DELETE - @Path("{testId}/profiles/{profileId}") - @Operation(description="Delete an Experiment Profiles for a Test") - @Parameters(value = { - @Parameter(name = "testId", description = "Test ID", example = "101"), - @Parameter(name = "profileId", description = "Experiment Profile ID", example = "202"), - }) - void deleteProfile(@PathParam("testId") int testId, - @PathParam("profileId") int profileId); - - @GET - @Path("models") - @Operation(description="Retrieve a list of Condition Config models") - List models(); - - @GET - @Path("run") - @Produces(MediaType.APPLICATION_JSON) - @Operation(description="Run an experiment for a given dataset and experiment profile") - @Parameters(value = { - @Parameter(name = "datasetId", description = "The dataset to run the experiment on", example = "101"), - }) - @APIResponses( - value = { @APIResponse(responseCode = "200", description = "Array of experiment results", - content = { @Content( - schema = @Schema(type = SchemaType.ARRAY, implementation = ExperimentResult.class)) - }) - }) - List runExperiments(@QueryParam("datasetId") int datasetId); - - @Schema(description = "Result of running an Experiment", type = SchemaType.STRING) - enum BetterOrWorse { - BETTER("BETTER"), - SAME("SAME"), - WORSE("WORSE"); - private static final BetterOrWorse[] VALUES = BetterOrWorse.values(); - - private final String name; - - BetterOrWorse(String s) { this.name = s; } - - public static BetterOrWorse fromString(String s) { - for (BetterOrWorse v : VALUES) { - if (v.name.equals(s)) { - return v; + @GET + @Path("{testId}/profiles") + @Operation(description = "Retrieve Experiment Profiles by Test ID") + @Parameters(value = { + @Parameter(name = "testId", description = "Test ID to retrieve Experiment Profiles for", example = "101"), + }) + Collection profiles(@PathParam("testId") int testId); + + @POST + @Path("{testId}/profiles") + @Operation(description = "Save new or update existing Experiment Profiles for a Test ") + @Parameters(value = { + @Parameter(name = "testId", description = "Test ID to retrieve Experiment Profiles for", example = "101"), + }) + int addOrUpdateProfile(@PathParam("testId") int testId, + @RequestBody(required = true) ExperimentProfile profile); + + @DELETE + @Path("{testId}/profiles/{profileId}") + @Operation(description = "Delete an Experiment Profiles for a Test") + @Parameters(value = { + @Parameter(name = "testId", description = "Test ID", example = "101"), + @Parameter(name = "profileId", description = "Experiment Profile ID", example = "202"), + }) + void deleteProfile(@PathParam("testId") int testId, + @PathParam("profileId") int profileId); + + @GET + @Path("models") + @Operation(description = "Retrieve a list of Condition Config models") + List models(); + + @GET + @Path("run") + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Run an experiment for a given dataset and experiment profile") + @Parameters(value = { + @Parameter(name = "datasetId", description = "The dataset to run the experiment on", example = "101"), + }) + @APIResponses(value = { + @APIResponse(responseCode = "200", description = "Array of experiment results", content = { + @Content(schema = @Schema(type = SchemaType.ARRAY, implementation = ExperimentResult.class)) + }) + }) + List runExperiments(@QueryParam("datasetId") int datasetId); + + @Schema(description = "Result of running an Experiment", type = SchemaType.STRING) + enum BetterOrWorse { + BETTER("BETTER"), + SAME("SAME"), + WORSE("WORSE"); + + private static final BetterOrWorse[] VALUES = BetterOrWorse.values(); + + private final String name; + + BetterOrWorse(String s) { + this.name = s; + } + + public static BetterOrWorse fromString(String s) { + for (BetterOrWorse v : VALUES) { + if (v.name.equals(s)) { + return v; + } } - } - return null; - } - - public static BetterOrWorse fromInt(int b) { - return VALUES[b]; - } - } - - @Schema(description = "Result of running an Experiment", type = SchemaType.OBJECT) - class ExperimentResult { - - @Schema(description="Experiment profile that results relates to") - public ExperimentProfile profile; - @Schema(description="A list of log statements recorded while Experiment was evaluated") - public List logs; - @Schema(description="Dataset Info about dataset used for experiment") - public Dataset.Info datasetInfo; - @Schema(description="A list of Dataset Info for experiment baseline(s)") - public List baseline; - - @JsonSerialize(keyUsing = ExperimentComparisonSerializer.class) - @JsonDeserialize(keyUsing = ExperimentComparisonDeserializer.class) - @Schema(description="A Map of all comparisons and results evaluated during an Experiment") - public Map results; - - @Schema(implementation = String.class) - public JsonNode extraLabels; - public boolean notify; - - public ExperimentResult() { - } - - public ExperimentResult(ExperimentProfile profile, List logs, - Dataset.Info datasetInfo, List baseline, - Map results, - JsonNode extraLabels, boolean notify) { - this.profile = profile; - this.logs = logs; - this.datasetInfo = datasetInfo; - this.baseline = baseline; - this.results = results; - this.extraLabels = extraLabels; - this.notify = notify; - } - } - - @Schema(description = "Result of performing a Comparison", - type = SchemaType.OBJECT) - class ComparisonResult { - @Schema(description="Was the Experiment dataset better or worse than the baseline dataset", - type = SchemaType.STRING, implementation = BetterOrWorse.class, allOf = BetterOrWorse.class) - public BetterOrWorse overall; - @Schema(description="Experiment value") - public double experimentValue; - @Schema(description="Baseline value") - public double baselineValue; - @Schema(description="The relative difference between the Experiment and Baseline Datasets") - public String result; - - public ComparisonResult() { - } - public ComparisonResult(BetterOrWorse overall, double experimentValue, double baselineValue, String result) { - this.overall = overall; - this.experimentValue = experimentValue; - this.baselineValue = baselineValue; - this.result = result; - } - } - - class ExperimentComparisonSerializer extends JsonSerializer { - @Override - public void serialize(ExperimentComparison value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeFieldName(value.variableName); - } - } - - class ExperimentComparisonDeserializer extends KeyDeserializer { - @Override - public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException { - return key; - } - } + return null; + } + + public static BetterOrWorse fromInt(int b) { + return VALUES[b]; + } + } + + @Schema(description = "Result of running an Experiment", type = SchemaType.OBJECT) + class ExperimentResult { + + @Schema(description = "Experiment profile that results relates to") + public ExperimentProfile profile; + @Schema(description = "A list of log statements recorded while Experiment was evaluated") + public List logs; + @Schema(description = "Dataset Info about dataset used for experiment") + public Dataset.Info datasetInfo; + @Schema(description = "A list of Dataset Info for experiment baseline(s)") + public List baseline; + + @JsonSerialize(keyUsing = ExperimentComparisonSerializer.class) + @JsonDeserialize(keyUsing = ExperimentComparisonDeserializer.class) + @Schema(description = "A Map of all comparisons and results evaluated during an Experiment") + public Map results; + + @Schema(implementation = String.class) + public JsonNode extraLabels; + public boolean notify; + + public ExperimentResult() { + } + + public ExperimentResult(ExperimentProfile profile, List logs, + Dataset.Info datasetInfo, List baseline, + Map results, + JsonNode extraLabels, boolean notify) { + this.profile = profile; + this.logs = logs; + this.datasetInfo = datasetInfo; + this.baseline = baseline; + this.results = results; + this.extraLabels = extraLabels; + this.notify = notify; + } + } + + @Schema(description = "Result of performing a Comparison", type = SchemaType.OBJECT) + class ComparisonResult { + @Schema(description = "Was the Experiment dataset better or worse than the baseline dataset", type = SchemaType.STRING, implementation = BetterOrWorse.class, allOf = BetterOrWorse.class) + public BetterOrWorse overall; + @Schema(description = "Experiment value") + public double experimentValue; + @Schema(description = "Baseline value") + public double baselineValue; + @Schema(description = "The relative difference between the Experiment and Baseline Datasets") + public String result; + + public ComparisonResult() { + } + + public ComparisonResult(BetterOrWorse overall, double experimentValue, double baselineValue, String result) { + this.overall = overall; + this.experimentValue = experimentValue; + this.baselineValue = baselineValue; + this.result = result; + } + } + + class ExperimentComparisonSerializer extends JsonSerializer { + @Override + public void serialize(ExperimentComparison value, JsonGenerator gen, SerializerProvider serializers) + throws IOException { + gen.writeFieldName(value.variableName); + } + } + + class ExperimentComparisonDeserializer extends KeyDeserializer { + @Override + public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException { + return key; + } + } } diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/RunService.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/RunService.java index 0a8c3c990..1ca880d41 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/RunService.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/RunService.java @@ -1,13 +1,5 @@ package io.hyperfoil.tools.horreum.api.services; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -import com.fasterxml.jackson.databind.node.ObjectNode; -import io.hyperfoil.tools.horreum.api.ApiIgnore; -import io.hyperfoil.tools.horreum.api.SortDirection; -import io.hyperfoil.tools.horreum.api.data.*; - import java.util.List; import java.util.Map; @@ -34,21 +26,23 @@ import org.jboss.resteasy.reactive.Separator; import org.jboss.resteasy.reactive.multipart.FileUpload; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import io.hyperfoil.tools.horreum.api.ApiIgnore; +import io.hyperfoil.tools.horreum.api.SortDirection; +import io.hyperfoil.tools.horreum.api.data.*; + @Path("/api/run") -@Consumes({MediaType.APPLICATION_JSON}) +@Consumes({ MediaType.APPLICATION_JSON }) @Produces(MediaType.APPLICATION_JSON) @Tag(name = "Run", description = "Manage test runs. Runs are instances of results of a benchmark execution") @Extension(name = "x-smallrye-profile-external", value = "") public interface RunService { @GET @Path("{id}") - @APIResponse( - responseCode = "404", - description = "If no Run have been found with the given id", - content = @Content(mediaType = MediaType.APPLICATION_JSON)) - @APIResponseSchema(value = RunExtended.class, - responseDescription = "Run data with the referenced schemas and generated datasets", - responseCode = "200") + @APIResponse(responseCode = "404", description = "If no Run have been found with the given id", content = @Content(mediaType = MediaType.APPLICATION_JSON)) + @APIResponseSchema(value = RunExtended.class, responseDescription = "Run data with the referenced schemas and generated datasets", responseCode = "200") @Operation(description = "Get extended Run information by Run ID") @Parameters(value = { @Parameter(name = "id", in = ParameterIn.PATH, description = "Run ID", example = "202"), @@ -56,17 +50,12 @@ public interface RunService { }) RunExtended getRun(@PathParam("id") int id, - @QueryParam("token") String token); + @QueryParam("token") String token); @GET @Path("{id}/summary") - @APIResponse( - responseCode = "404", - description = "If no Run have been found with the given id", - content = @Content(mediaType = MediaType.APPLICATION_JSON)) - @APIResponseSchema(value = RunSummary.class, - responseDescription = "Run summary with the referenced schemas and generated datasets", - responseCode = "200") + @APIResponse(responseCode = "404", description = "If no Run have been found with the given id", content = @Content(mediaType = MediaType.APPLICATION_JSON)) + @APIResponseSchema(value = RunSummary.class, responseDescription = "Run summary with the referenced schemas and generated datasets", responseCode = "200") @Operation(description = "Get Run Summary information by Run ID") @Parameters(value = { @Parameter(name = "id", in = ParameterIn.PATH, description = "Run ID", example = "202"), @@ -84,66 +73,50 @@ RunExtended getRun(@PathParam("id") int id, @Parameter(name = "schemaUri", in = ParameterIn.QUERY, description = "FIlter by Schmea URI", example = "uri:my-benchmark:0.1") }) - @APIResponses( - value = { - @APIResponse(responseCode = "200", - description = "Run payload", - content = { - @Content(schema = @Schema(type = SchemaType.OBJECT), - example = "{ \"buildID\": 1709, ...}") - } - ) - } - ) + @APIResponses(value = { + @APIResponse(responseCode = "200", description = "Run payload", content = { + @Content(schema = @Schema(type = SchemaType.OBJECT), example = "{ \"buildID\": 1709, ...}") + }) + }) Object getData(@PathParam("id") int id, - @QueryParam("token") String token, - @QueryParam("schemaUri") String schemaUri); + @QueryParam("token") String token, + @QueryParam("schemaUri") String schemaUri); @GET @Path("{id}/labelValues") @Operation(description = "Get all the label values for the run") @Parameters(value = { - @Parameter(name = "id", in =ParameterIn.PATH, description = "Run Id", example = "101"), + @Parameter(name = "id", in = ParameterIn.PATH, description = "Run Id", example = "101"), @Parameter(name = "filter", description = "either a required json sub-document or path expression", examples = { - @ExampleObject(name="object", value="{labelName:necessaryValue,...}", description = "json object that must exist in the values object"), - @ExampleObject(name="string", value="$.count ? (@ < 20 && @ > 10)",description = "valid filtering jsonpath that returns null if not found (not predicates)") + @ExampleObject(name = "object", value = "{labelName:necessaryValue,...}", description = "json object that must exist in the values object"), + @ExampleObject(name = "string", value = "$.count ? (@ < 20 && @ > 10)", description = "valid filtering jsonpath that returns null if not found (not predicates)") }), @Parameter(name = "sort", description = "label name for sorting"), - @Parameter(name = "direction",description = "either Ascending or Descending",example="count"), - @Parameter(name = "limit",description = "the maximum number of results to include",example="10"), - @Parameter(name = "page",description = "which page to skip to when using a limit",example="2"), - @Parameter(name = "include", description = "label name(s) to include in the result as scalar or comma separated", - examples = { - @ExampleObject(name="single", value="id", description = "including a single label"), - @ExampleObject(name="multiple", value="id,count", description = "including multiple labels") - }), - @Parameter(name = "exclude", description = "label name(s) to exclude from the result as scalar or comma separated", - examples = { - @ExampleObject(name="single", value="id", description = "excluding a single label"), - @ExampleObject(name="multiple", value="id,count", description = "excluding multiple labels") - }), + @Parameter(name = "direction", description = "either Ascending or Descending", example = "count"), + @Parameter(name = "limit", description = "the maximum number of results to include", example = "10"), + @Parameter(name = "page", description = "which page to skip to when using a limit", example = "2"), + @Parameter(name = "include", description = "label name(s) to include in the result as scalar or comma separated", examples = { + @ExampleObject(name = "single", value = "id", description = "including a single label"), + @ExampleObject(name = "multiple", value = "id,count", description = "including multiple labels") + }), + @Parameter(name = "exclude", description = "label name(s) to exclude from the result as scalar or comma separated", examples = { + @ExampleObject(name = "single", value = "id", description = "excluding a single label"), + @ExampleObject(name = "multiple", value = "id,count", description = "excluding multiple labels") + }), @Parameter(name = "multiFilter", description = "enable filtering for multiple values with an array of values", example = "true") }) - @APIResponses( - value = { - @APIResponse(responseCode = "200", - description = "label Values", - content = { - @Content( - schema = @Schema(type = SchemaType.ARRAY, implementation = ExportedLabelValues.class), - example = "[ { \"datasetId\" : 101, \"runId\": 201, \"values\" : { [labelName] : labelValue } },...]" - ) - } - ) - } - ) + @APIResponses(value = { + @APIResponse(responseCode = "200", description = "label Values", content = { + @Content(schema = @Schema(type = SchemaType.ARRAY, implementation = ExportedLabelValues.class), example = "[ { \"datasetId\" : 101, \"runId\": 201, \"values\" : { [labelName] : labelValue } },...]") + }) + }) List labelValues( @PathParam("id") int runId, @QueryParam("filter") @DefaultValue("{}") String filter, @QueryParam("sort") @DefaultValue("") String sort, @QueryParam("direction") @DefaultValue("Ascending") String direction, - @QueryParam("limit") @DefaultValue(""+Integer.MAX_VALUE) int limit, + @QueryParam("limit") @DefaultValue("" + Integer.MAX_VALUE) int limit, @QueryParam("page") @DefaultValue("0") int page, @QueryParam("include") @Separator(",") List include, @QueryParam("exclude") @Separator(",") List exclude, @@ -158,20 +131,14 @@ List labelValues( @Parameter(name = "schemaUri", in = ParameterIn.QUERY, description = "Filter by Schmea URI", example = "uri:my-benchmark:0.1") }) - @APIResponses( - value = { - @APIResponse(responseCode = "200", - description = "Run payload", - content = { - @Content(schema = @Schema(type = SchemaType.OBJECT), - example = "{ \"metaDataID\": 1709, ...}") - } - ) - } - ) + @APIResponses(value = { + @APIResponse(responseCode = "200", description = "Run payload", content = { + @Content(schema = @Schema(type = SchemaType.OBJECT), example = "{ \"metaDataID\": 1709, ...}") + }) + }) Object getMetadata(@PathParam("id") int id, - @QueryParam("token") String token, - @QueryParam("schemaUri") String schemaUri); + @QueryParam("token") String token, + @QueryParam("schemaUri") String schemaUri); @POST @Path("{id}/resetToken") @@ -179,16 +146,11 @@ Object getMetadata(@PathParam("id") int id, @Parameters(value = { @Parameter(name = "id", description = "Token ID", example = "102"), }) - @APIResponses( - value = { - @APIResponse(responseCode = "200", - content = { - @Content(schema = @Schema(type = SchemaType.STRING), - example = "094678029a2aaf9a2847502273099bb3a1b2338c2b9c618ed09aef0181666e38") - } - ) - } - ) + @APIResponses(value = { + @APIResponse(responseCode = "200", content = { + @Content(schema = @Schema(type = SchemaType.STRING), example = "094678029a2aaf9a2847502273099bb3a1b2338c2b9c618ed09aef0181666e38") + }) + }) String resetToken(@PathParam("id") int id); @POST @@ -209,8 +171,8 @@ Object getMetadata(@PathParam("id") int id, @Parameter(name = "access", required = true, description = "New Access level", example = "0") }) void updateAccess(@PathParam("id") int id, - @QueryParam("owner") String owner, - @QueryParam("access") Access access); + @QueryParam("owner") String owner, + @QueryParam("access") Access access); @POST @Path("test") @@ -222,57 +184,45 @@ void updateAccess(@PathParam("id") int id, @Parameter(name = "access", description = "New Access level", example = "0"), @Parameter(name = "token", in = ParameterIn.QUERY, description = "API token", example = "094678029a2aaf9a2847502273099bb3a1b2338c2b9c618ed09aef0181666e38"), }) - @RequestBody(name = "runBody", - content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = Run.class)), - required = true) + @RequestBody(name = "runBody", content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = Run.class)), required = true) Response add(@QueryParam("test") String testNameOrId, - @QueryParam("owner") String owner, - @QueryParam("access") Access access, - @QueryParam("token") String token, - Run run); + @QueryParam("owner") String owner, + @QueryParam("access") Access access, + @QueryParam("token") String token, + Run run); @POST @Path("data") - @RequestBody(content = @Content(mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(type = SchemaType.STRING, implementation = String.class), - example = "[\n" + - " {\n" + - " \"tag\": \"main\",\n" + - " \"score\": 2031.7424089224041,\n" + - " \"params\": {\n" + - " \"size\": \"1000\",\n" + - " \"useTreeSet\": \"true\"\n" + - " },\n" + - " \"$schema\": \"urn:jmh:0.2\",\n" + - " \"testName\": \"org.drools.benchmarks.datastructures.QueueBenchmark.benchmark\"\n" + - " },\n" + - " {\n" + - " \"$schema\": \"urn:horreum:jenkins-plugin:0.1\",\n" + - " \"jobName\": \"upstream-perf-bre-datastructures\",\n" + - " \"buildUrl\": \"https://qe.com/job/TESTING/job/upstream-perfx-datastructures/125/\",\n" + - " \"startTime\": 1698020160763,\n" + - " \"uploadTime\": 1698020592674,\n" + - " \"buildNumber\": 125,\n" + - " \"jobFullName\": \"TESTING/RHBA/_upstream/decisions/8.x/performance/nightly/upstream-perf-bre-datastructures\",\n" + - " \"scheduleTime\": 1698020160756,\n" + - " \"jobDisplayName\": \"upstream-perf-bre-datastructures\",\n" + - " \"buildDisplayName\": \"#125\"\n" + - " }\n" + - "]")) - @APIResponses( - value = { - @APIResponse( - responseCode = "200", - description = "id of the newly generated run", - content = @Content(mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(type = SchemaType.INTEGER, implementation = Integer.class), - example = "101")), - @APIResponse( - responseCode = "400", - description = "Some fields are missing or invalid", - content = @Content(mediaType = MediaType.APPLICATION_JSON)) - } - ) + @RequestBody(content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(type = SchemaType.STRING, implementation = String.class), example = "[\n" + + + " {\n" + + " \"tag\": \"main\",\n" + + " \"score\": 2031.7424089224041,\n" + + " \"params\": {\n" + + " \"size\": \"1000\",\n" + + " \"useTreeSet\": \"true\"\n" + + " },\n" + + " \"$schema\": \"urn:jmh:0.2\",\n" + + " \"testName\": \"org.drools.benchmarks.datastructures.QueueBenchmark.benchmark\"\n" + + " },\n" + + " {\n" + + " \"$schema\": \"urn:horreum:jenkins-plugin:0.1\",\n" + + " \"jobName\": \"upstream-perf-bre-datastructures\",\n" + + " \"buildUrl\": \"https://qe.com/job/TESTING/job/upstream-perfx-datastructures/125/\",\n" + + " \"startTime\": 1698020160763,\n" + + " \"uploadTime\": 1698020592674,\n" + + " \"buildNumber\": 125,\n" + + " \"jobFullName\": \"TESTING/RHBA/_upstream/decisions/8.x/performance/nightly/upstream-perf-bre-datastructures\",\n" + + + " \"scheduleTime\": 1698020160756,\n" + + " \"jobDisplayName\": \"upstream-perf-bre-datastructures\",\n" + + " \"buildDisplayName\": \"#125\"\n" + + " }\n" + + "]")) + @APIResponses(value = { + @APIResponse(responseCode = "200", description = "id of the newly generated run", content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(type = SchemaType.INTEGER, implementation = Integer.class), example = "101")), + @APIResponse(responseCode = "400", description = "Some fields are missing or invalid", content = @Content(mediaType = MediaType.APPLICATION_JSON)) + }) @Operation(description = "Upload a new Run") @Parameters(value = { @Parameter(name = "start", required = true, description = "start timestamp of run, or json path expression", examples = { @@ -292,14 +242,14 @@ Response add(@QueryParam("test") String testNameOrId, }) Response addRunFromData(@QueryParam("start") String start, - @QueryParam("stop") String stop, - @QueryParam("test") String test, - @QueryParam("owner") String owner, - @QueryParam("access") Access access, - @QueryParam("token") String token, - @QueryParam("schema") String schemaUri, - @QueryParam("description") String description, - @RequestBody(required = true) String data); + @QueryParam("stop") String stop, + @QueryParam("test") String test, + @QueryParam("owner") String owner, + @QueryParam("access") Access access, + @QueryParam("token") String token, + @QueryParam("schema") String schemaUri, + @QueryParam("description") String description, + @RequestBody(required = true) String data); @POST @Path("data") @@ -307,27 +257,24 @@ Response addRunFromData(@QueryParam("start") String start, @Produces(MediaType.TEXT_PLAIN) // run ID as string @Operation(description = "Upload a new Run with metadata", hidden = true) @APIResponses(value = { - @APIResponse(responseCode = "200", - content = {@Content(mediaType = MediaType.TEXT_PLAIN, - schema = @Schema(type = SchemaType.STRING))})}) + @APIResponse(responseCode = "200", content = { + @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = SchemaType.STRING)) }) }) Response addRunFromData(@Parameter(required = true) @QueryParam("start") String start, - @Parameter(required = true) @QueryParam("stop") String stop, - @Parameter(required = true) @QueryParam("test") String test, - @QueryParam("owner") String owner, - @QueryParam("access") Access access, - @Parameter(description = "Horreum internal token. Incompatible with Keycloak") @QueryParam("token") String token, - @QueryParam("schema") String schemaUri, - @QueryParam("description") String description, - @RestForm("data") FileUpload data, - @RestForm("metadata") FileUpload metadata); + @Parameter(required = true) @QueryParam("stop") String stop, + @Parameter(required = true) @QueryParam("test") String test, + @QueryParam("owner") String owner, + @QueryParam("access") Access access, + @Parameter(description = "Horreum internal token. Incompatible with Keycloak") @QueryParam("token") String token, + @QueryParam("schema") String schemaUri, + @QueryParam("description") String description, + @RestForm("data") FileUpload data, + @RestForm("metadata") FileUpload metadata); @GET @Path("autocomplete") @ApiIgnore - List autocomplete(@Parameter(required = true, - name = "query", - description = "JSONPath to be autocompleted", - example = "$.") @QueryParam("query") String query); + List autocomplete( + @Parameter(required = true, name = "query", description = "JSONPath to be autocompleted", example = "$.") @QueryParam("query") String query); @GET @Path("list") @@ -341,24 +288,22 @@ List autocomplete(@Parameter(required = true, @Parameter(name = "page", description = "filter by page number of a paginated list of Tests", example = "2"), @Parameter(name = "sort", description = "Field name to sort results", example = "name"), @Parameter(name = "direction", description = "Sort direction", example = "Ascending") - } - ) + }) RunsSummary listAllRuns(@QueryParam("query") String query, - @QueryParam("matchAll") boolean matchAll, - @QueryParam("roles") String roles, - @QueryParam("trashed") boolean trashed, - @QueryParam("limit") Integer limit, - @QueryParam("page") Integer page, - @QueryParam("sort") String sort, - @QueryParam("direction") SortDirection direction); + @QueryParam("matchAll") boolean matchAll, + @QueryParam("roles") String roles, + @QueryParam("trashed") boolean trashed, + @QueryParam("limit") Integer limit, + @QueryParam("page") Integer page, + @QueryParam("sort") String sort, + @QueryParam("direction") SortDirection direction); @GET @Path("count") @Operation(description = "Run count summary for given Test ID") @Parameters(value = { @Parameter(name = "testId", required = true, description = "Test ID", example = "101"), - } - ) + }) RunCount runCount(@QueryParam("testId") int testId); @GET @@ -371,14 +316,13 @@ RunsSummary listAllRuns(@QueryParam("query") String query, @Parameter(name = "page", description = "filter by page number of a paginated list of Tests", example = "2"), @Parameter(name = "sort", description = "Field name to sort results", example = "name"), @Parameter(name = "direction", description = "Sort direction", example = "Ascending") - } - ) + }) RunsSummary listTestRuns(@PathParam("testId") int testId, - @QueryParam("trashed") boolean trashed, - @QueryParam("limit") Integer limit, - @QueryParam("page") Integer page, - @QueryParam("sort") String sort, - @QueryParam("direction") SortDirection direction); + @QueryParam("trashed") boolean trashed, + @QueryParam("limit") Integer limit, + @QueryParam("page") Integer page, + @QueryParam("sort") String sort, + @QueryParam("direction") SortDirection direction); @GET @Path("bySchema") @@ -391,10 +335,10 @@ RunsSummary listTestRuns(@PathParam("testId") int testId, @Parameter(name = "direction", description = "Sort direction", example = "Ascending") }) RunsSummary listBySchema(@QueryParam("uri") String uri, - @QueryParam("limit") Integer limit, - @QueryParam("page") Integer page, - @QueryParam("sort") String sort, - @QueryParam("direction") SortDirection direction); + @QueryParam("limit") Integer limit, + @QueryParam("page") Integer page, + @QueryParam("sort") String sort, + @QueryParam("direction") SortDirection direction); @POST @Path("{id}/trash") @@ -422,20 +366,20 @@ RunsSummary listBySchema(@QueryParam("uri") String uri, @Parameter(name = "id", description = "Run ID", example = "101"), @Parameter(name = "path", description = "JSON path expression to update schema", example = "$.schemaURI"), }) -// TODO:: I can not find a way of defining a Map response type correctly via smallrye annotations -// @APIResponses( -// value = { -// @APIResponse( responseCode = "200", -// description = "Map of schema by ID", -// content = { -// @Content ( example = "") -// } -// ) -// } -// ) + // TODO:: I can not find a way of defining a Map response type correctly via smallrye annotations + // @APIResponses( + // value = { + // @APIResponse( responseCode = "200", + // description = "Map of schema by ID", + // content = { + // @Content ( example = "") + // } + // ) + // } + // ) Map updateSchema(@PathParam("id") int id, - @QueryParam("path") String path, - @RequestBody(required = true) String schemaUri); + @QueryParam("path") String path, + @RequestBody(required = true) String schemaUri); @POST @Path("{id}/recalculate") @@ -443,18 +387,11 @@ Map updateSchema(@PathParam("id") int id, @Parameters(value = { @Parameter(name = "id", description = "Run ID", example = "101"), }) - @APIResponses( - value = { - @APIResponse(responseCode = "200", - description = "Array of generated Datasets", - content = { - @Content( - schema = @Schema(type = SchemaType.ARRAY, implementation = Integer.class), - example = "[101, 102, 103]") - } - ) - } - ) + @APIResponses(value = { + @APIResponse(responseCode = "200", description = "Array of generated Datasets", content = { + @Content(schema = @Schema(type = SchemaType.ARRAY, implementation = Integer.class), example = "[101, 102, 103]") + }) + }) List recalculateDatasets(@PathParam("id") int runId); @POST @@ -467,35 +404,35 @@ Map updateSchema(@PathParam("id") int id, void recalculateAll(@QueryParam("from") String from, @QueryParam("to") String to); @Schema(type = SchemaType.OBJECT, allOf = ProtectedTimeType.class) - class RunSummary extends ProtectedTimeType { - @JsonProperty(required = true) - @Schema(required = true, description = "Run unique ID", example = "202") - public int id; - @JsonProperty(required = true) - @Schema(description = "test ID run relates to", example = "101") - public int testid; - - public String token; - @NotNull - @Schema(description = "test ID run relates to", example = "My benchmark") - public String testname; - @JsonProperty(required = true) - @Schema(description = "has Run been trashed in the UI", example = "false") - public boolean trashed; - @JsonProperty(required = true) - @Schema(description = "does Run have metadata uploaded alongside Run data", example = "false") - public boolean hasMetadata; - @Schema(description = "Run description", example = "Run on AWS with m7g.large") - public String description; - @Schema(description = "List of all Schema Usages for Run") - public List schemas; - @Schema(required = true, description = "Array of datasets ids", example = "[101, 102, 103]") - public Integer[] datasets; - @Schema(description = "Array of validation errors") - public ValidationError[] validationErrors; - } - - @JsonIgnoreProperties({"token", "old_start"}) //ignore properties that have not been mapped + class RunSummary extends ProtectedTimeType { + @JsonProperty(required = true) + @Schema(required = true, description = "Run unique ID", example = "202") + public int id; + @JsonProperty(required = true) + @Schema(description = "test ID run relates to", example = "101") + public int testid; + + public String token; + @NotNull + @Schema(description = "test ID run relates to", example = "My benchmark") + public String testname; + @JsonProperty(required = true) + @Schema(description = "has Run been trashed in the UI", example = "false") + public boolean trashed; + @JsonProperty(required = true) + @Schema(description = "does Run have metadata uploaded alongside Run data", example = "false") + public boolean hasMetadata; + @Schema(description = "Run description", example = "Run on AWS with m7g.large") + public String description; + @Schema(description = "List of all Schema Usages for Run") + public List schemas; + @Schema(required = true, description = "Array of datasets ids", example = "[101, 102, 103]") + public Integer[] datasets; + @Schema(description = "Array of validation errors") + public ValidationError[] validationErrors; + } + + @JsonIgnoreProperties({ "token", "old_start" }) //ignore properties that have not been mapped @Schema(type = SchemaType.OBJECT) class RunExtended extends Run { @NotNull diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/SchemaService.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/SchemaService.java index 55511aaa7..7983fbce4 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/SchemaService.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/SchemaService.java @@ -1,17 +1,9 @@ package io.hyperfoil.tools.horreum.api.services; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.node.ObjectNode; -import io.hyperfoil.tools.horreum.api.SortDirection; -import io.hyperfoil.tools.horreum.api.data.Label; -import io.hyperfoil.tools.horreum.api.data.Schema; -import io.hyperfoil.tools.horreum.api.data.SchemaExport; -import io.hyperfoil.tools.horreum.api.data.Transformer; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import io.hyperfoil.tools.horreum.api.data.Access; import jakarta.validation.constraints.NotNull; import jakarta.ws.rs.Consumes; import jakarta.ws.rs.DELETE; @@ -22,6 +14,7 @@ import jakarta.ws.rs.Produces; import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; + import org.eclipse.microprofile.openapi.annotations.Operation; import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.extensions.Extension; @@ -34,450 +27,409 @@ import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; import org.eclipse.microprofile.openapi.annotations.tags.Tag; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import io.hyperfoil.tools.horreum.api.SortDirection; +import io.hyperfoil.tools.horreum.api.data.Access; +import io.hyperfoil.tools.horreum.api.data.Label; +import io.hyperfoil.tools.horreum.api.data.Schema; +import io.hyperfoil.tools.horreum.api.data.SchemaExport; +import io.hyperfoil.tools.horreum.api.data.Transformer; + @Path("api/schema") @Produces(MediaType.APPLICATION_JSON) -@Consumes({ MediaType.APPLICATION_JSON}) +@Consumes({ MediaType.APPLICATION_JSON }) @Tag(name = "Schema", description = "Manage schemas") @Extension(name = "x-smallrye-profile-external", value = "") public interface SchemaService { - @GET - @Path("{id}") - @APIResponse( - responseCode = "404", - description = "No Schema with the given id was found", - content = @Content(mediaType = "application/json")) - @APIResponseSchema(value = Schema.class, - responseCode = "200", - responseDescription = "Returns Schema if a matching id is found") - @Operation(description="Retrieve Schema by ID") - @Parameters(value = { - @Parameter(name = "id", description = "Schema ID to retrieve", example = "101"), - @Parameter(name = "token", description = "API token for authorization", example = "101"), - }) - Schema getSchema(@PathParam("id") int id, @QueryParam("token") String token); - - @GET - @Path("idByUri/{uri}") - @Operation(description="Retrieve Schema ID by uri") - @Parameters(value = { - @Parameter(name = "uri", description = "Schema uri", example = "uri:my-schema:0.1"), - }) - @APIResponses( - value = { - @APIResponse( responseCode = "200", - content = { - @Content ( schema=@org.eclipse.microprofile.openapi.annotations.media.Schema(type = SchemaType.INTEGER, implementation = Integer.class), - example = "101") - } - ) - } - ) - int idByUri(@PathParam("uri") String uri); - - @POST - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - @Operation(description="Save a new Schema") - @APIResponse(responseCode = "200", description = "Import a new Schema", - content = @Content( schema = @org.eclipse.microprofile.openapi.annotations.media.Schema( type = SchemaType.INTEGER, implementation = Integer.class), - example = "103") - ) - Integer add(Schema schema); - - @GET - @Operation(description="Retrieve a paginated list of Schemas with available count") - @Parameters(value = { - @Parameter(name = "limit", description = "limit the number of results", example = "20"), - @Parameter(name = "page", description = "filter by page number of a paginated list of Schemas", example = "2"), - @Parameter(name = "sort", description = "Field name to sort results", example = "name"), - @Parameter(name = "direction", description = "Sort direction", example ="Ascending"), - @Parameter(name = "roles", description = "__my, __all or a comma delimited list of roles", example = "__my"), - }) - SchemaQueryResult list(@QueryParam("roles") String roles, - @QueryParam("limit") Integer limit, - @QueryParam("page") Integer page, - @QueryParam("sort") String sort, - @QueryParam("direction") SortDirection direction); - - - @GET - @Path("descriptors") - @Produces(MediaType.APPLICATION_JSON) - @Operation(description="Retrieve a list of Schema Descriptors") - @Parameters(value = { - @Parameter(name = "id", description = "Limit to a single Schema by ID", example = "102"), - }) - List descriptors(@QueryParam("id") List ids); - - @POST - @Path("{id}/resetToken") - @Operation(description="Regenerate access token for schema") - @Parameters(value = { - @Parameter(name = "id", description = "Token ID", example = "102"), - }) - @APIResponses( - value = { - @APIResponse( responseCode = "200", - content = { - @Content ( schema = @org.eclipse.microprofile.openapi.annotations.media.Schema(type = SchemaType.STRING), - example = "094678029a2aaf9a2847502273099bb3a1b2338c2b9c618ed09aef0181666e38") - } - ) - } - ) - String resetToken(@PathParam("id") int id); - - @DELETE - @Path("{id}/dropToken") - @Operation(description="Remove access token for schema") - @Parameters(value = { - @Parameter(name = "id", description = "Token ID", example = "102"), - }) - void dropToken(@PathParam("id") int id); - - @POST - @Path("{id}/updateAccess") - // TODO: it would be nicer to use @FormParams but fetchival on client side doesn't support that - @Operation(description="Update the Access configuration for a Schema") - @Parameters(value = { - @Parameter(name = "id", description = "Schema ID to update Access", example = "101"), - @Parameter(name = "owner", required = true, description = "Name of the new owner", example = "perf-team"), - @Parameter(name = "access", required = true, description = "New Access level", example = "0") - }) - void updateAccess(@PathParam("id") int id, - @QueryParam("owner") String owner, - @QueryParam("access") Access access); - - @DELETE - @Path("{id}") - @Operation(description="Delete a Schema by id") - @Parameters(value = { - @Parameter(name = "id", description = "Schema ID to delete", example = "101"), - }) - void delete(@PathParam("id") int id); - - @GET - @Path("findUsages") - @Produces(MediaType.APPLICATION_JSON) - @Operation(description="Find all usages of a Schema by label name") - @Parameters(value = { - @Parameter(name = "label", required = true, description = "Name of label to search for", example = "Throughput"), - }) - List findUsages(@QueryParam("label") String label); - - @GET - @Path("{schemaId}/transformers") - @Produces(MediaType.APPLICATION_JSON) - @Operation(description="List all Transformers defined for a Schema") - @Parameters(value = { - @Parameter(name = "schemaId", description = "Schema ID", example = "101"), - }) - List listTransformers(@PathParam("schemaId") int schemaId); - - @POST - @Path("{schemaId}/transformers") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - @Operation(description="Save new or update existing Transformer defintion") - @Parameters(value = { - @Parameter(name = "schemaId", description = "Schema ID", example = "101"), - }) - int addOrUpdateTransformer(@PathParam("schemaId") int schemaId, - @RequestBody(required = true) Transformer transformer); - - @DELETE - @Path("{schemaId}/transformers/{transformerId}") - @Operation(description="Delete a Transformer defined for a Schema") - @Parameters(value = { - @Parameter(name = "schemaId", description = "Schema ID", example = "101"), - @Parameter(name = "transformerId", description = "Transformer ID", example = "202"), - }) - void deleteTransformer(@PathParam("schemaId") int schemaId, @PathParam("transformerId") int transformerId); - - @GET - @Path("{schemaId}/labels") - @Produces(MediaType.APPLICATION_JSON) - @Operation(description="Retrieve list of Labels for a Schema by Schema ID") - @Parameters(value = { - @Parameter(name = "schemaId", description = "Schema ID", example = "101"), - }) - List