This is an automated email from the ASF dual-hosted git repository. btellier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit cd883f2d37f2d0088b02dbe68af8395664a8bdb0 Author: datph <[email protected]> AuthorDate: Fri Mar 29 15:10:55 2019 +0700 JAMES-2706 Extract RecordingMetricFactory to introduce new metrics-tests module --- mailbox/store/pom.xml | 5 + .../james/mailbox/store/PreDeletionHooksTest.java | 65 +------------ metrics/metrics-tests/pom.xml | 72 +++++++++++++++ .../james/metrics/tests/RecordingMetric.java | 57 ++++++++++++ .../metrics/tests/RecordingMetricFactory.java | 61 ++++++++++++ .../james/metrics/tests/RecordingTimeMetric.java | 51 +++++++++++ .../metrics/tests/RecordingMetricFactoryTest.java | 102 +++++++++++++++++++++ metrics/pom.xml | 1 + pom.xml | 5 + 9 files changed, 358 insertions(+), 61 deletions(-) diff --git a/mailbox/store/pom.xml b/mailbox/store/pom.xml index 16dd512..a9741da 100644 --- a/mailbox/store/pom.xml +++ b/mailbox/store/pom.xml @@ -60,6 +60,11 @@ </dependency> <dependency> <groupId>${james.groupId}</groupId> + <artifactId>metrics-tests</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>${james.groupId}</groupId> <artifactId>james-core</artifactId> </dependency> <dependency> diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/PreDeletionHooksTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/PreDeletionHooksTest.java index 81ec41a..4e86487 100644 --- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/PreDeletionHooksTest.java +++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/PreDeletionHooksTest.java @@ -31,35 +31,25 @@ import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import java.time.Duration; -import java.util.Collection; import java.util.Date; -import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Consumer; import javax.mail.Flags; -import org.apache.commons.lang3.NotImplementedException; import org.apache.james.mailbox.MessageUid; import org.apache.james.mailbox.MetadataWithMailboxId; import org.apache.james.mailbox.extension.PreDeletionHook; import org.apache.james.mailbox.model.MessageMetaData; import org.apache.james.mailbox.model.TestId; import org.apache.james.mailbox.model.TestMessageId; -import org.apache.james.metrics.api.Metric; -import org.apache.james.metrics.api.MetricFactory; -import org.apache.james.metrics.api.TimeMetric; +import org.apache.james.metrics.tests.RecordingMetricFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.stubbing.Answer; import org.reactivestreams.Publisher; -import com.google.common.base.Stopwatch; -import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Multimap; -import com.google.common.collect.Multimaps; import reactor.core.publisher.Mono; @@ -77,53 +67,6 @@ class PreDeletionHooksTest { private PreDeletionHooks testee; private RecordingMetricFactory metricFactory; - public static class RecordingTimeMetric implements TimeMetric { - private final String name; - private final Stopwatch stopwatch = Stopwatch.createStarted(); - private final Consumer<Long> publishCallback; - - RecordingTimeMetric(String name, Consumer<Long> publishCallback) { - this.name = name; - this.publishCallback = publishCallback; - } - - @Override - public String name() { - return name; - } - - @Override - public long stopAndPublish() { - long elapsed = stopwatch.elapsed(TimeUnit.MILLISECONDS); - publishCallback.accept(elapsed); - return elapsed; - } - } - - public static class RecordingMetricFactory implements MetricFactory { - private final Multimap<String, Long> executionTimesInMs = Multimaps.synchronizedSetMultimap(HashMultimap.create()); - - @Override - public Metric generate(String name) { - throw new NotImplementedException("Not implemented"); - } - - @Override - public TimeMetric timer(String name) { - return new RecordingTimeMetric(name, executionTime -> { - synchronized (executionTimesInMs) { - executionTimesInMs.put(name, executionTime); - } - }); - } - - Collection<Long> executionTimesFor(String name) { - synchronized (executionTimesInMs) { - return executionTimesInMs.get(name); - } - } - } - @BeforeEach void setUp() { hook1 = mock(PreDeletionHook.class); @@ -218,10 +161,10 @@ class PreDeletionHooksTest { @Test void runHooksShouldPublishTimerMetrics() { - long sleepDurationInMs = Duration.ofSeconds(1).toMillis(); + Duration sleepDuration = Duration.ofSeconds(1); Mono<Void> notifyDeleteAnswer = Mono.fromCallable(() -> { - Thread.sleep(sleepDurationInMs); + Thread.sleep(sleepDuration.toMillis()); return Mono.empty(); }).then(); @@ -232,6 +175,6 @@ class PreDeletionHooksTest { assertThat(metricFactory.executionTimesFor(PRE_DELETION_HOOK_METRIC_NAME)) .hasSize(2) - .allSatisfy(executionInMs -> assertThat(executionInMs).isGreaterThanOrEqualTo(sleepDurationInMs)); + .allSatisfy(duration -> assertThat(duration).isGreaterThanOrEqualTo(sleepDuration)); } } \ No newline at end of file diff --git a/metrics/metrics-tests/pom.xml b/metrics/metrics-tests/pom.xml new file mode 100644 index 0000000..3ad0b3b --- /dev/null +++ b/metrics/metrics-tests/pom.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>metrics</artifactId> + <groupId>org.apache.james</groupId> + <version>3.4.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>metrics-tests</artifactId> + + <name>Apache James :: Metrics :: Tests</name> + + <dependencies> + <dependency> + <groupId>${james.groupId}</groupId> + <artifactId>james-server-util</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>${james.groupId}</groupId> + <artifactId>metrics-api</artifactId> + </dependency> + <dependency> + <groupId>com.jayway.awaitility</groupId> + <artifactId>awaitility</artifactId> + </dependency> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + </dependency> + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.platform</groupId> + <artifactId>junit-platform-launcher</artifactId> + <scope>test</scope> + </dependency> + </dependencies> +</project> \ No newline at end of file diff --git a/metrics/metrics-tests/src/main/java/org/apache/james/metrics/tests/RecordingMetric.java b/metrics/metrics-tests/src/main/java/org/apache/james/metrics/tests/RecordingMetric.java new file mode 100644 index 0000000..97bef5d --- /dev/null +++ b/metrics/metrics-tests/src/main/java/org/apache/james/metrics/tests/RecordingMetric.java @@ -0,0 +1,57 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + +package org.apache.james.metrics.tests; + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; + +import org.apache.james.metrics.api.Metric; + +public class RecordingMetric implements Metric { + private final String name; + private AtomicInteger value; + private final Consumer<Integer> publishCallback; + + public RecordingMetric(String name, Consumer<Integer> publishCallback) { + this.name = name; + this.value = new AtomicInteger(); + this.publishCallback = publishCallback; + } + + @Override + public void increment() { + publishCallback.accept(value.incrementAndGet()); + } + + @Override + public void decrement() { + publishCallback.accept(value.decrementAndGet()); + } + + @Override + public void add(int i) { + publishCallback.accept(value.addAndGet(i)); + } + + @Override + public void remove(int i) { + publishCallback.accept(value.addAndGet(-1 * i)); + } +} diff --git a/metrics/metrics-tests/src/main/java/org/apache/james/metrics/tests/RecordingMetricFactory.java b/metrics/metrics-tests/src/main/java/org/apache/james/metrics/tests/RecordingMetricFactory.java new file mode 100644 index 0000000..6fec18b --- /dev/null +++ b/metrics/metrics-tests/src/main/java/org/apache/james/metrics/tests/RecordingMetricFactory.java @@ -0,0 +1,61 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + +package org.apache.james.metrics.tests; + +import java.time.Duration; +import java.util.Collection; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.james.metrics.api.Metric; +import org.apache.james.metrics.api.MetricFactory; +import org.apache.james.metrics.api.TimeMetric; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; + +public class RecordingMetricFactory implements MetricFactory { + private final Multimap<String, Duration> executionTimesInMs = Multimaps.synchronizedSetMultimap(HashMultimap.create()); + private final ConcurrentHashMap<String, Integer> executionValues = new ConcurrentHashMap<>(); + + @Override + public Metric generate(String name) { + return new RecordingMetric(name, executionValue -> executionValues.put(name, executionValue)); + } + + @Override + public TimeMetric timer(String name) { + return new RecordingTimeMetric(name, executionTime -> { + synchronized (executionTimesInMs) { + executionTimesInMs.put(name, executionTime); + } + }); + } + + public Collection<Duration> executionTimesFor(String name) { + synchronized (executionTimesInMs) { + return executionTimesInMs.get(name); + } + } + + public int countFor(String name) { + return executionValues.getOrDefault(name, 0); + } +} diff --git a/metrics/metrics-tests/src/main/java/org/apache/james/metrics/tests/RecordingTimeMetric.java b/metrics/metrics-tests/src/main/java/org/apache/james/metrics/tests/RecordingTimeMetric.java new file mode 100644 index 0000000..ea19cd7 --- /dev/null +++ b/metrics/metrics-tests/src/main/java/org/apache/james/metrics/tests/RecordingTimeMetric.java @@ -0,0 +1,51 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + +package org.apache.james.metrics.tests; + +import java.time.Duration; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +import org.apache.james.metrics.api.TimeMetric; + +import com.google.common.base.Stopwatch; + +public class RecordingTimeMetric implements TimeMetric { + private final String name; + private final Stopwatch stopwatch = Stopwatch.createStarted(); + private final Consumer<Duration> publishCallback; + + RecordingTimeMetric(String name, Consumer<Duration> publishCallback) { + this.name = name; + this.publishCallback = publishCallback; + } + + @Override + public String name() { + return name; + } + + @Override + public long stopAndPublish() { + long elapsed = stopwatch.elapsed(TimeUnit.MILLISECONDS); + publishCallback.accept(Duration.ofMillis(elapsed)); + return elapsed; + } +} diff --git a/metrics/metrics-tests/src/test/java/org/apache/james/metrics/tests/RecordingMetricFactoryTest.java b/metrics/metrics-tests/src/test/java/org/apache/james/metrics/tests/RecordingMetricFactoryTest.java new file mode 100644 index 0000000..f2de003 --- /dev/null +++ b/metrics/metrics-tests/src/test/java/org/apache/james/metrics/tests/RecordingMetricFactoryTest.java @@ -0,0 +1,102 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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. * + ****************************************************************/ + +package org.apache.james.metrics.tests; + +import static com.jayway.awaitility.Awaitility.await; +import static org.assertj.core.api.Assertions.assertThat; + +import org.apache.james.metrics.api.Metric; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.jayway.awaitility.Duration; +import com.jayway.awaitility.core.ConditionFactory; + +class RecordingMetricFactoryTest { + + private static final String TIME_METRIC_NAME = "timerMetric"; + private static final String METRIC_NAME = "metric"; + private static final java.time.Duration ONE_SECOND = java.time.Duration.ofSeconds(1); + private static final java.time.Duration FIVE_SECONDS = java.time.Duration.ofSeconds(5); + private static final ConditionFactory WAIT_CONDITION = await().timeout(Duration.ONE_MINUTE); + + private RecordingMetricFactory testee; + + @BeforeEach + void setUp() { + testee = new RecordingMetricFactory(); + } + + @Test + void executionTimesForATimeMetricShouldBeStoreMultipleTime() { + runTimeMetric(ONE_SECOND); + runTimeMetric(FIVE_SECONDS); + + WAIT_CONDITION + .until(() -> { + assertThat(testee.executionTimesFor(TIME_METRIC_NAME)) + .hasSize(2); + assertThat(testee.executionTimesFor(TIME_METRIC_NAME)) + .contains(ONE_SECOND, FIVE_SECONDS); + }); + } + + @Test + void countForAMetricShouldBeCountForIncrementMultipleTime() { + Metric metric = testee.generate(METRIC_NAME); + metric.increment(); + metric.increment(); + + assertThat(testee.countFor(METRIC_NAME)) + .isEqualTo(2); + } + + @Test + void countForAMetricShouldBeCountForIncrementAndDecrement() { + Metric metric = testee.generate(METRIC_NAME); + metric.increment(); + metric.increment(); + metric.decrement(); + + assertThat(testee.countFor(METRIC_NAME)) + .isEqualTo(1); + } + + @Test + void countForAMetricShouldBeCountForIncrementAddAndRemove() { + Metric metric = testee.generate(METRIC_NAME); + metric.increment(); + metric.increment(); + metric.add(3); + + assertThat(testee.countFor(METRIC_NAME)) + .isEqualTo(5); + } + + private void runTimeMetric(java.time.Duration duration) { + testee.runPublishingTimerMetric(TIME_METRIC_NAME, () -> { + try { + Thread.sleep(duration.toMillis()); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + } +} diff --git a/metrics/pom.xml b/metrics/pom.xml index 8da2640..0d08f8b 100644 --- a/metrics/pom.xml +++ b/metrics/pom.xml @@ -36,6 +36,7 @@ <module>metrics-api</module> <module>metrics-dropwizard</module> <module>metrics-logger</module> + <module>metrics-tests</module> </modules> </project> diff --git a/pom.xml b/pom.xml index 44b476f..9f04c6d 100644 --- a/pom.xml +++ b/pom.xml @@ -1762,6 +1762,11 @@ </dependency> <dependency> <groupId>${james.groupId}</groupId> + <artifactId>metrics-tests</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>${james.groupId}</groupId> <artifactId>quota-mailing-cassandra</artifactId> <version>${project.version}</version> </dependency> --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
