Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid implementing the OCI Monitoring interface. #8474

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions integrations/oci/metrics/cdi/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@
<artifactId>helidon-metrics</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.helidon.integrations.oci.sdk</groupId>
<artifactId>helidon-integrations-oci-sdk-cdi</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,12 @@
*/
package io.helidon.integrations.oci.metrics.cdi;

import java.lang.annotation.Annotation;
import java.lang.reflect.Proxy;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import com.oracle.bmc.monitoring.requests.CreateAlarmSuppressionRequest;
import com.oracle.bmc.monitoring.requests.DeleteAlarmSuppressionRequest;
import com.oracle.bmc.monitoring.requests.GetAlarmSuppressionRequest;
import com.oracle.bmc.monitoring.requests.ListAlarmSuppressionsRequest;
import com.oracle.bmc.monitoring.requests.SummarizeAlarmSuppressionHistoryRequest;
import com.oracle.bmc.monitoring.responses.CreateAlarmSuppressionResponse;
import com.oracle.bmc.monitoring.responses.DeleteAlarmSuppressionResponse;
import com.oracle.bmc.monitoring.responses.GetAlarmSuppressionResponse;
import com.oracle.bmc.monitoring.responses.ListAlarmSuppressionsResponse;
import com.oracle.bmc.monitoring.responses.SummarizeAlarmSuppressionHistoryResponse;
import io.helidon.config.Config;
import io.helidon.integrations.oci.metrics.OciMetricsSupport;
import io.helidon.metrics.api.Counter;
Expand All @@ -43,38 +36,22 @@
import io.helidon.microprofile.testing.junit5.DisableDiscovery;
import io.helidon.microprofile.testing.junit5.HelidonTest;

import com.oracle.bmc.Region;
import com.oracle.bmc.monitoring.Monitoring;
import com.oracle.bmc.monitoring.MonitoringPaginators;
import com.oracle.bmc.monitoring.MonitoringWaiters;
import com.oracle.bmc.monitoring.model.MetricDataDetails;
import com.oracle.bmc.monitoring.model.PostMetricDataDetails;
import com.oracle.bmc.monitoring.requests.ChangeAlarmCompartmentRequest;
import com.oracle.bmc.monitoring.requests.CreateAlarmRequest;
import com.oracle.bmc.monitoring.requests.DeleteAlarmRequest;
import com.oracle.bmc.monitoring.requests.GetAlarmHistoryRequest;
import com.oracle.bmc.monitoring.requests.GetAlarmRequest;
import com.oracle.bmc.monitoring.requests.ListAlarmsRequest;
import com.oracle.bmc.monitoring.requests.ListAlarmsStatusRequest;
import com.oracle.bmc.monitoring.requests.ListMetricsRequest;
import com.oracle.bmc.monitoring.requests.PostMetricDataRequest;
import com.oracle.bmc.monitoring.requests.RemoveAlarmSuppressionRequest;
import com.oracle.bmc.monitoring.requests.RetrieveDimensionStatesRequest;
import com.oracle.bmc.monitoring.requests.SummarizeMetricsDataRequest;
import com.oracle.bmc.monitoring.requests.UpdateAlarmRequest;
import com.oracle.bmc.monitoring.responses.ChangeAlarmCompartmentResponse;
import com.oracle.bmc.monitoring.responses.CreateAlarmResponse;
import com.oracle.bmc.monitoring.responses.DeleteAlarmResponse;
import com.oracle.bmc.monitoring.responses.GetAlarmHistoryResponse;
import com.oracle.bmc.monitoring.responses.GetAlarmResponse;
import com.oracle.bmc.monitoring.responses.ListAlarmsResponse;
import com.oracle.bmc.monitoring.responses.ListAlarmsStatusResponse;
import com.oracle.bmc.monitoring.responses.ListMetricsResponse;
import com.oracle.bmc.monitoring.responses.PostMetricDataResponse;
import com.oracle.bmc.monitoring.responses.RemoveAlarmSuppressionResponse;
import com.oracle.bmc.monitoring.responses.RetrieveDimensionStatesResponse;
import com.oracle.bmc.monitoring.responses.SummarizeMetricsDataResponse;
import com.oracle.bmc.monitoring.responses.UpdateAlarmResponse;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;

