@Test public void queuePollSyncTracksOnComplete() { //prepare registry with mock clock MockClock clock = new MockClock(); removeRegistry(); registry = new SimpleMeterRegistry(SimpleConfig.DEFAULT, clock); Metrics.globalRegistry.add(registry); AssertSubscriber<Integer> testSubscriber = AssertSubscriber.create(); MicrometerFluxMetricsFuseableSubscriber<Integer> fuseableSubscriber = new MicrometerFluxMetricsFuseableSubscriber<>(testSubscriber, registry, clock, "foo", Collections.emptyList()); Fuseable.QueueSubscription<Integer> testQueue = new FluxPeekFuseableTest.AssertQueueSubscription<>(); testQueue.offer(1); fuseableSubscriber.onSubscribe(testQueue); fuseableSubscriber.requestFusion(Fuseable.SYNC); clock.add(Duration.ofMillis(200)); Integer val1 = fuseableSubscriber.poll(); clock.add(Duration.ofMillis(123)); Integer val2 = fuseableSubscriber.poll(); assertThat(val1).isEqualTo(1); assertThat(val2).isNull(); //test meters Timer terminationTimer = registry.find(METER_FLOW_DURATION) .tag(TAG_STATUS, TAGVALUE_ON_COMPLETE) .timer(); assertThat(terminationTimer).isNotNull(); assertThat(terminationTimer.max(TimeUnit.MILLISECONDS)).as("terminate max delay").isEqualTo(323); }
@Test @DisplayName("record a runnable task") default void recordWithRunnable(MeterRegistry registry) { Timer t = registry.timer("myTimer"); try { t.record(() -> clock(registry).add(10, TimeUnit.NANOSECONDS)); clock(registry).add(step()); } finally { assertAll(() -> assertEquals(1L, t.count()), () -> assertEquals(10, t.totalTime(TimeUnit.NANOSECONDS), 1.0e-12)); } }
@Test public void timerRecordRunnable() { Timer t = registry.timer("foo"); t.record((Runnable) () -> clock.add(42, TimeUnit.SECONDS)); Assertions.assertEquals(1, t.count()); Assertions.assertEquals(TimeUnit.SECONDS.toNanos(42), t.totalTime()); }
@BeforeEach public void before() { clock = new MockClock(); meterRegistry = new SimpleMeterRegistry(SimpleConfig.DEFAULT, clock); registry = new MicrometerRegistry(meterRegistry); }
@Test public void maxGaugeSet() { Gauge g = registry.maxGauge("foo"); Assertions.assertTrue(Double.isNaN(g.value())); g.set(42.0); g.set(20.0); clock.addSeconds(60); Assertions.assertEquals(42.0, g.value(), 1e-12); }
@Test default void recordMax(MeterRegistry registry) { Timer timer = registry.timer("my.timer"); timer.record(10, TimeUnit.MILLISECONDS); timer.record(1, TimeUnit.SECONDS); clock(registry).add(step()); // for Atlas, which is step rather than ring-buffer based assertThat(timer.max(TimeUnit.SECONDS)).isEqualTo(1); assertThat(timer.max(TimeUnit.MILLISECONDS)).isEqualTo(1000); //noinspection ConstantConditions clock(registry).add(Duration.ofMillis(step().toMillis() * DistributionStatisticConfig.DEFAULT.getBufferLength())); assertThat(timer.max(TimeUnit.SECONDS)).isEqualTo(0); }
@Test public void timerRecordCallable() throws Exception { Timer t = registry.timer("foo"); t.record(() -> clock.add(42, TimeUnit.SECONDS)); Assertions.assertEquals(1, t.count()); Assertions.assertEquals(TimeUnit.SECONDS.toNanos(42), t.totalTime()); }
@Test public void unknownGet() { meterRegistry.more().longTaskTimer("foo").record(() -> clock.addSeconds(60)); Assertions.assertNull(registry.get(registry.createId("foo"))); }
@Test @DisplayName("record with stateful Sample instance") default void recordWithSample(MeterRegistry registry) { Timer timer = registry.timer("myTimer"); Timer.Sample sample = Timer.start(registry); clock(registry).add(10, TimeUnit.NANOSECONDS); sample.stop(timer); clock(registry).add(step()); assertAll(() -> assertEquals(1L, timer.count()), () -> assertEquals(10, timer.totalTime(TimeUnit.NANOSECONDS), 1.0e-12)); }
@Test public void queuePollTracksOnNext() { //prepare registry with mock clock MockClock clock = new MockClock(); removeRegistry(); registry = new SimpleMeterRegistry(SimpleConfig.DEFAULT, clock); Metrics.globalRegistry.add(registry); AssertSubscriber<Integer> testSubscriber = AssertSubscriber.create(); MicrometerFluxMetricsFuseableSubscriber<Integer> fuseableSubscriber = new MicrometerFluxMetricsFuseableSubscriber<>(testSubscriber, registry, clock, "foo", Collections.emptyList()); Fuseable.QueueSubscription<Integer> testQueue = new FluxPeekFuseableTest.AssertQueueSubscription<>(); testQueue.offer(1); fuseableSubscriber.onSubscribe(testQueue); clock.add(Duration.ofMillis(200)); Integer val1 = fuseableSubscriber.poll(); Integer val2 = fuseableSubscriber.poll(); assertThat(val1).isEqualTo(1); assertThat(val2).isNull(); //test meters Timer nextTimer = registry.find(METER_ON_NEXT_DELAY) .timer(); assertThat(nextTimer).isNotNull(); assertThat(nextTimer.max(TimeUnit.MILLISECONDS)).as("onNext max delay").isEqualTo(200); }
@Test public void patternUsingState() { LongTaskTimer t = LongTaskTimer.get(registry, registry.createId("foo")); long tid = t.start(); clock.addSeconds(60); PolledMeter.update(registry); Gauge g = registry.gauge(registry.createId("foo").withTag(Statistic.duration)); Assertions.assertEquals(60.0, g.value(), 1e-12); t.stop(tid); PolledMeter.update(registry); Assertions.assertEquals(0.0, g.value(), 1e-12); } }
@Test @DisplayName("callable task that throws exception is still recorded") default void recordCallableException(MeterRegistry registry) { Timer t = registry.timer("myTimer"); assertThrows(Exception.class, () -> { t.recordCallable(() -> { clock(registry).add(10, TimeUnit.NANOSECONDS); throw new Exception("uh oh"); }); }); clock(registry).add(step()); assertAll(() -> assertEquals(1L, t.count()), () -> assertEquals(10, t.totalTime(TimeUnit.NANOSECONDS), 1.0e-12)); }
@Test public void queuePollSyncTracksOnComplete() { //prepare registry with mock clock MockClock clock = new MockClock(); removeRegistry(); registry = new SimpleMeterRegistry(SimpleConfig.DEFAULT, clock); Metrics.globalRegistry.add(registry); AssertSubscriber<Integer> testSubscriber = AssertSubscriber.create(); MicrometerMonoMetricsFuseableSubscriber<Integer> fuseableSubscriber = new MicrometerMonoMetricsFuseableSubscriber<>(testSubscriber, registry, clock, "foo", Collections.emptyList()); Fuseable.QueueSubscription<Integer> testQueue = new FluxPeekFuseableTest.AssertQueueSubscription<>(); testQueue.offer(1); fuseableSubscriber.onSubscribe(testQueue); fuseableSubscriber.requestFusion(Fuseable.SYNC); clock.add(Duration.ofMillis(200)); Integer val1 = fuseableSubscriber.poll(); clock.add(Duration.ofMillis(123)); Integer val2 = fuseableSubscriber.poll(); assertThat(val1).isEqualTo(1); assertThat(val2).isNull(); //test meters Timer terminationTimer = registry.find(METER_FLOW_DURATION) .tag(TAG_STATUS, TAGVALUE_ON_COMPLETE) .timer(); assertThat(terminationTimer).isNotNull(); assertThat(terminationTimer.max(TimeUnit.MILLISECONDS)).as("terminate max delay").isEqualTo(323); }
@DisplayName("multiple increments are maintained") @Test default void increment(MeterRegistry registry) { Counter c = registry.counter("myCounter"); c.increment(); clock(registry).add(step()); assertThat(c.count()).isEqualTo(1.0, offset(1e-12)); c.increment(); c.increment(); clock(registry).add(step()); // in the case of a step aggregating system will be 2, otherwise 3 assertThat(c.count()).isGreaterThanOrEqualTo(2.0); }
@Test public void queuePollDoesntTrackOnNext() { //prepare registry with mock clock MockClock clock = new MockClock(); removeRegistry(); registry = new SimpleMeterRegistry(SimpleConfig.DEFAULT, clock); Metrics.globalRegistry.add(registry); AssertSubscriber<Integer> testSubscriber = AssertSubscriber.create(); MicrometerMonoMetricsFuseableSubscriber<Integer> fuseableSubscriber = new MicrometerMonoMetricsFuseableSubscriber<>(testSubscriber, registry, clock, "foo", Collections.emptyList()); Fuseable.QueueSubscription<Integer> testQueue = new FluxPeekFuseableTest.AssertQueueSubscription<>(); testQueue.offer(1); fuseableSubscriber.onSubscribe(testQueue); clock.add(Duration.ofMillis(200)); Integer val1 = fuseableSubscriber.poll(); Integer val2 = fuseableSubscriber.poll(); assertThat(val1).isEqualTo(1); assertThat(val2).isNull(); //test meters Timer nextTimer = registry.find(METER_ON_NEXT_DELAY) .timer(); assertThat(nextTimer).as("no onNext delay meter for Mono").isNull(); }
@Test @DisplayName("function-tracking counter increments by change in a monotonically increasing function when observed") default void functionTrackingCounter(MeterRegistry registry) { AtomicLong n = new AtomicLong(0); registry.more().counter("tracking", emptyList(), n); n.incrementAndGet(); clock(registry).add(step()); registry.forEachMeter(Meter::measure); assertThat(registry.get("tracking").functionCounter().count()).isEqualTo(1.0); } }
@Test public void queuePollError() { //prepare registry with mock clock MockClock clock = new MockClock(); removeRegistry(); registry = new SimpleMeterRegistry(SimpleConfig.DEFAULT, clock); Metrics.globalRegistry.add(registry); AssertSubscriber<Integer> testSubscriber = AssertSubscriber.create(); MicrometerMonoMetricsFuseableSubscriber<Integer> fuseableSubscriber = new MicrometerMonoMetricsFuseableSubscriber<>(testSubscriber, registry, clock, "foo", Collections.emptyList()); FluxPeekFuseableTest.AssertQueueSubscription<Integer> testQueue = new FluxPeekFuseableTest.AssertQueueSubscription<>(); testQueue.setCompleteWithError(true); testQueue.offer(1); fuseableSubscriber.onSubscribe(testQueue); fuseableSubscriber.requestFusion(Fuseable.SYNC); clock.add(Duration.ofMillis(200)); Integer val1 = fuseableSubscriber.poll(); assertThat(val1).isEqualTo(1); clock.add(Duration.ofMillis(123)); assertThatIllegalStateException().isThrownBy(fuseableSubscriber::poll) .withMessage("AssertQueueSubscriber poll error"); //test meters Timer terminationTimer = registry.find(METER_FLOW_DURATION) .tag(TAG_STATUS, TAGVALUE_ON_ERROR) .timer(); assertThat(terminationTimer).isNotNull(); assertThat(terminationTimer.max(TimeUnit.MILLISECONDS)).as("terminate max delay").isEqualTo(323); }
@Test @DisplayName("function timers respect the base unit of an underlying registry") void functionTimerUnits(MeterRegistry registry) { Object o = new Object(); registry.more().timer("function.timer", emptyList(), o, o2 -> 1, o2 -> 1, TimeUnit.MILLISECONDS); FunctionTimer ft = registry.get("function.timer").functionTimer(); clock(registry).add(step()); assertThat(ft.measure()) .anySatisfy(ms -> { TimeUnit baseUnit = TimeUnit.valueOf(requireNonNull(ft.getId().getBaseUnit()).toUpperCase()); assertThat(ms.getStatistic()).isEqualTo(Statistic.TOTAL_TIME); assertThat(TimeUtils.convert(ms.getValue(), baseUnit, TimeUnit.MILLISECONDS)).isEqualTo(1); }); }
@Test public void queuePollError() { //prepare registry with mock clock MockClock clock = new MockClock(); removeRegistry(); registry = new SimpleMeterRegistry(SimpleConfig.DEFAULT, clock); Metrics.globalRegistry.add(registry); AssertSubscriber<Integer> testSubscriber = AssertSubscriber.create(); MicrometerFluxMetricsFuseableSubscriber<Integer> fuseableSubscriber = new MicrometerFluxMetricsFuseableSubscriber<>(testSubscriber, registry, clock, "foo", Collections.emptyList()); FluxPeekFuseableTest.AssertQueueSubscription<Integer> testQueue = new FluxPeekFuseableTest.AssertQueueSubscription<>(); testQueue.setCompleteWithError(true); testQueue.offer(1); fuseableSubscriber.onSubscribe(testQueue); fuseableSubscriber.requestFusion(Fuseable.SYNC); clock.add(Duration.ofMillis(200)); Integer val1 = fuseableSubscriber.poll(); assertThat(val1).isEqualTo(1); clock.add(Duration.ofMillis(123)); assertThatIllegalStateException().isThrownBy(fuseableSubscriber::poll) .withMessage("AssertQueueSubscriber poll error"); //test meters Timer terminationTimer = registry.find(METER_FLOW_DURATION) .tag(TAG_STATUS, TAGVALUE_ON_ERROR) .timer(); assertThat(terminationTimer).isNotNull(); assertThat(terminationTimer.max(TimeUnit.MILLISECONDS)).as("terminate max delay").isEqualTo(323); }