diff --git a/HTTP_API.md b/HTTP_API.md index e2d0a8c792..1ab04b391c 100644 --- a/HTTP_API.md +++ b/HTTP_API.md @@ -1238,7 +1238,7 @@ The handler-specific descriptions below describe how each handler populates the | What you want to do | Which handler you should use | | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------| | **Recordings in Target JVMs** | | -| Search event types that can be produced by a target JVM | [`TargetEventsSearchGetHandler`](#TargetEventsSearchGetHandler) | +| List or search event types that can be produced by a target JVM | [`TargetEventsGetHandler`](#TargetEventsGetHandler) | | Get a list of recording options for a target JVM | [`TargetRecordingOptionsListGetHandler`](#TargetRecordingOptionsListGetHandler) | | Create a snapshot recording in a target JVM | [`TargetSnapshotPostHandler`](#TargetSnapshotPostHandler-1) | | **Automated Rules** | | @@ -1254,20 +1254,22 @@ The handler-specific descriptions below describe how each handler populates the ### Recordings in Target JVMs -* #### `TargetEventsSearchGetHandler` +* #### `TargetEventsGetHandler` ###### synopsis Returns a list of event types that can be produced by a target JVM, where the event name, category, label, etc. matches the given query. ###### request - `GET /api/v2/targets/:targetId/eventsSearch/:query` + `GET /api/v2/targets/:targetId/events[?q=searchQuery]` `targetId` - The location of the target JVM to connect to, in the form of a `service:rmi:jmx://` JMX Service URL, or `hostname:port`. Should use percent-encoding. - `query` - The search query. + `q` - The search query. Event names, IDs, categories, and descriptions will + be searched for case-insensitive substring matches of the supplied query. If + this parameter is omitted or blank then all events will be returned. ###### response `200` - The result is a JSON array of event objects. @@ -1293,7 +1295,7 @@ The handler-specific descriptions below describe how each handler populates the ###### example ``` - $ curl localhost:8181/api/v2/targets/localhost/eventsSearch/javaerrorthrow + $ curl localhost:8181/api/v2/targets/localhost/events?q=javaerrorthrow {"meta":{"type":"application/json","status":"OK"},"data":{"result":[{"name":"Java Error","typeId":"jdk.JavaErrorThrow","description":"An object derived from java.lang.Error has been created. OutOfMemoryErrors are ignored","category":["Java Application"],"options":{"enabled":{"name":"Enabled","description":"Record event","defaultValue":"false"},"threshold":{"name":"Threshold","description":"Record event with duration above or equal to threshold","defaultValue":"0ns[ns]"},"stackTrace":{"name":"Stack Trace","description":"Record stack traces","defaultValue":"false"}}}]}} ``` diff --git a/src/main/java/io/cryostat/net/web/http/api/v2/HttpApiV2Module.java b/src/main/java/io/cryostat/net/web/http/api/v2/HttpApiV2Module.java index e2ab53c69e..72da0c186b 100644 --- a/src/main/java/io/cryostat/net/web/http/api/v2/HttpApiV2Module.java +++ b/src/main/java/io/cryostat/net/web/http/api/v2/HttpApiV2Module.java @@ -87,7 +87,7 @@ abstract RequestHandler bindTargetRecordingOptionsListGetHandler( @Binds @IntoSet - abstract RequestHandler bindTargetEventsSearchGetHandler(TargetEventsSearchGetHandler handler); + abstract RequestHandler bindTargetEventsGetHandler(TargetEventsGetHandler handler); @Provides @Singleton diff --git a/src/main/java/io/cryostat/net/web/http/api/v2/TargetEventsSearchGetHandler.java b/src/main/java/io/cryostat/net/web/http/api/v2/TargetEventsGetHandler.java similarity index 89% rename from src/main/java/io/cryostat/net/web/http/api/v2/TargetEventsSearchGetHandler.java rename to src/main/java/io/cryostat/net/web/http/api/v2/TargetEventsGetHandler.java index 7ef35041d4..9bbba64520 100644 --- a/src/main/java/io/cryostat/net/web/http/api/v2/TargetEventsSearchGetHandler.java +++ b/src/main/java/io/cryostat/net/web/http/api/v2/TargetEventsGetHandler.java @@ -55,14 +55,14 @@ import com.google.gson.Gson; import io.vertx.core.http.HttpMethod; +import org.apache.commons.lang3.StringUtils; -class TargetEventsSearchGetHandler - extends AbstractV2RequestHandler> { +class TargetEventsGetHandler extends AbstractV2RequestHandler> { private final TargetConnectionManager targetConnectionManager; @Inject - TargetEventsSearchGetHandler( + TargetEventsGetHandler( AuthManager auth, TargetConnectionManager targetConnectionManager, Gson gson) { super(auth, gson); this.targetConnectionManager = targetConnectionManager; @@ -85,7 +85,7 @@ public HttpMethod httpMethod() { @Override public String path() { - return basePath() + "targets/:targetId/eventsSearch/:query"; + return basePath() + "targets/:targetId/events"; } @Override @@ -104,13 +104,14 @@ public IntermediateResponse> handle(RequestParam return targetConnectionManager.executeConnectedTask( getConnectionDescriptorFromParams(params), connection -> { - String query = params.getPathParams().get("query"); + String q = params.getQueryParams().get("q"); List matchingEvents = connection.getService().getAvailableEventTypes().stream() .filter( event -> - eventMatchesSearchTerm( - event, query.toLowerCase())) + StringUtils.isBlank(q) + || eventMatchesSearchTerm( + event, q.toLowerCase())) .map(SerializableEventTypeInfo::new) .collect(Collectors.toList()); return new IntermediateResponse>() diff --git a/src/test/java/io/cryostat/net/web/http/api/v2/TargetEventsSearchGetHandlerTest.java b/src/test/java/io/cryostat/net/web/http/api/v2/TargetEventsGetHandlerTest.java similarity index 94% rename from src/test/java/io/cryostat/net/web/http/api/v2/TargetEventsSearchGetHandlerTest.java rename to src/test/java/io/cryostat/net/web/http/api/v2/TargetEventsGetHandlerTest.java index f87568fea5..662ede1d68 100644 --- a/src/test/java/io/cryostat/net/web/http/api/v2/TargetEventsSearchGetHandlerTest.java +++ b/src/test/java/io/cryostat/net/web/http/api/v2/TargetEventsGetHandlerTest.java @@ -71,9 +71,9 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) -class TargetEventsSearchGetHandlerTest { +class TargetEventsGetHandlerTest { - TargetEventsSearchGetHandler handler; + TargetEventsGetHandler handler; @Mock AuthManager auth; @Mock TargetConnectionManager targetConnectionManager; @Mock Logger logger; @@ -83,7 +83,7 @@ class TargetEventsSearchGetHandlerTest { @BeforeEach void setup() { - this.handler = new TargetEventsSearchGetHandler(auth, targetConnectionManager, gson); + this.handler = new TargetEventsGetHandler(auth, targetConnectionManager, gson); } @Test @@ -94,7 +94,7 @@ void shouldHandleGETRequest() { @Test void shouldHandleCorrectPath() { MatcherAssert.assertThat( - handler.path(), Matchers.equalTo("/api/v2/targets/:targetId/eventsSearch/:query")); + handler.path(), Matchers.equalTo("/api/v2/targets/:targetId/events")); } @Test @@ -111,8 +111,8 @@ void shouldHandleNoMatches() throws Exception { RequestParameters params = new RequestParameters( - Map.of("targetId", "foo:9091", "query", "foo"), - MultiMap.caseInsensitiveMultiMap(), + Map.of("targetId", "foo:9091"), + MultiMap.caseInsensitiveMultiMap().set("q", "foo"), MultiMap.caseInsensitiveMultiMap(), MultiMap.caseInsensitiveMultiMap(), Set.of(), @@ -179,8 +179,8 @@ void shouldHandleMatches() throws Exception { RequestParameters params = new RequestParameters( - Map.of("targetId", "foo:9091", "query", "foo"), - MultiMap.caseInsensitiveMultiMap(), + Map.of("targetId", "foo:9091"), + MultiMap.caseInsensitiveMultiMap().set("q", "foo"), MultiMap.caseInsensitiveMultiMap(), MultiMap.caseInsensitiveMultiMap(), Set.of(), diff --git a/src/test/java/itest/TargetEventsGetIT.java b/src/test/java/itest/TargetEventsGetIT.java index c7f849e895..647295e68a 100644 --- a/src/test/java/itest/TargetEventsGetIT.java +++ b/src/test/java/itest/TargetEventsGetIT.java @@ -57,7 +57,7 @@ public class TargetEventsGetIT extends StandardSelfTest { static final String EVENT_REQ_URL = String.format("/api/v1/targets/%s/events", SELF_REFERENCE_TARGET_ID); static final String SEARCH_REQ_URL = - String.format("/api/v2/targets/%s/eventsSearch", SELF_REFERENCE_TARGET_ID); + String.format("/api/v2/targets/%s/events", SELF_REFERENCE_TARGET_ID); @Test public void testGetTargetEventsReturnsListOfEvents() throws Exception { @@ -80,10 +80,33 @@ public void testGetTargetEventsReturnsListOfEvents() throws Exception { } @Test - public void testGetTargetEventsSearchReturnsRequestedEvents() throws Exception { + public void testGetTargetEventsV2WithNoQueryReturnsListOfEvents() throws Exception { CompletableFuture getResponse = new CompletableFuture<>(); webClient - .get(String.format("%s/WebServerRequest", SEARCH_REQ_URL)) + .get(SEARCH_REQ_URL) + .send( + ar -> { + if (assertRequestStatus(ar, getResponse)) { + MatcherAssert.assertThat( + ar.result().statusCode(), Matchers.equalTo(200)); + MatcherAssert.assertThat( + ar.result().getHeader(HttpHeaders.CONTENT_TYPE.toString()), + Matchers.equalTo(HttpMimeType.JSON.mime())); + getResponse.complete(ar.result().bodyAsJsonObject()); + } + }); + + MatcherAssert.assertThat(getResponse.get().size(), Matchers.greaterThan(0)); + MatcherAssert.assertThat( + getResponse.get().getJsonObject("data").getJsonArray("result").size(), + Matchers.greaterThan(0)); + } + + @Test + public void testGetTargetEventsV2WithQueryReturnsRequestedEvents() throws Exception { + CompletableFuture getResponse = new CompletableFuture<>(); + webClient + .get(String.format("%s?q=WebServerRequest", SEARCH_REQ_URL)) .send( ar -> { if (assertRequestStatus(ar, getResponse)) { @@ -140,10 +163,10 @@ public void testGetTargetEventsSearchReturnsRequestedEvents() throws Exception { } @Test - public void testGetTargetEventsSearchReturnsEmptyListWhenNoEventsMatch() throws Exception { + public void testGetTargetEventsV2WithQueryReturnsEmptyListWhenNoEventsMatch() throws Exception { CompletableFuture getResponse = new CompletableFuture<>(); webClient - .get(String.format("%s/thisEventDoesNotExist", SEARCH_REQ_URL)) + .get(String.format("%s?q=thisEventDoesNotExist", SEARCH_REQ_URL)) .send( ar -> { if (assertRequestStatus(ar, getResponse)) {