blob: d20b743aecb9b0333f2a04c39a6a79a310d5b980 [file] [log] [blame]
/*
* 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.geode.internal.metrics;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import org.junit.After;
import org.junit.Test;
import org.apache.geode.internal.cache.GemFireCacheImpl;
import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.internal.metrics.CacheLifecycleMetricsSession.CacheLifecycle;
import org.apache.geode.internal.metrics.CacheLifecycleMetricsSession.ErrorLogger;
import org.apache.geode.metrics.MetricsPublishingService;
public class CacheLifecycleMetricsSessionTest {
private final CompositeMeterRegistry compositeRegistry = new CompositeMeterRegistry();
private CacheLifecycleMetricsSession metricsSession;
@After
public void tearDown() {
if (metricsSession != null) {
GemFireCacheImpl.removeCacheLifecycleListener(metricsSession);
}
}
@Test
public void startsWithNoDownstreamRegistries() {
metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
Collections.emptyList());
Set<MeterRegistry> downstreamRegistries = compositeRegistry.getRegistries();
assertThat(downstreamRegistries)
.isEmpty();
}
@Test
public void remembersConnectedDownstreamRegistries() {
metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
Collections.emptyList());
MeterRegistry downstreamRegistry = new SimpleMeterRegistry();
metricsSession.addSubregistry(downstreamRegistry);
assertThat(compositeRegistry.getRegistries())
.contains(downstreamRegistry);
}
@Test
public void forgetsDisconnectedDownstreamRegistries() {
metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
Collections.emptyList());
MeterRegistry downstreamRegistry = new SimpleMeterRegistry();
metricsSession.addSubregistry(downstreamRegistry);
metricsSession.removeSubregistry(downstreamRegistry);
assertThat(compositeRegistry.getRegistries())
.doesNotContain(downstreamRegistry);
}
@Test
public void connectsExistingMetersToNewDownstreamRegistries() {
metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
Collections.emptyList());
String counterName = "the.counter";
Counter primaryCounter = compositeRegistry.counter(counterName);
double amountIncrementedBeforeConnectingDownstreamRegistry = 3.0;
primaryCounter.increment(amountIncrementedBeforeConnectingDownstreamRegistry);
MeterRegistry downstreamRegistry = new SimpleMeterRegistry();
metricsSession.addSubregistry(downstreamRegistry);
Counter downstreamCounter = downstreamRegistry.find(counterName).counter();
assertThat(downstreamCounter)
.as("downstream counter after connecting, before incrementing")
.isNotNull();
// Note that the newly-created downstream counter starts at zero, ignoring
// any increments that happened before the downstream registry was added.
assertThat(downstreamCounter.count())
.as("downstream counter value after connecting, before incrementing")
.isNotEqualTo(amountIncrementedBeforeConnectingDownstreamRegistry)
.isEqualTo(0);
double amountIncrementedAfterConnectingDownstreamRegistry = 42.0;
primaryCounter.increment(amountIncrementedAfterConnectingDownstreamRegistry);
assertThat(downstreamCounter.count())
.as("downstream counter value after incrementing")
.isEqualTo(amountIncrementedAfterConnectingDownstreamRegistry);
}
@Test
public void connectsNewMetersToExistingDownstreamRegistries() {
metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
Collections.emptyList());
MeterRegistry downstreamRegistry = new SimpleMeterRegistry();
metricsSession.addSubregistry(downstreamRegistry);
String counterName = "the.counter";
Counter newCounter = compositeRegistry.counter(counterName);
Counter downstreamCounter = downstreamRegistry.find(counterName).counter();
assertThat(downstreamCounter)
.as("downstream counter before incrementing")
.isNotNull();
assertThat(downstreamCounter.count())
.as("downstream counter value before incrementing")
.isEqualTo(newCounter.count())
.isEqualTo(0);
double amountIncrementedAfterConnectingDownstreamRegistry = 93.0;
newCounter.increment(amountIncrementedAfterConnectingDownstreamRegistry);
assertThat(downstreamCounter.count())
.as("downstream counter value after incrementing")
.isEqualTo(newCounter.count());
}
@Test
public void cacheCreatedStartsEachMetricsPublishingService() {
List<MetricsPublishingService> metricsPublishingServices = Arrays.asList(
metricsPublishingService("metricsPublishingService1"),
metricsPublishingService("metricsPublishingService2"),
metricsPublishingService("metricsPublishingService3"));
metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
metricsPublishingServices);
metricsSession.cacheCreated(mock(InternalCache.class));
for (MetricsPublishingService metricsPublishingService : metricsPublishingServices) {
verify(metricsPublishingService).start(same(metricsSession));
}
}
@Test
public void cacheClosedStopsEachMetricsPublishingService() {
List<MetricsPublishingService> metricsPublishingServices = Arrays.asList(
metricsPublishingService("metricsPublishingService1"),
metricsPublishingService("metricsPublishingService2"),
metricsPublishingService("metricsPublishingService3"));
metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
metricsPublishingServices);
metricsSession.cacheClosed(mock(InternalCache.class));
for (MetricsPublishingService metricsPublishingService : metricsPublishingServices) {
verify(metricsPublishingService).stop();
}
}
@Test
public void cacheClosedDisconnectsAllDownstreamRegistries() {
metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
Collections.emptyList());
MeterRegistry downstreamMeterRegistry1 = new SimpleMeterRegistry();
MeterRegistry downstreamMeterRegistry2 = new SimpleMeterRegistry();
MeterRegistry downstreamMeterRegistry3 = new SimpleMeterRegistry();
metricsSession.addSubregistry(downstreamMeterRegistry1);
metricsSession.addSubregistry(downstreamMeterRegistry2);
metricsSession.addSubregistry(downstreamMeterRegistry3);
metricsSession.cacheClosed(mock(InternalCache.class));
assertThat(compositeRegistry.getRegistries()).isEmpty();
}
@Test
public void cacheClosedRemovesSessionAsCacheLifecycleListener() {
CacheLifecycle theCacheLifecycle = mock(CacheLifecycle.class);
metricsSession =
new CacheLifecycleMetricsSession(theCacheLifecycle, compositeRegistry,
Collections.emptyList());
metricsSession.cacheClosed(mock(InternalCache.class));
verify(theCacheLifecycle).removeListener(same(metricsSession));
}
@Test
public void cacheCreated_logsErrorMessage_ifMetricsPublishingServiceStartThrowsRuntimeException() {
MetricsPublishingService metricsPublishingService =
metricsPublishingService("metricsPublishingService");
String theClassName = metricsPublishingService.getClass().getName();
RuntimeException theException = new RuntimeException("theExceptionMessage");
doThrow(theException).when(metricsPublishingService).start(any());
List<MetricsPublishingService> metricsPublishingServices =
Collections.singletonList(metricsPublishingService);
ErrorLogger errorLogger = mock(ErrorLogger.class);
metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
metricsPublishingServices, errorLogger);
metricsSession.cacheCreated(mock(InternalCache.class));
verify(errorLogger).logError(anyString(), eq("start"), same(theClassName), same(theException));
}
@Test
public void cacheCreated_logsErrorMessage_ifMetricsPublishingServiceStartThrowsError() {
MetricsPublishingService metricsPublishingService =
metricsPublishingService("metricsPublishingService");
String theClassName = metricsPublishingService.getClass().getName();
Error theError = new Error("theErrorMessage");
doThrow(theError).when(metricsPublishingService).start(any());
List<MetricsPublishingService> metricsPublishingServices =
Collections.singletonList(metricsPublishingService);
ErrorLogger errorLogger = mock(ErrorLogger.class);
metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
metricsPublishingServices, errorLogger);
metricsSession.cacheCreated(mock(InternalCache.class));
verify(errorLogger).logError(anyString(), eq("start"), same(theClassName), same(theError));
}
@Test
public void cacheClosed_logsErrorMessage_ifMetricsPublishingServiceStopThrowsRuntimeException() {
MetricsPublishingService metricsPublishingService =
metricsPublishingService("metricsPublishingService");
String theClassName = metricsPublishingService.getClass().getName();
RuntimeException theException = new RuntimeException("theExceptionMessage");
doThrow(theException).when(metricsPublishingService).stop();
List<MetricsPublishingService> metricsPublishingServices =
Collections.singletonList(metricsPublishingService);
ErrorLogger errorLogger = mock(ErrorLogger.class);
metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
metricsPublishingServices, errorLogger);
metricsSession.cacheClosed(mock(InternalCache.class));
verify(errorLogger).logError(anyString(), eq("stop"), same(theClassName), same(theException));
}
@Test
public void cacheClosed_logsErrorMessage_ifMetricsPublishingServiceStopThrowsError() {
MetricsPublishingService metricsPublishingService =
metricsPublishingService("metricsPublishingService");
String theClassName = metricsPublishingService.getClass().getName();
Error theError = new Error("theErrorMessage");
doThrow(theError).when(metricsPublishingService).stop();
List<MetricsPublishingService> metricsPublishingServices =
Collections.singletonList(metricsPublishingService);
ErrorLogger errorLogger = mock(ErrorLogger.class);
metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
metricsPublishingServices, errorLogger);
metricsSession.cacheClosed(mock(InternalCache.class));
verify(errorLogger).logError(anyString(), eq("stop"), same(theClassName), same(theError));
}
private MetricsPublishingService metricsPublishingService(String name) {
return mock(MetricsPublishingService.class, name);
}
}