From 76556f03fa4db12ce7665a93e7745311b8c5a713 Mon Sep 17 00:00:00 2001 From: Patrick Boos Date: Wed, 23 Aug 2023 16:56:11 +0200 Subject: [PATCH 1/5] Allow configuring log level --- README.md | 4 ++++ .../core/OpenApiInteractionValidatorFactory.java | 14 +++++++++----- .../OpenApiValidationApplicationProperties.java | 2 ++ .../autoconfigure/LibraryAutoConfiguration.java | 4 +++- .../META-INF/spring-configuration-metadata.json | 5 +++++ 5 files changed, 23 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0c96fee2..c54c8d37 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,10 @@ openapi.validation.specification-file-path=/tmp/openapi-spec/openapi.json # If it is within src/main/resources/folder/my-spec.json use openapi.validation.specification-file-path=folder/my-spec.json +# Custom log level for violations +# Default: info +openapi.validation.violation-log-level=error + # Comma separated list of paths to be excluded from validation. Default is no excluded paths openapi.validation.excluded-paths=/_readiness,/_liveness,/_metrics # Allows to exclude requests based on headers. Default is no excluded headers. diff --git a/openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/OpenApiInteractionValidatorFactory.java b/openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/OpenApiInteractionValidatorFactory.java index c3614a66..ab78de3c 100644 --- a/openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/OpenApiInteractionValidatorFactory.java +++ b/openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/OpenApiInteractionValidatorFactory.java @@ -1,5 +1,7 @@ package com.getyourguide.openapi.validation.core; +import static com.atlassian.oai.validator.report.ValidationReport.Level.IGNORE; + import com.atlassian.oai.validator.OpenApiInteractionValidator; import com.atlassian.oai.validator.report.LevelResolver; import com.atlassian.oai.validator.report.ValidationReport; @@ -145,7 +147,9 @@ private LevelResolver buildLevelResolver( Map levelResolverLevels, LogLevel levelResolverDefaultLevel ) { - var builder = LevelResolver.create(); + var builder = LevelResolver.create() + // This is needed if your spec uses composition via allOf, anyOf or oneOf. + .withLevel("validation.schema.additionalProperties", IGNORE); if (levelResolverLevels != null && !levelResolverLevels.isEmpty()) { builder.withLevels( levelResolverLevels.entrySet().stream() @@ -154,10 +158,10 @@ private LevelResolver buildLevelResolver( ) ); } - return builder - // this will cause all messages to be warn by default - .withDefaultLevel(mapLevel(levelResolverDefaultLevel).orElse(ValidationReport.Level.INFO)) - .build(); + + mapLevel(levelResolverDefaultLevel).ifPresent(builder::withDefaultLevel); + + return builder.build(); } private Optional mapLevel(LogLevel level) { diff --git a/spring-boot-starter/spring-boot-starter-core/src/main/java/com/getyourguide/openapi/validation/OpenApiValidationApplicationProperties.java b/spring-boot-starter/spring-boot-starter-core/src/main/java/com/getyourguide/openapi/validation/OpenApiValidationApplicationProperties.java index 50ec9a36..bca01caa 100644 --- a/spring-boot-starter/spring-boot-starter-core/src/main/java/com/getyourguide/openapi/validation/OpenApiValidationApplicationProperties.java +++ b/spring-boot-starter/spring-boot-starter-core/src/main/java/com/getyourguide/openapi/validation/OpenApiValidationApplicationProperties.java @@ -3,6 +3,7 @@ import static com.getyourguide.openapi.validation.OpenApiValidationApplicationProperties.PROPERTY_PREFIX; import com.getyourguide.openapi.validation.api.exclusions.ExcludedHeader; +import com.getyourguide.openapi.validation.api.log.LogLevel; import com.getyourguide.openapi.validation.api.metrics.MetricTag; import com.getyourguide.openapi.validation.util.CommaSeparatedStringsUtil; import java.util.Arrays; @@ -27,6 +28,7 @@ public class OpenApiValidationApplicationProperties { private Double sampleRate; private String specificationFilePath; + private LogLevel violationLogLevel; private Integer validationReportThrottleWaitSeconds; private String validationReportMetricName; private String validationReportMetricAdditionalTags; diff --git a/spring-boot-starter/spring-boot-starter-core/src/main/java/com/getyourguide/openapi/validation/autoconfigure/LibraryAutoConfiguration.java b/spring-boot-starter/spring-boot-starter-core/src/main/java/com/getyourguide/openapi/validation/autoconfigure/LibraryAutoConfiguration.java index c5249b0f..c6782a9f 100644 --- a/spring-boot-starter/spring-boot-starter-core/src/main/java/com/getyourguide/openapi/validation/autoconfigure/LibraryAutoConfiguration.java +++ b/spring-boot-starter/spring-boot-starter-core/src/main/java/com/getyourguide/openapi/validation/autoconfigure/LibraryAutoConfiguration.java @@ -90,7 +90,9 @@ public ValidationReportHandler validationReportHandler( public ValidatorConfiguration validatorConfiguration() { return new ValidatorConfigurationBuilder() // .levelResolverLevel("validation.request.body.schema.additionalProperties", LogLevel.IGNORE) - .levelResolverDefaultLevel(LogLevel.INFO) + .levelResolverDefaultLevel( + properties.getViolationLogLevel() != null ? properties.getViolationLogLevel() : LogLevel.INFO + ) .build(); } diff --git a/spring-boot-starter/spring-boot-starter-core/src/main/resources/META-INF/spring-configuration-metadata.json b/spring-boot-starter/spring-boot-starter-core/src/main/resources/META-INF/spring-configuration-metadata.json index 018c3310..d10d22c5 100644 --- a/spring-boot-starter/spring-boot-starter-core/src/main/resources/META-INF/spring-configuration-metadata.json +++ b/spring-boot-starter/spring-boot-starter-core/src/main/resources/META-INF/spring-configuration-metadata.json @@ -10,6 +10,11 @@ "type": "java.lang.String", "description": "Path to the OpenAPI specification file. If set, the system will search for this file within resources and also as a path based on the current (working) directory. The property defaults to null. If null, the program searches for either an 'openapi.yaml/json' or a 'spec.yaml/json' file under resources." }, + { + "name": "openapi.validation.violation-log-level", + "type": "com.getyourguide.openapi.validation.api.log.LogLevel", + "description": "Log level to be used for all violations. Default: info\nNote: This has no effect if a custom ValidatorConfiguration is provided, then it needs to be configured there." + }, { "name": "openapi.validation.excluded-paths", "type": "java.lang.String", From 6aa86592beec5c783fa2fcd31a7321482a405c78 Mon Sep 17 00:00:00 2001 From: Patrick Boos Date: Wed, 23 Aug 2023 16:56:35 +0200 Subject: [PATCH 2/5] Do not report IGNORE level violations --- .../validation/api/metrics/DefaultMetricsReporter.java | 5 +++++ .../openapi/validation/core/DefaultViolationLogger.java | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/openapi-validation-api/src/main/java/com/getyourguide/openapi/validation/api/metrics/DefaultMetricsReporter.java b/openapi-validation-api/src/main/java/com/getyourguide/openapi/validation/api/metrics/DefaultMetricsReporter.java index cea88d65..79dc2a52 100644 --- a/openapi-validation-api/src/main/java/com/getyourguide/openapi/validation/api/metrics/DefaultMetricsReporter.java +++ b/openapi-validation-api/src/main/java/com/getyourguide/openapi/validation/api/metrics/DefaultMetricsReporter.java @@ -1,5 +1,6 @@ package com.getyourguide.openapi.validation.api.metrics; +import com.getyourguide.openapi.validation.api.log.LogLevel; import com.getyourguide.openapi.validation.api.metrics.client.MetricsClient; import com.getyourguide.openapi.validation.api.model.OpenApiViolation; import java.util.ArrayList; @@ -16,6 +17,10 @@ public class DefaultMetricsReporter implements MetricsReporter { @Override public void reportViolation(OpenApiViolation violation) { + if (violation.getLevel() == LogLevel.IGNORE) { + return; + } + metricsClient.increment(buildMetricName(".error"), createTagsForViolation(violation)); } diff --git a/openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/DefaultViolationLogger.java b/openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/DefaultViolationLogger.java index 2df30467..b7fb62a1 100644 --- a/openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/DefaultViolationLogger.java +++ b/openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/DefaultViolationLogger.java @@ -22,8 +22,6 @@ public void log(OpenApiViolation violation) { case INFO -> log.info(violation.getLogMessage()); case WARN -> log.warn(violation.getLogMessage()); case ERROR -> log.error(violation.getLogMessage()); - // keeping ignored as debug for now - case IGNORE -> log.debug(violation.getLogMessage()); default -> { /* do nothing */ } } } catch (IOException e) { From 9c3a2e0e7fddd6d57c2b279c765ff24c8237286b Mon Sep 17 00:00:00 2001 From: Patrick Boos Date: Wed, 23 Aug 2023 17:22:20 +0200 Subject: [PATCH 3/5] Update test --- .../OpenApiValidationApplicationPropertiesTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spring-boot-starter/spring-boot-starter-core/src/test/java/com/getyourguide/openapi/validation/OpenApiValidationApplicationPropertiesTest.java b/spring-boot-starter/spring-boot-starter-core/src/test/java/com/getyourguide/openapi/validation/OpenApiValidationApplicationPropertiesTest.java index 5bd07644..f5f95c15 100644 --- a/spring-boot-starter/spring-boot-starter-core/src/test/java/com/getyourguide/openapi/validation/OpenApiValidationApplicationPropertiesTest.java +++ b/spring-boot-starter/spring-boot-starter-core/src/test/java/com/getyourguide/openapi/validation/OpenApiValidationApplicationPropertiesTest.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import com.getyourguide.openapi.validation.api.exclusions.ExcludedHeader; +import com.getyourguide.openapi.validation.api.log.LogLevel; import com.getyourguide.openapi.validation.api.metrics.MetricTag; import java.util.List; import java.util.Set; @@ -14,6 +15,7 @@ class OpenApiValidationApplicationPropertiesTest { private static final Double SAMPLE_RATE = 0.001; private static final String SPECIFICATION_FILE_PATH = "/tmp/openapi.yaml"; + private static final LogLevel LOG_LEVEL = LogLevel.ERROR; private static final Integer VALIDATION_REPORT_THROTTLE_WAIT_SECONDS = 10; private static final String VALIDATION_REPORT_METRIC_NAME = "openapi_validation"; private static final String VALIDATION_REPORT_METRIC_ADDITONAL_TAGS_STRING = "service=payment,team=chk"; @@ -25,6 +27,7 @@ void getters() { var loggingConfiguration = new OpenApiValidationApplicationProperties( SAMPLE_RATE, SPECIFICATION_FILE_PATH, + LOG_LEVEL, VALIDATION_REPORT_THROTTLE_WAIT_SECONDS, VALIDATION_REPORT_METRIC_NAME, VALIDATION_REPORT_METRIC_ADDITONAL_TAGS_STRING, @@ -36,6 +39,7 @@ void getters() { assertEquals(SAMPLE_RATE, loggingConfiguration.getSampleRate()); assertEquals(SPECIFICATION_FILE_PATH, loggingConfiguration.getSpecificationFilePath()); + assertEquals(LOG_LEVEL, loggingConfiguration.getViolationLogLevel()); assertEquals(VALIDATION_REPORT_THROTTLE_WAIT_SECONDS, loggingConfiguration.getValidationReportThrottleWaitSeconds()); assertEquals(VALIDATION_REPORT_METRIC_NAME, loggingConfiguration.getValidationReportMetricName()); From 0c1e1015b86929a709c492a0891e8844b762fadf Mon Sep 17 00:00:00 2001 From: Patrick Boos Date: Wed, 23 Aug 2023 17:26:38 +0200 Subject: [PATCH 4/5] Remove static import --- .../validation/core/OpenApiInteractionValidatorFactory.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/OpenApiInteractionValidatorFactory.java b/openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/OpenApiInteractionValidatorFactory.java index ab78de3c..0822e69c 100644 --- a/openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/OpenApiInteractionValidatorFactory.java +++ b/openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/OpenApiInteractionValidatorFactory.java @@ -1,7 +1,5 @@ package com.getyourguide.openapi.validation.core; -import static com.atlassian.oai.validator.report.ValidationReport.Level.IGNORE; - import com.atlassian.oai.validator.OpenApiInteractionValidator; import com.atlassian.oai.validator.report.LevelResolver; import com.atlassian.oai.validator.report.ValidationReport; @@ -149,7 +147,7 @@ private LevelResolver buildLevelResolver( ) { var builder = LevelResolver.create() // This is needed if your spec uses composition via allOf, anyOf or oneOf. - .withLevel("validation.schema.additionalProperties", IGNORE); + .withLevel("validation.schema.additionalProperties", ValidationReport.Level.IGNORE); if (levelResolverLevels != null && !levelResolverLevels.isEmpty()) { builder.withLevels( levelResolverLevels.entrySet().stream() From 3180dcf1a0da9e1d7aaf3d88de5fa56c771c9848 Mon Sep 17 00:00:00 2001 From: Patrick Boos Date: Thu, 24 Aug 2023 09:32:04 +0200 Subject: [PATCH 5/5] Add log levels to README.md --- README.md | 2 +- .../src/main/resources/application.properties | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c54c8d37..e779ce95 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ openapi.validation.specification-file-path=/tmp/openapi-spec/openapi.json # If it is within src/main/resources/folder/my-spec.json use openapi.validation.specification-file-path=folder/my-spec.json -# Custom log level for violations +# Custom log level for violations (ignore, info, warn, error) # Default: info openapi.validation.violation-log-level=error diff --git a/examples/example-spring-boot-starter-web/src/main/resources/application.properties b/examples/example-spring-boot-starter-web/src/main/resources/application.properties index 462980be..55795058 100644 --- a/examples/example-spring-boot-starter-web/src/main/resources/application.properties +++ b/examples/example-spring-boot-starter-web/src/main/resources/application.properties @@ -1,5 +1,6 @@ openapi.validation.sample-rate=1 openapi.validation.specification-file-path=openapi.yaml +openapi.validation.violation-log-level= openapi.validation.excluded-paths=/_readiness,/_liveness,/_metrics openapi.validation.validation-report-throttle-wait-seconds=10 openapi.validation.validation-report-metric-name=openapi_error