Skip to content

Commit 93b2d3a

Browse files
authored
Core: Replace dropwizard with micrometer (#97)
1 parent 0b9032a commit 93b2d3a

17 files changed

+213
-249
lines changed

README.md

+16-11
Original file line numberDiff line numberDiff line change
@@ -181,12 +181,12 @@ public class CustomPropertyConfiguration
181181

182182
### _Metrics_
183183

184-
Currently, there is support for the capturing of metrics using _Graphite_.
185-
For more information, see: https://graphite.readthedocs.io/en/latest/
184+
Metrics are collected and exported using _Micrometer_.
185+
For more information, see: https://micrometer.io
186186

187187
###### A. Durations (timers) and Rates (meters)
188188

189-
The metrics registory supports collection on these types:
189+
Alongside the default application health metrics exported by the Spring Actuator, the metrics repository supports collection on these types:
190190
* _request and request duration_
191191
* _json request_
192192
* _xml request_
@@ -196,17 +196,22 @@ The metrics registory supports collection on these types:
196196
* _internal server error_
197197

198198

199-
###### B. Graphite YAML Configuration
200-
A carbon-cache daemon needs to be running on the _Graphite_ host for collection to happen. In addition, the sending of metrics is batched for every minute. Connection details such as host / port will need to be specified in the configuration.
199+
###### B. Micrometer YAML Configuration
200+
201+
The full list of supported monitoring systems that Micrometer can export to can be found here: https://micrometer.io/docs
202+
Please keep in mind that for some of them, additional dependencies may be needed in pom.xml
201203

202204
_src/main/resources/repository.yml_:
203205
```yaml
204-
metrics:
205-
graphite:
206-
enabled: true
207-
host: http://graphite.yourdomain.com
208-
port: 2003
209-
prefix: prebid
206+
management:
207+
metrics:
208+
export:
209+
graphite:
210+
enabled: false
211+
host: http://graphite.yourdomain.com
212+
port: 2003
213+
tags-as-prefix:
214+
- prebid
210215
```
211216
212217
### _Logging_

pom.xml

+3-3
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,9 @@
152152
<scope>provided</scope>
153153
</dependency>
154154
<dependency>
155-
<groupId>io.dropwizard.metrics</groupId>
156-
<artifactId>metrics-graphite</artifactId>
157-
<version>${metrics-graphite.version}</version>
155+
<groupId>io.micrometer</groupId>
156+
<artifactId>micrometer-registry-graphite</artifactId>
157+
<version>${micrometer.version}</version>
158158
</dependency>
159159
<dependency>
160160
<groupId>javax.el</groupId>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.prebid.cache.config;
2+
3+
import io.micrometer.core.instrument.MeterRegistry;
4+
import io.micrometer.core.instrument.config.NamingConvention;
5+
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
6+
import org.springframework.context.annotation.Bean;
7+
import org.springframework.context.annotation.Configuration;
8+
9+
@Configuration
10+
public class MetricsConfig {
11+
12+
@Bean
13+
MeterRegistryCustomizer<MeterRegistry> identityNamingConventionMeterCustomizer() {
14+
// To preserve metric names as they defined in code
15+
return registry -> registry.config().namingConvention(NamingConvention.identity);
16+
}
17+
}

src/main/java/org/prebid/cache/handlers/CacheHandler.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.prebid.cache.handlers;
22

3-
import com.codahale.metrics.Timer;
43
import lombok.extern.slf4j.Slf4j;
54
import org.apache.commons.lang3.exception.ExceptionUtils;
65
import org.prebid.cache.exceptions.BadRequestException;
@@ -11,6 +10,7 @@
1110
import org.prebid.cache.exceptions.ResourceNotFoundException;
1211
import org.prebid.cache.exceptions.UnsupportedMediaTypeException;
1312
import org.prebid.cache.metrics.MetricsRecorder;
13+
import org.prebid.cache.metrics.MetricsRecorder.MetricsRecorderTimer;
1414
import org.springframework.http.HttpMethod;
1515
import org.springframework.http.HttpStatus;
1616
import org.springframework.web.reactive.function.server.ServerRequest;
@@ -103,7 +103,7 @@ private Mono<ServerResponse> handleErrorMetrics(final Throwable error,
103103

104104
Mono<ServerResponse> finalizeResult(final Mono<ServerResponse> mono,
105105
final ServerRequest request,
106-
final Timer.Context timerContext) {
106+
final MetricsRecorderTimer timerContext) {
107107
// transform to error, if needed and send metrics
108108
return mono.onErrorResume(throwable -> handleErrorMetrics(throwable, request))
109109
.doAfterSuccessOrError((v, t) -> {
@@ -118,7 +118,7 @@ void applyMetrics(Throwable t) {
118118
}
119119

120120
if (t instanceof DuplicateKeyException) {
121-
metricsRecorder.getExistingKeyError().mark();
121+
metricsRecorder.getExistingKeyError().increment();
122122
}
123123
}
124124
}

src/main/java/org/prebid/cache/handlers/ErrorHandler.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import org.prebid.cache.builders.PrebidServerResponseBuilder;
55
import org.prebid.cache.exceptions.BadRequestException;
66
import org.prebid.cache.exceptions.ResourceNotFoundException;
7-
import org.prebid.cache.metrics.GraphiteMetricsRecorder;
7+
import org.prebid.cache.metrics.MetricsRecorder;
88
import org.springframework.beans.factory.annotation.Autowired;
99
import org.springframework.stereotype.Component;
1010
import org.springframework.web.reactive.function.server.ServerRequest;
@@ -20,7 +20,7 @@ public class ErrorHandler extends MetricsHandler {
2020
private static final String NO_ELEMENTS_FOUND = "No Elements Found.";
2121

2222
@Autowired
23-
public ErrorHandler(final GraphiteMetricsRecorder metricsRecorder, final PrebidServerResponseBuilder builder) {
23+
public ErrorHandler(final MetricsRecorder metricsRecorder, final PrebidServerResponseBuilder builder) {
2424
this.metricsRecorder = metricsRecorder;
2525
this.builder = builder;
2626
}
@@ -38,7 +38,7 @@ static Mono<ServerResponse> createNoElementsFound() {
3838
}
3939

4040
public Mono<ServerResponse> invalidRequest(final ServerRequest request) {
41-
metricsRecorder.getInvalidRequestMeter().mark();
41+
metricsRecorder.getInvalidRequestMeter().increment();
4242
return builder.error(Mono.just(new ResourceNotFoundException(RESOURCE_NOT_FOUND_BAD_URL)), request);
4343
}
4444
}

src/main/java/org/prebid/cache/handlers/GetCacheHandler.java

+38-50
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.prebid.cache.handlers;
22

3-
import com.codahale.metrics.Timer;
43
import com.github.benmanes.caffeine.cache.Caffeine;
54
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
65
import io.github.resilience4j.reactor.circuitbreaker.operator.CircuitBreakerOperator;
@@ -10,8 +9,8 @@
109
import org.apache.http.client.utils.URIBuilder;
1110
import org.prebid.cache.builders.PrebidServerResponseBuilder;
1211
import org.prebid.cache.exceptions.UnsupportedMediaTypeException;
13-
import org.prebid.cache.metrics.GraphiteMetricsRecorder;
1412
import org.prebid.cache.metrics.MetricsRecorder;
13+
import org.prebid.cache.metrics.MetricsRecorder.MetricsRecorderTimer;
1514
import org.prebid.cache.model.PayloadWrapper;
1615
import org.prebid.cache.repository.CacheConfig;
1716
import org.prebid.cache.repository.ReactiveRepository;
@@ -47,7 +46,7 @@ public class GetCacheHandler extends CacheHandler {
4746
public GetCacheHandler(final ReactiveRepository<PayloadWrapper, String> repository,
4847
final CacheConfig config,
4948
final ApiConfig apiConfig,
50-
final GraphiteMetricsRecorder metricsRecorder,
49+
final MetricsRecorder metricsRecorder,
5150
final PrebidServerResponseBuilder builder,
5251
final CircuitBreaker circuitBreaker) {
5352
this.metricsRecorder = metricsRecorder;
@@ -72,8 +71,7 @@ private static Map<String, WebClient> createClientsCache(final int ttl, final in
7271
public Mono<ServerResponse> fetch(ServerRequest request) {
7372
// metrics
7473
metricsRecorder.markMeterForTag(this.metricTagPrefix, MetricsRecorder.MeasurementTag.REQUEST);
75-
final var timerContext =
76-
metricsRecorder.createRequestContextTimerOptionalForServiceType(this.type).orElse(null);
74+
final var timerContext = metricsRecorder.createRequestTimerForServiceType(this.type);
7775

7876
return request.queryParam(ID_KEY).map(id -> fetch(request, id, timerContext)).orElseGet(() -> {
7977
final var responseMono = ErrorHandler.createInvalidParameters();
@@ -83,14 +81,14 @@ public Mono<ServerResponse> fetch(ServerRequest request) {
8381

8482
private Mono<ServerResponse> fetch(final ServerRequest request,
8583
final String id,
86-
final Timer.Context timerContext) {
84+
final MetricsRecorderTimer timerContext) {
8785

8886
final var cacheUrl = resolveCacheUrl(request);
8987

9088
final var responseMono =
9189
StringUtils.containsIgnoreCase(cacheUrl, config.getAllowedProxyHost())
92-
? processProxyRequest(request, id, cacheUrl)
93-
: processRequest(request, id);
90+
? processProxyRequest(request, id, cacheUrl)
91+
: processRequest(request, id);
9492

9593
return finalizeResult(responseMono, request, timerContext);
9694
}
@@ -99,10 +97,10 @@ private String resolveCacheUrl(final ServerRequest request) {
9997
final var cacheHostParam = request.queryParam(CACHE_HOST_KEY).orElse(null);
10098
if (StringUtils.isNotBlank(cacheHostParam)) {
10199
return new URIBuilder()
102-
.setHost(cacheHostParam)
103-
.setPath(apiConfig.getPath())
104-
.setScheme(config.getHostParamProtocol())
105-
.toString();
100+
.setHost(cacheHostParam)
101+
.setPath(apiConfig.getPath())
102+
.setScheme(config.getHostParamProtocol())
103+
.toString();
106104
}
107105

108106
return null;
@@ -115,66 +113,56 @@ private Mono<ServerResponse> processProxyRequest(final ServerRequest request,
115113
final var webClient = clientsCache.computeIfAbsent(cacheUrl, WebClient::create);
116114

117115
return webClient.get()
118-
.uri(uriBuilder -> uriBuilder.queryParam(ID_KEY, idKeyParam).build())
119-
.headers(httpHeaders -> httpHeaders.addAll(request.headers().asHttpHeaders()))
120-
.exchange()
121-
.transform(CircuitBreakerOperator.of(circuitBreaker))
122-
.timeout(Duration.ofMillis(config.getTimeoutMs()))
123-
.subscribeOn(Schedulers.parallel())
124-
.handle(this::updateProxyMetrics)
125-
.flatMap(GetCacheHandler::fromClientResponse)
126-
.doOnError(error -> {
127-
metricsRecorder.getProxyFailure().mark();
128-
log.info("Failed to send request: '{}', cause: '{}'",
129-
ExceptionUtils.getMessage(error), ExceptionUtils.getMessage(error));
130-
131-
});
116+
.uri(uriBuilder -> uriBuilder.queryParam(ID_KEY, idKeyParam).build())
117+
.headers(httpHeaders -> httpHeaders.addAll(request.headers().asHttpHeaders()))
118+
.exchange()
119+
.transform(CircuitBreakerOperator.of(circuitBreaker))
120+
.timeout(Duration.ofMillis(config.getTimeoutMs()))
121+
.subscribeOn(Schedulers.parallel())
122+
.handle(this::updateProxyMetrics)
123+
.flatMap(GetCacheHandler::fromClientResponse)
124+
.doOnError(error -> {
125+
metricsRecorder.getProxyFailure().increment();
126+
log.info("Failed to send request: '{}', cause: '{}'",
127+
ExceptionUtils.getMessage(error), ExceptionUtils.getMessage(error));
128+
});
132129
}
133130

134131
private void updateProxyMetrics(final ClientResponse clientResponse,
135132
final SynchronousSink<ClientResponse> sink) {
136133
if (HttpStatus.OK.equals(clientResponse.statusCode())) {
137-
metricsRecorder.getProxySuccess().mark();
134+
metricsRecorder.getProxySuccess().increment();
138135
} else {
139-
metricsRecorder.getProxyFailure().mark();
136+
metricsRecorder.getProxyFailure().increment();
140137
}
141138

142139
sink.next(clientResponse);
143140
}
144141

145142
private static Mono<ServerResponse> fromClientResponse(final ClientResponse clientResponse) {
146143
return ServerResponse.status(clientResponse.statusCode())
147-
.headers(headerConsumer -> clientResponse.headers().asHttpHeaders().forEach(headerConsumer::addAll))
148-
.body(clientResponse.bodyToMono(String.class), String.class);
144+
.headers(headerConsumer -> clientResponse.headers().asHttpHeaders().forEach(headerConsumer::addAll))
145+
.body(clientResponse.bodyToMono(String.class), String.class);
149146
}
150147

151148
private Mono<ServerResponse> processRequest(final ServerRequest request, final String keyIdParam) {
152149
final var normalizedId = String.format("%s%s", config.getPrefix(), keyIdParam);
153150
return repository.findById(normalizedId)
154-
.transform(CircuitBreakerOperator.of(circuitBreaker))
155-
.timeout(Duration.ofMillis(config.getTimeoutMs()))
156-
.subscribeOn(Schedulers.parallel())
157-
.transform(this::validateErrorResult)
158-
.flatMap(wrapper -> createServerResponse(wrapper, request))
159-
.switchIfEmpty(ErrorHandler.createResourceNotFound(normalizedId));
151+
.transform(CircuitBreakerOperator.of(circuitBreaker))
152+
.timeout(Duration.ofMillis(config.getTimeoutMs()))
153+
.subscribeOn(Schedulers.parallel())
154+
.transform(this::validateErrorResult)
155+
.flatMap(wrapper -> createServerResponse(wrapper, request))
156+
.switchIfEmpty(ErrorHandler.createResourceNotFound(normalizedId));
160157
}
161158

162159
private Mono<ServerResponse> createServerResponse(final PayloadWrapper wrapper, final ServerRequest request) {
163-
164160
if (wrapper.getPayload().getType().equals(PayloadType.JSON.toString())) {
165-
metricsRecorder.markMeterForTag(this.metricTagPrefix,
166-
MetricsRecorder.MeasurementTag.JSON);
167-
return builder.createResponseMono(request,
168-
MediaType.APPLICATION_JSON_UTF8,
169-
wrapper);
170-
} else if (wrapper.getPayload()
171-
.getType()
172-
.equals(PayloadType.XML.toString())) {
173-
metricsRecorder.markMeterForTag(this.metricTagPrefix,
174-
MetricsRecorder.MeasurementTag.XML);
175-
return builder.createResponseMono(request,
176-
MediaType.APPLICATION_XML,
177-
wrapper);
161+
metricsRecorder.markMeterForTag(this.metricTagPrefix, MetricsRecorder.MeasurementTag.JSON);
162+
return builder.createResponseMono(request, MediaType.APPLICATION_JSON_UTF8, wrapper);
163+
} else if (wrapper.getPayload().getType().equals(PayloadType.XML.toString())) {
164+
metricsRecorder.markMeterForTag(this.metricTagPrefix, MetricsRecorder.MeasurementTag.XML);
165+
return builder.createResponseMono(request, MediaType.APPLICATION_XML, wrapper);
178166
}
179167

180168
return Mono.error(new UnsupportedMediaTypeException(UNSUPPORTED_MEDIATYPE));
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package org.prebid.cache.handlers;
22

33
import org.prebid.cache.builders.PrebidServerResponseBuilder;
4-
import org.prebid.cache.metrics.GraphiteMetricsRecorder;
4+
import org.prebid.cache.metrics.MetricsRecorder;
55

66
abstract class MetricsHandler {
7-
GraphiteMetricsRecorder metricsRecorder;
7+
MetricsRecorder metricsRecorder;
88
PrebidServerResponseBuilder builder;
99
}

src/main/java/org/prebid/cache/handlers/PostCacheHandler.java

+4-6
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import org.prebid.cache.exceptions.InvalidUUIDException;
1313
import org.prebid.cache.exceptions.RequestBodyDeserializeException;
1414
import org.prebid.cache.helpers.RandomUUID;
15-
import org.prebid.cache.metrics.GraphiteMetricsRecorder;
1615
import org.prebid.cache.metrics.MetricsRecorder;
1716
import org.prebid.cache.model.Payload;
1817
import org.prebid.cache.model.PayloadTransfer;
@@ -63,7 +62,7 @@ public class PostCacheHandler extends CacheHandler {
6362
@Autowired
6463
public PostCacheHandler(final ReactiveRepository<PayloadWrapper, String> repository,
6564
final CacheConfig config,
66-
final GraphiteMetricsRecorder metricsRecorder,
65+
final MetricsRecorder metricsRecorder,
6766
final PrebidServerResponseBuilder builder,
6867
final Supplier<Date> currentDateProvider,
6968
final CircuitBreaker circuitBreaker) {
@@ -82,8 +81,7 @@ public PostCacheHandler(final ReactiveRepository<PayloadWrapper, String> reposit
8281

8382
public Mono<ServerResponse> save(final ServerRequest request) {
8483
metricsRecorder.markMeterForTag(this.metricTagPrefix, MetricsRecorder.MeasurementTag.REQUEST);
85-
final var timerContext = metricsRecorder.createRequestContextTimerOptionalForServiceType(type)
86-
.orElse(null);
84+
final var timerContext = metricsRecorder.createRequestTimerForServiceType(type);
8785

8886
String secondaryCache = request.queryParam(SECONDARY_CACHE_KEY).orElse(StringUtils.EMPTY);
8987

@@ -182,13 +180,13 @@ private void sendRequestToSecondaryPrebidCacheHosts(List<PayloadWrapper> payload
182180
.syncBody(requestObject)
183181
.exchange()
184182
.doOnError(throwable -> {
185-
metricsRecorder.getSecondaryCacheWriteError().mark();
183+
metricsRecorder.getSecondaryCacheWriteError().increment();
186184
log.info("Failed to send request: '{}', cause: '{}'",
187185
ExceptionUtils.getMessage(throwable), ExceptionUtils.getMessage(throwable));
188186
})
189187
.subscribe(clientResponse -> {
190188
if (clientResponse.statusCode() != HttpStatus.OK) {
191-
metricsRecorder.getSecondaryCacheWriteError().mark();
189+
metricsRecorder.getSecondaryCacheWriteError().increment();
192190
log.debug(clientResponse.statusCode().toString());
193191
log.info("Failed to write to remote address : {}", ip);
194192
}

src/main/java/org/prebid/cache/metrics/GraphiteConfig.java

-19
This file was deleted.

0 commit comments

Comments
 (0)