import jakarta.enterprise.inject.Default;
import jakarta.enterprise.inject.spi.AfterBeanDiscovery;
import jakarta.enterprise.inject.spi.Extension;
import jakarta.enterprise.inject.spi.InjectionPoint;
import jakarta.enterprise.inject.spi.ProcessInjectionPoint;
import jakarta.enterprise.inject.spi.configurator.BeanConfigurator;
import org.glassfish.jersey.ext.cdi1x.internal.CdiComponentProvider;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;

Expand All @@ -84,15 +61,15 @@
import static org.junit.jupiter.api.Assertions.fail;

@HelidonTest(resetPerTest = true)
@AddBean(OciMetricsCdiExtensionTest.MockMonitoring.class)
@AddBean(OciMetricsCdiExtensionTest.MockOciMetricsBean.class)
@DisableDiscovery
@AddBean(OciMetricsCdiExtensionTest.MockOciMetricsBean.class)
// Helidon MP Extensions
@AddExtension(ServerCdiExtension.class)
@AddExtension(JaxRsCdiExtension.class)
@AddExtension(ConfigCdiExtension.class)
// OciMetricsCdiExtension
@AddExtension(OciMetricsCdiExtension.class)
@AddExtension(CdiComponentProvider.class)
// Add an extension that will simulate a mocked OciExtension that will inject a mocked Monitoring object
@AddExtension(OciMetricsCdiExtensionTest.MockOciMonitoringExtension.class)
// ConfigSources
@AddConfig(key = "ocimetrics.compartmentId",
value = OciMetricsCdiExtensionTest.MetricDataDetailsOCIParams.compartmentId)
Expand All @@ -101,8 +78,9 @@
@AddConfig(key = "ocimetrics.resourceGroup",
value = OciMetricsCdiExtensionTest.MetricDataDetailsOCIParams.resourceGroup)
@AddConfig(key = "ocimetrics.initialDelay", value = "1")
@AddConfig(key = "ocimetrics.delay", value = "2")
@AddConfig(key = "ocimetrics.delay", value = "1")
class OciMetricsCdiExtensionTest {
private static String METRIC_NAME_SUFFIX = "DummyCounter";
private static volatile int testMetricCount = 0;
private static CountDownLatch countDownLatch = new CountDownLatch(1);
private static PostMetricDataDetails postMetricDataDetails;
Expand Down Expand Up @@ -134,13 +112,13 @@ void testDisableOciMetrics() throws InterruptedException {
}

private void validateOciMetricsSupport(boolean enabled) throws InterruptedException {
Counter c1 = registry.getOrCreate(Counter.builder("baseDummyCounter")
Counter c1 = registry.getOrCreate(Counter.builder(Meter.Scope.BASE + METRIC_NAME_SUFFIX)
.scope(Meter.Scope.BASE));
c1.increment();
Counter c2 = registry.getOrCreate(Counter.builder("vendorDummyCounter")
Counter c2 = registry.getOrCreate(Counter.builder(Meter.Scope.VENDOR + METRIC_NAME_SUFFIX)
.scope(Meter.Scope.VENDOR));
c2.increment();
Counter c3 = registry.getOrCreate(Counter.builder("appDummyCounter")
Counter c3 = registry.getOrCreate(Counter.builder(Meter.Scope.APPLICATION + METRIC_NAME_SUFFIX)
.scope(Meter.Scope.APPLICATION));
c3.increment();

Expand All @@ -156,12 +134,9 @@ private void validateOciMetricsSupport(boolean enabled) throws InterruptedExcept
assertThat(activateOciMetricsSupportIsInvoked, is(true));
// System meters in the registry might vary over time. Instead of looking for a specific number of meters,
// make sure the three we added are in the OCI metric data.
long dummyCounterCount = postMetricDataDetails.getMetricData().stream()
.filter(details -> details.getName().contains("DummyCounter"))
.count();
assertThat(dummyCounterCount, is(3L));
assertThat(testMetricCount, is(3));

MetricDataDetails metricDataDetails = postMetricDataDetails.getMetricData().get(0);
MetricDataDetails metricDataDetails = postMetricDataDetails.getMetricData().getFirst();
assertThat(metricDataDetails.getCompartmentId(),
is(MetricDataDetailsOCIParams.compartmentId));
assertThat(metricDataDetails.getNamespace(), is(MetricDataDetailsOCIParams.namespace));
Expand All @@ -183,140 +158,70 @@ interface MetricDataDetailsOCIParams {
String resourceGroup = "dummy_resourceGroup";
}

static class MockMonitoring implements Monitoring {
@Override
public String getEndpoint() {
return "http://www.DummyEndpoint.com";
}

@Override
public void setEndpoint(String s) {
}

@Override
public void setRegion(Region region) {
}

@Override
public void setRegion(String s) {
}

@Override
public void useRealmSpecificEndpointTemplate(boolean b) {
}

@Override
public void refreshClient() {
}

@Override
public ChangeAlarmCompartmentResponse changeAlarmCompartment(ChangeAlarmCompartmentRequest changeAlarmCompartmentRequest) {
return null;
}

@Override
public CreateAlarmResponse createAlarm(CreateAlarmRequest createAlarmRequest) {
return null;
}

@Override
public CreateAlarmSuppressionResponse createAlarmSuppression(CreateAlarmSuppressionRequest createAlarmSuppressionRequest) {
return null;
}

@Override
public DeleteAlarmResponse deleteAlarm(DeleteAlarmRequest deleteAlarmRequest) {
return null;
}

@Override
public DeleteAlarmSuppressionResponse deleteAlarmSuppression(DeleteAlarmSuppressionRequest deleteAlarmSuppressionRequest) {
return null;
}

@Override
public GetAlarmResponse getAlarm(GetAlarmRequest getAlarmRequest) {
return null;
}

@Override
public GetAlarmHistoryResponse getAlarmHistory(GetAlarmHistoryRequest getAlarmHistoryRequest) {
return null;
}

@Override
public GetAlarmSuppressionResponse getAlarmSuppression(GetAlarmSuppressionRequest getAlarmSuppressionRequest) {
return null;
}

@Override
public ListAlarmSuppressionsResponse listAlarmSuppressions(ListAlarmSuppressionsRequest listAlarmSuppressionsRequest) {
return null;
}

@Override
public ListAlarmsResponse listAlarms(ListAlarmsRequest listAlarmsRequest) {
return null;
}

@Override
public ListAlarmsStatusResponse listAlarmsStatus(ListAlarmsStatusRequest listAlarmsStatusRequest) {
return null;
}

@Override
public ListMetricsResponse listMetrics(ListMetricsRequest listMetricsRequest) {
return null;
}

@Override
public PostMetricDataResponse postMetricData(PostMetricDataRequest postMetricDataRequest) {
postMetricDataDetails = postMetricDataRequest.getPostMetricDataDetails();
testMetricCount = postMetricDataDetails.getMetricData().size();
// Give signal that testMetricCount was retrieved
countDownLatch.countDown();
return PostMetricDataResponse.builder()
.__httpStatusCode__(200)
.build();
}

@Override
public RemoveAlarmSuppressionResponse removeAlarmSuppression(RemoveAlarmSuppressionRequest removeAlarmSuppressionRequest) {
return null;
}

@Override
public RetrieveDimensionStatesResponse retrieveDimensionStates(RetrieveDimensionStatesRequest retrieveDimensionStatesRequest) {
return null;
}

@Override
public SummarizeAlarmSuppressionHistoryResponse summarizeAlarmSuppressionHistory(SummarizeAlarmSuppressionHistoryRequest summarizeAlarmSuppressionHistoryRequest) {
return null;
}

@Override
public SummarizeMetricsDataResponse summarizeMetricsData(SummarizeMetricsDataRequest summarizeMetricsDataRequest) {
return null;
}

@Override
public UpdateAlarmResponse updateAlarm(UpdateAlarmRequest updateAlarmRequest) {
return null;
}

@Override
public MonitoringWaiters getWaiters() {
return null;
}

@Override
public MonitoringPaginators getPaginators() {
return null;
// Use this to replace OciExtension, but will only process OCI Monitoring annotation. If the Monitoring
// annotation is found, a Mocked Monitoring object will be injected as a bean
static public class MockOciMonitoringExtension implements Extension {
boolean monitoringFound;
Set<Annotation> monitoringQualifiers;

void processInjectionPoint(@Observes final ProcessInjectionPoint<?, ?> event) {
if (event != null) {
InjectionPoint ip = event.getInjectionPoint();
Class<?> c = (Class<?>) ip.getAnnotated().getBaseType();
final Set<Annotation> existingQualifiers = ip.getQualifiers();
if (c == Monitoring.class && existingQualifiers != null && !existingQualifiers.isEmpty()) {
monitoringFound = true;
monitoringQualifiers = existingQualifiers;
}
}
}

@Override
public void close() throws Exception {
Monitoring getMockedMonitoring() {
// Use Proxy to mock only getEndPoint() and postMetricDataDetails() methods of the Monitoring interface,
// as those are the only ones needed by the test
return
(Monitoring) Proxy.newProxyInstance(
Monitoring.class.getClassLoader(),
new Class[] {Monitoring.class},
(proxy, method, args) -> {
if (method.getName().equals("getEndpoint")) {
return "http://www.DummyEndpoint.com";
} else if (method.getName().equals("postMetricData")) {
PostMetricDataRequest postMetricDataRequest = (PostMetricDataRequest) args[0];
postMetricDataDetails = postMetricDataRequest.getPostMetricDataDetails();
testMetricCount = (int) postMetricDataDetails.getMetricData().stream()
.filter(details -> details.getName().contains(METRIC_NAME_SUFFIX))
.count();
PostMetricDataResponse response = PostMetricDataResponse.builder()
.__httpStatusCode__(200)
.build();

// Give signal that metrics will be posted if the right no. of metrics has been retrieved.
// If not, that means that the metrics have not been registered yet, so try again on the
// next invocation.
if (testMetricCount > 0) {
countDownLatch.countDown();
}
return response;
}
return null;
});
}

void afterBeanDiscovery(@Observes AfterBeanDiscovery event) {
if (monitoringFound) {
BeanConfigurator<Object> beanConfigurator = event.addBean()
.types(Monitoring.class)
.scope(ApplicationScoped.class)
.addQualifiers(monitoringQualifiers);
beanConfigurator = monitoringQualifiers != null ? beanConfigurator.addQualifiers(monitoringQualifiers) :
beanConfigurator.addQualifier(Default.Literal.INSTANCE);
// Add the mocked Monitoring as a bean
beanConfigurator.produceWith(obj -> getMockedMonitoring());
} else {
throw new IllegalStateException("Monitoring was never injected. Check if OciMetricsBean.registerOciMetrics() "
+ "has changed and does not inject Monitoring anymore.");
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@
import java.lang.reflect.Field;

import io.helidon.integrations.oci.metrics.OciMetricsSupport;
import io.helidon.microprofile.config.ConfigCdiExtension;
import io.helidon.microprofile.server.JaxRsCdiExtension;
import io.helidon.microprofile.server.ServerCdiExtension;
import io.helidon.microprofile.testing.junit5.AddBean;
import io.helidon.microprofile.testing.junit5.AddConfig;
import io.helidon.microprofile.testing.junit5.AddExtension;
import io.helidon.microprofile.testing.junit5.DisableDiscovery;
import io.helidon.microprofile.testing.junit5.HelidonTest;

import jakarta.inject.Inject;
Expand All @@ -31,10 +36,17 @@
import static org.hamcrest.Matchers.is;

@HelidonTest
@DisableDiscovery
@AddBean(OverridingOciMetricsBean.class)
// Use OciMetricsCdiExtensionTest.MockOciMonitoringExtension to avoid Monitoring client from being instantiated
// with OCI authentication
@AddExtension(OciMetricsCdiExtensionTest.MockOciMonitoringExtension.class)
// Supporting Extensions for CDI
@AddExtension(ServerCdiExtension.class)
@AddExtension(JaxRsCdiExtension.class)
@AddExtension(ConfigCdiExtension.class)
@AddConfig(key = "oci.metrics.product", value = TestOverridingBean.PRODUCT)
@AddConfig(key = "oci.metrics.fleet", value = TestOverridingBean.FLEET)
@AddBean(OciMetricsCdiExtensionTest.MockMonitoring.class)
class TestOverridingBean {

static final String PRODUCT = "overriding-product-name";
Expand All @@ -54,7 +66,7 @@ void checkOverriding() throws NoSuchFieldException, IllegalAccessException {
String resourceGroup = getStringField("resourceGroup", ociMetricsSupport);

assertThat("Effective namespace", namespace, is(equalTo(PRODUCT)));
assertThat("Effective namespace", resourceGroup, is(equalTo(FLEET)));
assertThat("Effective resourceGroup", resourceGroup, is(equalTo(FLEET)));
}

private String getStringField(String fieldName, OciMetricsSupport ociMetricsSupport)
Expand Down