Skip to content

Commit 042dcf0

Browse files
authored
feature: Provide custom MetricTags during runtime (#111)
1 parent dfa62a8 commit 042dcf0

File tree

6 files changed

+60
-8
lines changed

6 files changed

+60
-8
lines changed

README.md

+14
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,20 @@ public class ViolationExclusionsExample implements ViolationExclusions {
222222
}
223223
```
224224

225+
### Provide metric tags at runtime
226+
Sometimes you want to generate your own metric tags based on the violation.
227+
This can be achieved as demonstrated in the following snippet.
228+
229+
```java
230+
@Component
231+
public class MetricTagProviderExample implements MetricTagProvider {
232+
@Override
233+
public List<MetricTag> getTagsForViolation(OpenApiViolation violation) {
234+
return List.of(new MetricTag("rule", violation.getRule()));
235+
}
236+
}
237+
```
238+
225239
## Examples
226240
Run examples with `./gradlew :examples:example-spring-boot-starter-web:bootRun` or `./gradlew :examples:example-spring-boot-starter-webflux:bootRun`.
227241

examples/example-spring-boot-starter-web/build.gradle

+8-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,14 @@ plugins {
99
dependencies {
1010
implementation project(':examples:examples-common')
1111
implementation project(':spring-boot-starter:spring-boot-starter-web')
12-
implementation 'org.springframework.boot:spring-boot-starter-web'
12+
implementation('org.springframework.boot:spring-boot-starter-web') {
13+
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
14+
exclude group: 'io.undertow', module: 'undertow-websockets-jsr'
15+
}
16+
17+
implementation 'org.springframework.boot:spring-boot-starter-undertow'
18+
implementation 'org.springframework.boot:spring-boot-starter-validation'
19+
implementation 'org.hibernate.validator:hibernate-validator'
1320

1421
implementation 'org.springframework.boot:spring-boot-starter-validation'
1522
implementation(libs.openapi.tools.jacksonDatabindNullable)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.getyourguide.openapi.validation.api.metrics;
2+
3+
import com.getyourguide.openapi.validation.api.model.OpenApiViolation;
4+
import java.util.List;
5+
6+
public interface MetricTagProvider {
7+
List<MetricTag> getTagsForViolation(OpenApiViolation violation);
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.getyourguide.openapi.validation.api.metrics;
2+
3+
import com.getyourguide.openapi.validation.api.model.OpenApiViolation;
4+
import java.util.List;
5+
6+
public class NullMetricTagProvider implements MetricTagProvider {
7+
@Override
8+
public List<MetricTag> getTagsForViolation(OpenApiViolation violation) {
9+
return List.of();
10+
}
11+
}

openapi-validation-api/src/main/java/com/getyourguide/openapi/validation/api/metrics/DefaultMetricsReporter.java openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/metrics/DefaultMetricsReporter.java

+11-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
package com.getyourguide.openapi.validation.api.metrics;
1+
package com.getyourguide.openapi.validation.core.metrics;
22

33
import com.getyourguide.openapi.validation.api.log.LogLevel;
4+
import com.getyourguide.openapi.validation.api.metrics.MetricTag;
5+
import com.getyourguide.openapi.validation.api.metrics.MetricTagProvider;
6+
import com.getyourguide.openapi.validation.api.metrics.MetricsReporter;
47
import com.getyourguide.openapi.validation.api.metrics.client.MetricsClient;
58
import com.getyourguide.openapi.validation.api.model.OpenApiViolation;
69
import java.util.ArrayList;
@@ -13,6 +16,7 @@
1316
public class DefaultMetricsReporter implements MetricsReporter {
1417

1518
private final MetricsClient metricsClient;
19+
private final MetricTagProvider metricTagProvider;
1620
private final Configuration configuration;
1721

1822
@Override
@@ -49,7 +53,8 @@ private MetricTag[] createTagsForViolation(OpenApiViolation violation) {
4953
violation.getResponseStatus()
5054
.ifPresent(responseStatus -> tags.add(new MetricTag("status", responseStatus.toString())));
5155

52-
addAdditionalTags(tags);
56+
tags.addAll(getMetricTagsFromConfiguration());
57+
tags.addAll(metricTagProvider.getTagsForViolation(violation));
5358

5459
return tags.toArray(MetricTag[]::new);
5560
}
@@ -64,15 +69,16 @@ private MetricTag[] createTagsForStartup(
6469
tags.add(new MetricTag("validation_enabled", String.valueOf(isValidationEnabled)));
6570
tags.add(new MetricTag("sample_rate", String.valueOf(sampleRate)));
6671
tags.add(new MetricTag("throttling", String.valueOf(validationReportThrottleWaitSeconds)));
67-
addAdditionalTags(tags);
72+
tags.addAll(getMetricTagsFromConfiguration());
6873

6974
return tags.toArray(MetricTag[]::new);
7075
}
7176

72-
private void addAdditionalTags(ArrayList<MetricTag> tags) {
77+
private List<MetricTag> getMetricTagsFromConfiguration() {
7378
if (configuration.getMetricAdditionalTags() != null) {
74-
tags.addAll(configuration.getMetricAdditionalTags());
79+
return configuration.getMetricAdditionalTags();
7580
}
81+
return List.of();
7682
}
7783

7884
@Builder

spring-boot-starter/spring-boot-starter-core/src/main/java/com/getyourguide/openapi/validation/autoconfigure/LibraryAutoConfiguration.java

+8-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
import com.getyourguide.openapi.validation.api.log.NoOpLoggerExtension;
99
import com.getyourguide.openapi.validation.api.log.OpenApiViolationHandler;
1010
import com.getyourguide.openapi.validation.api.log.ViolationLogger;
11-
import com.getyourguide.openapi.validation.api.metrics.DefaultMetricsReporter;
11+
import com.getyourguide.openapi.validation.api.metrics.MetricTagProvider;
1212
import com.getyourguide.openapi.validation.api.metrics.MetricsReporter;
13+
import com.getyourguide.openapi.validation.api.metrics.NullMetricTagProvider;
1314
import com.getyourguide.openapi.validation.api.metrics.client.MetricsClient;
1415
import com.getyourguide.openapi.validation.api.metrics.client.NoOpMetricsClient;
1516
import com.getyourguide.openapi.validation.api.model.ValidatorConfiguration;
@@ -22,6 +23,7 @@
2223
import com.getyourguide.openapi.validation.core.log.ExclusionsOpenApiViolationHandler;
2324
import com.getyourguide.openapi.validation.core.log.ThrottlingOpenApiViolationHandler;
2425
import com.getyourguide.openapi.validation.core.mapper.ValidationReportToOpenApiViolationsMapper;
26+
import com.getyourguide.openapi.validation.core.metrics.DefaultMetricsReporter;
2527
import java.util.Optional;
2628
import java.util.concurrent.LinkedBlockingQueue;
2729
import java.util.concurrent.ThreadPoolExecutor;
@@ -49,12 +51,16 @@ public ViolationLogger violationLogger(Optional<LoggerExtension> loggerExtension
4951

5052
@Bean
5153
@ConditionalOnMissingBean
52-
public MetricsReporter metricsReporter(Optional<MetricsClient> metricsClient) {
54+
public MetricsReporter metricsReporter(
55+
Optional<MetricsClient> metricsClient,
56+
Optional<MetricTagProvider> metricTagProvider
57+
) {
5358
var metricName = properties.getValidationReportMetricName() != null
5459
? properties.getValidationReportMetricName()
5560
: DEFAULT_METRIC_NAME;
5661
return new DefaultMetricsReporter(
5762
metricsClient.orElseGet(NoOpMetricsClient::new),
63+
metricTagProvider.orElseGet(NullMetricTagProvider::new),
5864
DefaultMetricsReporter.Configuration.builder()
5965
.metricName(metricName)
6066
.metricAdditionalTags(properties.getValidationReportMetricAdditionalTags())

0 commit comments

Comments
 (0)