1515 */
1616package io .helidon .integrations .oci .metrics .cdi ;
1717
18+ import java .lang .annotation .Annotation ;
19+ import java .lang .reflect .Proxy ;
20+ import java .util .Set ;
1821import java .util .concurrent .CountDownLatch ;
1922import java .util .concurrent .TimeUnit ;
2023
21- import com .oracle .bmc .monitoring .requests .CreateAlarmSuppressionRequest ;
22- import com .oracle .bmc .monitoring .requests .DeleteAlarmSuppressionRequest ;
23- import com .oracle .bmc .monitoring .requests .GetAlarmSuppressionRequest ;
24- import com .oracle .bmc .monitoring .requests .ListAlarmSuppressionsRequest ;
25- import com .oracle .bmc .monitoring .requests .SummarizeAlarmSuppressionHistoryRequest ;
26- import com .oracle .bmc .monitoring .responses .CreateAlarmSuppressionResponse ;
27- import com .oracle .bmc .monitoring .responses .DeleteAlarmSuppressionResponse ;
28- import com .oracle .bmc .monitoring .responses .GetAlarmSuppressionResponse ;
29- import com .oracle .bmc .monitoring .responses .ListAlarmSuppressionsResponse ;
30- import com .oracle .bmc .monitoring .responses .SummarizeAlarmSuppressionHistoryResponse ;
3124import io .helidon .config .Config ;
3225import io .helidon .integrations .oci .metrics .OciMetricsSupport ;
3326import io .helidon .metrics .api .Counter ;
4336import io .helidon .microprofile .testing .junit5 .DisableDiscovery ;
4437import io .helidon .microprofile .testing .junit5 .HelidonTest ;
4538
46- import com .oracle .bmc .Region ;
4739import com .oracle .bmc .monitoring .Monitoring ;
48- import com .oracle .bmc .monitoring .MonitoringPaginators ;
49- import com .oracle .bmc .monitoring .MonitoringWaiters ;
5040import com .oracle .bmc .monitoring .model .MetricDataDetails ;
5141import com .oracle .bmc .monitoring .model .PostMetricDataDetails ;
52- import com .oracle .bmc .monitoring .requests .ChangeAlarmCompartmentRequest ;
53- import com .oracle .bmc .monitoring .requests .CreateAlarmRequest ;
54- import com .oracle .bmc .monitoring .requests .DeleteAlarmRequest ;
55- import com .oracle .bmc .monitoring .requests .GetAlarmHistoryRequest ;
56- import com .oracle .bmc .monitoring .requests .GetAlarmRequest ;
57- import com .oracle .bmc .monitoring .requests .ListAlarmsRequest ;
58- import com .oracle .bmc .monitoring .requests .ListAlarmsStatusRequest ;
59- import com .oracle .bmc .monitoring .requests .ListMetricsRequest ;
6042import com .oracle .bmc .monitoring .requests .PostMetricDataRequest ;
61- import com .oracle .bmc .monitoring .requests .RemoveAlarmSuppressionRequest ;
62- import com .oracle .bmc .monitoring .requests .RetrieveDimensionStatesRequest ;
63- import com .oracle .bmc .monitoring .requests .SummarizeMetricsDataRequest ;
64- import com .oracle .bmc .monitoring .requests .UpdateAlarmRequest ;
65- import com .oracle .bmc .monitoring .responses .ChangeAlarmCompartmentResponse ;
66- import com .oracle .bmc .monitoring .responses .CreateAlarmResponse ;
67- import com .oracle .bmc .monitoring .responses .DeleteAlarmResponse ;
68- import com .oracle .bmc .monitoring .responses .GetAlarmHistoryResponse ;
69- import com .oracle .bmc .monitoring .responses .GetAlarmResponse ;
70- import com .oracle .bmc .monitoring .responses .ListAlarmsResponse ;
71- import com .oracle .bmc .monitoring .responses .ListAlarmsStatusResponse ;
72- import com .oracle .bmc .monitoring .responses .ListMetricsResponse ;
7343import com .oracle .bmc .monitoring .responses .PostMetricDataResponse ;
74- import com .oracle .bmc .monitoring .responses .RemoveAlarmSuppressionResponse ;
75- import com .oracle .bmc .monitoring .responses .RetrieveDimensionStatesResponse ;
76- import com .oracle .bmc .monitoring .responses .SummarizeMetricsDataResponse ;
77- import com .oracle .bmc .monitoring .responses .UpdateAlarmResponse ;
44+
45+ import jakarta .enterprise .context .ApplicationScoped ;
46+ import jakarta .enterprise .event .Observes ;
47+
48+ import jakarta .enterprise .inject .Default ;
49+ import jakarta .enterprise .inject .spi .AfterBeanDiscovery ;
50+ import jakarta .enterprise .inject .spi .Extension ;
51+ import jakarta .enterprise .inject .spi .InjectionPoint ;
52+ import jakarta .enterprise .inject .spi .ProcessInjectionPoint ;
53+ import jakarta .enterprise .inject .spi .configurator .BeanConfigurator ;
54+ import org .glassfish .jersey .ext .cdi1x .internal .CdiComponentProvider ;
7855import org .junit .jupiter .api .AfterEach ;
7956import org .junit .jupiter .api .Test ;
8057
8461import static org .junit .jupiter .api .Assertions .fail ;
8562
8663@ HelidonTest (resetPerTest = true )
87- @ AddBean (OciMetricsCdiExtensionTest .MockMonitoring .class )
88- @ AddBean (OciMetricsCdiExtensionTest .MockOciMetricsBean .class )
8964@ DisableDiscovery
65+ @ AddBean (OciMetricsCdiExtensionTest .MockOciMetricsBean .class )
9066// Helidon MP Extensions
9167@ AddExtension (ServerCdiExtension .class )
9268@ AddExtension (JaxRsCdiExtension .class )
9369@ AddExtension (ConfigCdiExtension .class )
94- // OciMetricsCdiExtension
95- @ AddExtension (OciMetricsCdiExtension .class )
70+ @ AddExtension (CdiComponentProvider .class )
71+ // Add an extension that will simulate a mocked OciExtension that will inject a mocked Monitoring object
72+ @ AddExtension (OciMetricsCdiExtensionTest .MockOciMonitoringExtension .class )
9673// ConfigSources
9774@ AddConfig (key = "ocimetrics.compartmentId" ,
9875 value = OciMetricsCdiExtensionTest .MetricDataDetailsOCIParams .compartmentId )
10178@ AddConfig (key = "ocimetrics.resourceGroup" ,
10279 value = OciMetricsCdiExtensionTest .MetricDataDetailsOCIParams .resourceGroup )
10380@ AddConfig (key = "ocimetrics.initialDelay" , value = "1" )
104- @ AddConfig (key = "ocimetrics.delay" , value = "2 " )
81+ @ AddConfig (key = "ocimetrics.delay" , value = "1 " )
10582class OciMetricsCdiExtensionTest {
83+ private static String METRIC_NAME_SUFFIX = "DummyCounter" ;
10684 private static volatile int testMetricCount = 0 ;
10785 private static CountDownLatch countDownLatch = new CountDownLatch (1 );
10886 private static PostMetricDataDetails postMetricDataDetails ;
@@ -134,13 +112,13 @@ void testDisableOciMetrics() throws InterruptedException {
134112 }
135113
136114 private void validateOciMetricsSupport (boolean enabled ) throws InterruptedException {
137- Counter c1 = registry .getOrCreate (Counter .builder ("baseDummyCounter" )
115+ Counter c1 = registry .getOrCreate (Counter .builder (Meter . Scope . BASE + METRIC_NAME_SUFFIX )
138116 .scope (Meter .Scope .BASE ));
139117 c1 .increment ();
140- Counter c2 = registry .getOrCreate (Counter .builder ("vendorDummyCounter" )
118+ Counter c2 = registry .getOrCreate (Counter .builder (Meter . Scope . VENDOR + METRIC_NAME_SUFFIX )
141119 .scope (Meter .Scope .VENDOR ));
142120 c2 .increment ();
143- Counter c3 = registry .getOrCreate (Counter .builder ("appDummyCounter" )
121+ Counter c3 = registry .getOrCreate (Counter .builder (Meter . Scope . APPLICATION + METRIC_NAME_SUFFIX )
144122 .scope (Meter .Scope .APPLICATION ));
145123 c3 .increment ();
146124
@@ -156,12 +134,9 @@ private void validateOciMetricsSupport(boolean enabled) throws InterruptedExcept
156134 assertThat (activateOciMetricsSupportIsInvoked , is (true ));
157135 // System meters in the registry might vary over time. Instead of looking for a specific number of meters,
158136 // make sure the three we added are in the OCI metric data.
159- long dummyCounterCount = postMetricDataDetails .getMetricData ().stream ()
160- .filter (details -> details .getName ().contains ("DummyCounter" ))
161- .count ();
162- assertThat (dummyCounterCount , is (3L ));
137+ assertThat (testMetricCount , is (3 ));
163138
164- MetricDataDetails metricDataDetails = postMetricDataDetails .getMetricData ().get ( 0 );
139+ MetricDataDetails metricDataDetails = postMetricDataDetails .getMetricData ().getFirst ( );
165140 assertThat (metricDataDetails .getCompartmentId (),
166141 is (MetricDataDetailsOCIParams .compartmentId ));
167142 assertThat (metricDataDetails .getNamespace (), is (MetricDataDetailsOCIParams .namespace ));
@@ -183,140 +158,70 @@ interface MetricDataDetailsOCIParams {
183158 String resourceGroup = "dummy_resourceGroup" ;
184159 }
185160
186- static class MockMonitoring implements Monitoring {
187- @ Override
188- public String getEndpoint () {
189- return "http://www.DummyEndpoint.com" ;
190- }
191-
192- @ Override
193- public void setEndpoint (String s ) {
194- }
195-
196- @ Override
197- public void setRegion (Region region ) {
198- }
199-
200- @ Override
201- public void setRegion (String s ) {
202- }
203-
204- @ Override
205- public void useRealmSpecificEndpointTemplate (boolean b ) {
206- }
207-
208- @ Override
209- public void refreshClient () {
210- }
211-
212- @ Override
213- public ChangeAlarmCompartmentResponse changeAlarmCompartment (ChangeAlarmCompartmentRequest changeAlarmCompartmentRequest ) {
214- return null ;
215- }
216-
217- @ Override
218- public CreateAlarmResponse createAlarm (CreateAlarmRequest createAlarmRequest ) {
219- return null ;
220- }
221-
222- @ Override
223- public CreateAlarmSuppressionResponse createAlarmSuppression (CreateAlarmSuppressionRequest createAlarmSuppressionRequest ) {
224- return null ;
225- }
226-
227- @ Override
228- public DeleteAlarmResponse deleteAlarm (DeleteAlarmRequest deleteAlarmRequest ) {
229- return null ;
230- }
231-
232- @ Override
233- public DeleteAlarmSuppressionResponse deleteAlarmSuppression (DeleteAlarmSuppressionRequest deleteAlarmSuppressionRequest ) {
234- return null ;
235- }
236-
237- @ Override
238- public GetAlarmResponse getAlarm (GetAlarmRequest getAlarmRequest ) {
239- return null ;
240- }
241-
242- @ Override
243- public GetAlarmHistoryResponse getAlarmHistory (GetAlarmHistoryRequest getAlarmHistoryRequest ) {
244- return null ;
245- }
246-
247- @ Override
248- public GetAlarmSuppressionResponse getAlarmSuppression (GetAlarmSuppressionRequest getAlarmSuppressionRequest ) {
249- return null ;
250- }
251-
252- @ Override
253- public ListAlarmSuppressionsResponse listAlarmSuppressions (ListAlarmSuppressionsRequest listAlarmSuppressionsRequest ) {
254- return null ;
255- }
256-
257- @ Override
258- public ListAlarmsResponse listAlarms (ListAlarmsRequest listAlarmsRequest ) {
259- return null ;
260- }
261-
262- @ Override
263- public ListAlarmsStatusResponse listAlarmsStatus (ListAlarmsStatusRequest listAlarmsStatusRequest ) {
264- return null ;
265- }
266-
267- @ Override
268- public ListMetricsResponse listMetrics (ListMetricsRequest listMetricsRequest ) {
269- return null ;
270- }
271-
272- @ Override
273- public PostMetricDataResponse postMetricData (PostMetricDataRequest postMetricDataRequest ) {
274- postMetricDataDetails = postMetricDataRequest .getPostMetricDataDetails ();
275- testMetricCount = postMetricDataDetails .getMetricData ().size ();
276- // Give signal that testMetricCount was retrieved
277- countDownLatch .countDown ();
278- return PostMetricDataResponse .builder ()
279- .__httpStatusCode__ (200 )
280- .build ();
281- }
282-
283- @ Override
284- public RemoveAlarmSuppressionResponse removeAlarmSuppression (RemoveAlarmSuppressionRequest removeAlarmSuppressionRequest ) {
285- return null ;
286- }
287-
288- @ Override
289- public RetrieveDimensionStatesResponse retrieveDimensionStates (RetrieveDimensionStatesRequest retrieveDimensionStatesRequest ) {
290- return null ;
291- }
292-
293- @ Override
294- public SummarizeAlarmSuppressionHistoryResponse summarizeAlarmSuppressionHistory (SummarizeAlarmSuppressionHistoryRequest summarizeAlarmSuppressionHistoryRequest ) {
295- return null ;
296- }
297-
298- @ Override
299- public SummarizeMetricsDataResponse summarizeMetricsData (SummarizeMetricsDataRequest summarizeMetricsDataRequest ) {
300- return null ;
301- }
302-
303- @ Override
304- public UpdateAlarmResponse updateAlarm (UpdateAlarmRequest updateAlarmRequest ) {
305- return null ;
306- }
307-
308- @ Override
309- public MonitoringWaiters getWaiters () {
310- return null ;
311- }
312-
313- @ Override
314- public MonitoringPaginators getPaginators () {
315- return null ;
161+ // Use this to replace OciExtension, but will only process OCI Monitoring annotation. If the Monitoring
162+ // annotation is found, a Mocked Monitoring object will be injected as a bean
163+ static public class MockOciMonitoringExtension implements Extension {
164+ boolean monitoringFound ;
165+ Set <Annotation > monitoringQualifiers ;
166+
167+ void processInjectionPoint (@ Observes final ProcessInjectionPoint <?, ?> event ) {
168+ if (event != null ) {
169+ InjectionPoint ip = event .getInjectionPoint ();
170+ Class <?> c = (Class <?>) ip .getAnnotated ().getBaseType ();
171+ final Set <Annotation > existingQualifiers = ip .getQualifiers ();
172+ if (c == Monitoring .class && existingQualifiers != null && !existingQualifiers .isEmpty ()) {
173+ monitoringFound = true ;
174+ monitoringQualifiers = existingQualifiers ;
175+ }
176+ }
316177 }
317178
318- @ Override
319- public void close () throws Exception {
179+ Monitoring getMockedMonitoring () {
180+ // Use Proxy to mock only getEndPoint() and postMetricDataDetails() methods of the Monitoring interface,
181+ // as those are the only ones needed by the test
182+ return
183+ (Monitoring ) Proxy .newProxyInstance (
184+ Monitoring .class .getClassLoader (),
185+ new Class [] {Monitoring .class },
186+ (proxy , method , args ) -> {
187+ if (method .getName ().equals ("getEndpoint" )) {
188+ return "http://www.DummyEndpoint.com" ;
189+ } else if (method .getName ().equals ("postMetricData" )) {
190+ PostMetricDataRequest postMetricDataRequest = (PostMetricDataRequest ) args [0 ];
191+ postMetricDataDetails = postMetricDataRequest .getPostMetricDataDetails ();
192+ testMetricCount = (int ) postMetricDataDetails .getMetricData ().stream ()
193+ .filter (details -> details .getName ().contains (METRIC_NAME_SUFFIX ))
194+ .count ();
195+ PostMetricDataResponse response = PostMetricDataResponse .builder ()
196+ .__httpStatusCode__ (200 )
197+ .build ();
198+
199+ // Give signal that metrics will be posted if the right no. of metrics has been retrieved.
200+ // If not, that means that the metrics have not been registered yet, so try again on the
201+ // next invocation.
202+ if (testMetricCount > 0 ) {
203+ countDownLatch .countDown ();
204+ }
205+ return response ;
206+ }
207+ return null ;
208+ });
209+ }
210+
211+ void afterBeanDiscovery (@ Observes AfterBeanDiscovery event ) {
212+ if (monitoringFound ) {
213+ BeanConfigurator <Object > beanConfigurator = event .addBean ()
214+ .types (Monitoring .class )
215+ .scope (ApplicationScoped .class )
216+ .addQualifiers (monitoringQualifiers );
217+ beanConfigurator = monitoringQualifiers != null ? beanConfigurator .addQualifiers (monitoringQualifiers ) :
218+ beanConfigurator .addQualifier (Default .Literal .INSTANCE );
219+ // Add the mocked Monitoring as a bean
220+ beanConfigurator .produceWith (obj -> getMockedMonitoring ());
221+ } else {
222+ throw new IllegalStateException ("Monitoring was never injected. Check if OciMetricsBean.registerOciMetrics() "
223+ + "has changed and does not inject Monitoring anymore." );
224+ }
320225 }
321226 }
322227
0 commit comments