diff --git a/src/main/java/app/coronawarn/testresult/config/TestResultConfig.java b/src/main/java/app/coronawarn/testresult/config/TestResultConfig.java index d3d4f87..7e3fce7 100644 --- a/src/main/java/app/coronawarn/testresult/config/TestResultConfig.java +++ b/src/main/java/app/coronawarn/testresult/config/TestResultConfig.java @@ -36,6 +36,7 @@ public class TestResultConfig { private Cleanup cleanup; private Signature signature; + private Monitoring monitoring; @Getter @Setter @@ -53,6 +54,14 @@ public static class Scheduled { } + @Getter + @Setter + public static class Monitoring { + + private Integer batchSize; + + } + @Getter @Setter public static class Signature { diff --git a/src/main/java/app/coronawarn/testresult/monitoring/BatchCounter.java b/src/main/java/app/coronawarn/testresult/monitoring/BatchCounter.java new file mode 100644 index 0000000..3860195 --- /dev/null +++ b/src/main/java/app/coronawarn/testresult/monitoring/BatchCounter.java @@ -0,0 +1,58 @@ +/*- + * ---license-start + * Corona-Warn-App + * --- + * Copyright (C) 2020 SAP SE and all other contributors + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package app.coronawarn.testresult.monitoring; + +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.MeterRegistry; +import java.util.concurrent.atomic.AtomicLong; + +/** + * Batch counter for counting requests for monitoring. Counts up in batches, given batch size. This way, single requests + * cannot be traced to semantics of the counter by comparing time stamps. + */ +public class BatchCounter { + + private static final String TESTRESULT_CONTROLLER_REQUESTS_COUNTER_NAME = "testresult_controller.test_requests"; + private static final String TESTRESULT_CONTROLLER_REQUESTS_COUNTER_DESCRIPTION + = "Requests to the test request Controller."; + + private final long batchSize; + private final Counter counter; + private final AtomicLong count = new AtomicLong(0L); + + BatchCounter(MeterRegistry meterRegistry, long batchSize, String type) { + this.batchSize = batchSize; + counter = Counter.builder(TESTRESULT_CONTROLLER_REQUESTS_COUNTER_NAME) + .tag("type", type) + .description(TESTRESULT_CONTROLLER_REQUESTS_COUNTER_DESCRIPTION) + .register(meterRegistry); + } + + /** + * Increments the {@link BatchCounter}. If the batch size is reached, it is provided to monitoring, else, the internal + * counter is incremented. + */ + public void increment() { + if (0 == count.incrementAndGet() % batchSize) { + counter.increment(batchSize); + } + } +} diff --git a/src/main/java/app/coronawarn/testresult/monitoring/TestRequestMonitor.java b/src/main/java/app/coronawarn/testresult/monitoring/TestRequestMonitor.java new file mode 100644 index 0000000..ce6f8db --- /dev/null +++ b/src/main/java/app/coronawarn/testresult/monitoring/TestRequestMonitor.java @@ -0,0 +1,89 @@ +/*- + * ---license-start + * Corona-Warn-App + * --- + * Copyright (C) 2020 SAP SE and all other contributors + * All modifications are copyright (c) 2020 Devside SRL. + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + +package app.coronawarn.testresult.monitoring; + +import app.coronawarn.testresult.config.TestResultConfig; +import io.micrometer.core.instrument.MeterRegistry; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * Provides functionality for monitoring the diagnosis key submission handling logic. + */ +@Component +@ConfigurationProperties(prefix = "services.submission.monitoring") +public class TestRequestMonitor { + + private final MeterRegistry meterRegistry; + private final long batchSize; + + private BatchCounter nonExistingTestRequests; + private BatchCounter dummyTestRequests; + private BatchCounter positiveResponses; + private BatchCounter negativeResponses; + + /** + * Constructor for {@link TestRequestMonitor}. Initializes all counters to 0 upon being called. + * + * @param meterRegistry the meterRegistry + */ + protected TestRequestMonitor( + MeterRegistry meterRegistry, TestResultConfig testResultConfig) { + this.meterRegistry = meterRegistry; + this.batchSize = testResultConfig.getMonitoring().getBatchSize(); + initializeCounters(); + } + + /** + * We count the following values. + * + */ + private void initializeCounters() { + nonExistingTestRequests = new BatchCounter(meterRegistry, batchSize, "nonexisting"); + dummyTestRequests = new BatchCounter(meterRegistry, batchSize, "dummy"); + positiveResponses = new BatchCounter(meterRegistry, batchSize, "positive"); + negativeResponses = new BatchCounter(meterRegistry, batchSize, "negative"); + } + + public void incrementNonExistingTestRequest() { + nonExistingTestRequests.increment(); + } + + public void incrementDummyTestRequest() { + dummyTestRequests.increment(); + } + + public void incrementPositiveTestResponse() { + positiveResponses.increment(); + } + + public void incrementNegativeTestResponse() { + negativeResponses.increment(); + } + + +} diff --git a/src/main/java/app/coronawarn/testresult/sciensano/TestResultController.java b/src/main/java/app/coronawarn/testresult/sciensano/TestResultController.java index d69372b..491a725 100644 --- a/src/main/java/app/coronawarn/testresult/sciensano/TestResultController.java +++ b/src/main/java/app/coronawarn/testresult/sciensano/TestResultController.java @@ -26,6 +26,7 @@ import app.coronawarn.testresult.entity.TestResultEntity; import static app.coronawarn.testresult.entity.TestResultEntity.dummyPendingResult; import app.coronawarn.testresult.model.MobileTestResultRequest; +import app.coronawarn.testresult.monitoring.TestRequestMonitor; import io.swagger.v3.oas.annotations.Operation; import java.time.LocalDate; import java.util.Optional; @@ -52,6 +53,8 @@ public class TestResultController { private final AuthorizationCodeService authorizationCodeService; + private final TestRequestMonitor testRequestMonitor; + /** *

* Get the test result response for a given mobileTestId and datePatientInfectious. @@ -78,7 +81,10 @@ public ResponseEntity pollMobileTestResult(@RequestBody @Valid ).ifPresent(tr -> { tr.setDateTestCommunicated(LocalDate.now()); if (tr.isPositive()) { + testRequestMonitor.incrementPositiveTestResponse(); authorizationCodeService.generateAndSaveAuthorizationCode(tr); + } else { + testRequestMonitor.incrementNegativeTestResponse(); } }); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 489dea8..0ba2419 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -74,6 +74,9 @@ testresult: authorizationcode: transfer: rate: 60000 # every minute + monitoring: + batch-size: 1 + cloud: aws: region: