From 46c83ba6bb503d0a833803b7e9265be9147a9731 Mon Sep 17 00:00:00 2001 From: Oleksandr Zhevedenko <720803+Net-burst@users.noreply.github.com> Date: Sat, 15 Feb 2025 18:02:22 -0500 Subject: [PATCH 1/3] Emit a metric for requests not carrying API access header --- .../cache/handlers/cache/CacheHandler.java | 16 +++++------ .../cache/handlers/cache/GetCacheHandler.java | 8 +++--- .../handlers/cache/PostCacheHandler.java | 11 ++++++-- .../prebid/cache/metrics/MeasurementTag.java | 28 +++++++++++++++++++ .../prebid/cache/metrics/MetricsRecorder.java | 27 +----------------- 5 files changed, 49 insertions(+), 41 deletions(-) create mode 100644 src/main/java/org/prebid/cache/metrics/MeasurementTag.java diff --git a/src/main/java/org/prebid/cache/handlers/cache/CacheHandler.java b/src/main/java/org/prebid/cache/handlers/cache/CacheHandler.java index 6d0bbca..de7585a 100644 --- a/src/main/java/org/prebid/cache/handlers/cache/CacheHandler.java +++ b/src/main/java/org/prebid/cache/handlers/cache/CacheHandler.java @@ -11,7 +11,7 @@ import org.prebid.cache.handlers.MetricsHandler; import org.prebid.cache.handlers.ServiceType; import org.prebid.cache.log.ConditionalLogger; -import org.prebid.cache.metrics.MetricsRecorder; +import org.prebid.cache.metrics.MeasurementTag; import org.prebid.cache.metrics.MetricsRecorder.MetricsRecorderTimer; import org.springframework.core.io.buffer.DataBufferLimitException; import org.springframework.http.HttpHeaders; @@ -69,7 +69,7 @@ Mono finalizeResult(final Mono mono, private Mono handleErrorMetrics(final Throwable error, final ServerRequest request) { if (error instanceof RepositoryException) { - recordMetric(MetricsRecorder.MeasurementTag.ERROR_DB); + recordMetric(MeasurementTag.ERROR_DB); } else if (error instanceof ResourceNotFoundException) { conditionalLogger.info( error.getMessage() @@ -79,7 +79,7 @@ private Mono handleErrorMetrics(final Throwable error, final Ser } else if (error instanceof BadRequestException) { log.error(error.getMessage()); } else if (error instanceof TimeoutException) { - metricsRecorder.markMeterForTag(this.metricTagPrefix, MetricsRecorder.MeasurementTag.ERROR_TIMEDOUT); + metricsRecorder.markMeterForTag(this.metricTagPrefix, MeasurementTag.ERROR_TIMED_OUT); } else if (error instanceof DataBufferLimitException) { final long contentLength = request.headers().contentLength().orElse(UNKNOWN_SIZE_VALUE); conditionalLogger.error( @@ -98,17 +98,17 @@ private void handleErrorStatusCodes(ServerRequest request, Signal createClientsCache(final int ttl, final in public Mono fetch(ServerRequest request) { // metrics - metricsRecorder.markMeterForTag(this.metricTagPrefix, MetricsRecorder.MeasurementTag.REQUEST); + metricsRecorder.markMeterForTag(this.metricTagPrefix, MeasurementTag.REQUEST); final var timerContext = metricsRecorder.createRequestTimerForServiceType(this.type); return request.queryParam(ID_KEY).map(id -> fetch(request, id, timerContext)).orElseGet(() -> { @@ -163,14 +164,13 @@ private Mono processRequest(final ServerRequest request, final S private Mono createServerResponse(final PayloadWrapper wrapper, final ServerRequest request) { if (wrapper.getPayload().getType().equals(PayloadType.JSON.toString())) { - metricsRecorder.markMeterForTag(this.metricTagPrefix, MetricsRecorder.MeasurementTag.JSON); + metricsRecorder.markMeterForTag(this.metricTagPrefix, MeasurementTag.JSON); return builder.createResponseMono(request, MediaType.APPLICATION_JSON_UTF8, wrapper); } else if (wrapper.getPayload().getType().equals(PayloadType.XML.toString())) { - metricsRecorder.markMeterForTag(this.metricTagPrefix, MetricsRecorder.MeasurementTag.XML); + metricsRecorder.markMeterForTag(this.metricTagPrefix, MeasurementTag.XML); return builder.createResponseMono(request, MediaType.APPLICATION_XML, wrapper); } return Mono.error(new UnsupportedMediaTypeException(UNSUPPORTED_MEDIATYPE)); } } - diff --git a/src/main/java/org/prebid/cache/handlers/cache/PostCacheHandler.java b/src/main/java/org/prebid/cache/handlers/cache/PostCacheHandler.java index 42867da..5b53d41 100644 --- a/src/main/java/org/prebid/cache/handlers/cache/PostCacheHandler.java +++ b/src/main/java/org/prebid/cache/handlers/cache/PostCacheHandler.java @@ -14,6 +14,7 @@ import org.prebid.cache.handlers.ErrorHandler; import org.prebid.cache.handlers.ServiceType; import org.prebid.cache.helpers.RandomUUID; +import org.prebid.cache.metrics.MeasurementTag; import org.prebid.cache.metrics.MetricsRecorder; import org.prebid.cache.model.Payload; import org.prebid.cache.model.PayloadTransfer; @@ -89,7 +90,7 @@ public Mono save(final ServerRequest request) { return ServerResponse.status(HttpStatus.UNAUTHORIZED).build(); } - metricsRecorder.markMeterForTag(this.metricTagPrefix, MetricsRecorder.MeasurementTag.REQUEST); + metricsRecorder.markMeterForTag(this.metricTagPrefix, MeasurementTag.REQUEST); final var timerContext = metricsRecorder.createRequestTimerForServiceType(type); String secondaryCache = request.queryParam(SECONDARY_CACHE_KEY).orElse(StringUtils.EMPTY); @@ -129,8 +130,12 @@ public Mono save(final ServerRequest request) { } private boolean isWriteAllowed(final ServerRequest request) { - return !apiConfig.isCacheWriteSecured() - || StringUtils.equals(request.headers().firstHeader(API_KEY_HEADER), apiConfig.getApiKey()); + final boolean isValidApiKey = StringUtils.equals(request.headers().firstHeader(API_KEY_HEADER), + apiConfig.getApiKey()); + if (!isValidApiKey) { + metricsRecorder.markMeterForTag(metricTagPrefix, MeasurementTag.UNAUTHORIZED_WRITE); + } + return !apiConfig.isCacheWriteSecured() || isValidApiKey; } private Function payloadWrapperTransformer() { diff --git a/src/main/java/org/prebid/cache/metrics/MeasurementTag.java b/src/main/java/org/prebid/cache/metrics/MeasurementTag.java new file mode 100644 index 0000000..7f04e1d --- /dev/null +++ b/src/main/java/org/prebid/cache/metrics/MeasurementTag.java @@ -0,0 +1,28 @@ +package org.prebid.cache.metrics; + +import lombok.Getter; + +@Getter +public enum MeasurementTag { + REQUEST_DURATION("pbc.${prefix}.request.duration"), + REQUEST("pbc.${prefix}.request"), + ERROR_UNKNOWN("pbc.${prefix}.err.unknown"), + ERROR_TIMED_OUT("pbc.${prefix}.err.timedOut"), + ERROR_MISSING_ID("pbc.${prefix}.err.missingId"), + ERROR_BAD_REQUEST("pbc.${prefix}.err.badRequest"), + REQUEST_INVALID("pbc.request.invalid"), + JSON("pbc.${prefix}.json"), + XML("pbc.${prefix}.xml"), + ERROR_DB("pbc.${prefix}.err.db"), + ERROR_SECONDARY_WRITE("pbc.err.secondaryWrite"), + ERROR_EXISTING_ID("pbc.err.existingId"), + PROXY_SUCCESS("pbc.proxy.success"), + PROXY_FAILURE("pbc.proxy.failure"), + UNAUTHORIZED_WRITE("pbc.${prefix}.unauthorizedWrite"); + + private final String tag; + + MeasurementTag(final String tag) { + this.tag = tag; + } +} diff --git a/src/main/java/org/prebid/cache/metrics/MetricsRecorder.java b/src/main/java/org/prebid/cache/metrics/MetricsRecorder.java index 02eac81..bda7c1c 100644 --- a/src/main/java/org/prebid/cache/metrics/MetricsRecorder.java +++ b/src/main/java/org/prebid/cache/metrics/MetricsRecorder.java @@ -3,7 +3,6 @@ import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Timer; -import lombok.Getter; import org.prebid.cache.handlers.ServiceType; import org.springframework.stereotype.Component; @@ -18,30 +17,6 @@ public MetricsRecorder(MeterRegistry meterRegistry) { this.meterRegistry = meterRegistry; } - public enum MeasurementTag { - REQUEST_DURATION("pbc.${prefix}.request.duration"), - REQUEST("pbc.${prefix}.request"), - ERROR_UNKNOWN("pbc.${prefix}.err.unknown"), - ERROR_TIMEDOUT("pbc.${prefix}.err.timedOut"), - ERROR_MISSINGID("pbc.${prefix}.err.missingId"), - ERROR_BAD_REQUEST("pbc.${prefix}.err.badRequest"), - REQUEST_INVALID("pbc.request.invalid"), - JSON("pbc.${prefix}.json"), - XML("pbc.${prefix}.xml"), - ERROR_DB("pbc.${prefix}.err.db"), - ERROR_SECONDARY_WRITE("pbc.err.secondaryWrite"), - ERROR_EXISTINGID("pbc.err.existingId"), - PROXY_SUCCESS("pbc.proxy.success"), - PROXY_FAILURE("pbc.proxy.failure"); - - @Getter - private final String tag; - - MeasurementTag(final String tag) { - this.tag = tag; - } - } - public class MetricsRecorderTimer { private final Timer timer; private final Timer.Sample sample; @@ -65,7 +40,7 @@ public Counter getSecondaryCacheWriteError() { } public Counter getExistingKeyError() { - return meterRegistry.counter(MeasurementTag.ERROR_EXISTINGID.getTag()); + return meterRegistry.counter(MeasurementTag.ERROR_EXISTING_ID.getTag()); } public Counter getProxySuccess() { From 6383f54d3fa980d699695e2b9d65817b7008d2b6 Mon Sep 17 00:00:00 2001 From: Oleksandr Zhevedenko <720803+Net-burst@users.noreply.github.com> Date: Mon, 17 Feb 2025 21:33:02 -0500 Subject: [PATCH 2/3] Remarks --- .../cache/handlers/cache/PostCacheHandler.java | 17 +++++++++-------- .../prebid/cache/metrics/MeasurementTag.java | 9 +++++---- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/prebid/cache/handlers/cache/PostCacheHandler.java b/src/main/java/org/prebid/cache/handlers/cache/PostCacheHandler.java index 5b53d41..ddfa6ca 100644 --- a/src/main/java/org/prebid/cache/handlers/cache/PostCacheHandler.java +++ b/src/main/java/org/prebid/cache/handlers/cache/PostCacheHandler.java @@ -86,7 +86,13 @@ public PostCacheHandler(final ReactiveRepository reposit } public Mono save(final ServerRequest request) { - if (!isWriteAllowed(request)) { + final boolean isValidApiKey = isValidApiKey(request); + if (!isValidApiKey) { + metricsRecorder.markMeterForTag(metricTagPrefix, MeasurementTag.NO_API_KEY); + } + + if (apiConfig.isCacheWriteSecured() && !isValidApiKey) { + metricsRecorder.markMeterForTag(metricTagPrefix, MeasurementTag.ERROR_UNAUTHORIZED); return ServerResponse.status(HttpStatus.UNAUTHORIZED).build(); } @@ -129,13 +135,8 @@ public Mono save(final ServerRequest request) { return finalizeResult(responseMono, request, timerContext); } - private boolean isWriteAllowed(final ServerRequest request) { - final boolean isValidApiKey = StringUtils.equals(request.headers().firstHeader(API_KEY_HEADER), - apiConfig.getApiKey()); - if (!isValidApiKey) { - metricsRecorder.markMeterForTag(metricTagPrefix, MeasurementTag.UNAUTHORIZED_WRITE); - } - return !apiConfig.isCacheWriteSecured() || isValidApiKey; + private boolean isValidApiKey(final ServerRequest request) { + return StringUtils.equals(request.headers().firstHeader(API_KEY_HEADER), apiConfig.getApiKey()); } private Function payloadWrapperTransformer() { diff --git a/src/main/java/org/prebid/cache/metrics/MeasurementTag.java b/src/main/java/org/prebid/cache/metrics/MeasurementTag.java index 7f04e1d..53eb914 100644 --- a/src/main/java/org/prebid/cache/metrics/MeasurementTag.java +++ b/src/main/java/org/prebid/cache/metrics/MeasurementTag.java @@ -6,19 +6,20 @@ public enum MeasurementTag { REQUEST_DURATION("pbc.${prefix}.request.duration"), REQUEST("pbc.${prefix}.request"), + NO_API_KEY("pbc.${prefix}.noApiKey"), + REQUEST_INVALID("pbc.request.invalid"), ERROR_UNKNOWN("pbc.${prefix}.err.unknown"), ERROR_TIMED_OUT("pbc.${prefix}.err.timedOut"), ERROR_MISSING_ID("pbc.${prefix}.err.missingId"), ERROR_BAD_REQUEST("pbc.${prefix}.err.badRequest"), - REQUEST_INVALID("pbc.request.invalid"), + ERROR_UNAUTHORIZED("pbc.${prefix}.err.unauthorized"), + ERROR_DB("pbc.${prefix}.err.db"), JSON("pbc.${prefix}.json"), XML("pbc.${prefix}.xml"), - ERROR_DB("pbc.${prefix}.err.db"), ERROR_SECONDARY_WRITE("pbc.err.secondaryWrite"), ERROR_EXISTING_ID("pbc.err.existingId"), PROXY_SUCCESS("pbc.proxy.success"), - PROXY_FAILURE("pbc.proxy.failure"), - UNAUTHORIZED_WRITE("pbc.${prefix}.unauthorizedWrite"); + PROXY_FAILURE("pbc.proxy.failure"); private final String tag; From ea3eada823c1e2b9a3bdb167348443a8ae45b924 Mon Sep 17 00:00:00 2001 From: Oleksandr Zhevedenko <720803+Net-burst@users.noreply.github.com> Date: Mon, 17 Feb 2025 21:42:21 -0500 Subject: [PATCH 3/3] Flip untrusted call metric to make it more obvious --- .../org/prebid/cache/handlers/cache/PostCacheHandler.java | 4 ++-- src/main/java/org/prebid/cache/metrics/MeasurementTag.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/prebid/cache/handlers/cache/PostCacheHandler.java b/src/main/java/org/prebid/cache/handlers/cache/PostCacheHandler.java index ddfa6ca..313eff8 100644 --- a/src/main/java/org/prebid/cache/handlers/cache/PostCacheHandler.java +++ b/src/main/java/org/prebid/cache/handlers/cache/PostCacheHandler.java @@ -87,8 +87,8 @@ public PostCacheHandler(final ReactiveRepository reposit public Mono save(final ServerRequest request) { final boolean isValidApiKey = isValidApiKey(request); - if (!isValidApiKey) { - metricsRecorder.markMeterForTag(metricTagPrefix, MeasurementTag.NO_API_KEY); + if (isValidApiKey) { + metricsRecorder.markMeterForTag(metricTagPrefix, MeasurementTag.REQUEST_TRUSTED); } if (apiConfig.isCacheWriteSecured() && !isValidApiKey) { diff --git a/src/main/java/org/prebid/cache/metrics/MeasurementTag.java b/src/main/java/org/prebid/cache/metrics/MeasurementTag.java index 53eb914..4b87e9e 100644 --- a/src/main/java/org/prebid/cache/metrics/MeasurementTag.java +++ b/src/main/java/org/prebid/cache/metrics/MeasurementTag.java @@ -6,7 +6,7 @@ public enum MeasurementTag { REQUEST_DURATION("pbc.${prefix}.request.duration"), REQUEST("pbc.${prefix}.request"), - NO_API_KEY("pbc.${prefix}.noApiKey"), + REQUEST_TRUSTED("pbc.${prefix}.trustedRequest"), REQUEST_INVALID("pbc.request.invalid"), ERROR_UNKNOWN("pbc.${prefix}.err.unknown"), ERROR_TIMED_OUT("pbc.${prefix}.err.timedOut"),