Skip to content

Commit

Permalink
feat(agent): implement Agent HTTP dynamic JFR stop/delete (#1604)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewazores committed Sep 18, 2023
1 parent d4e3d88 commit a27bf79
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 9 deletions.
52 changes: 46 additions & 6 deletions src/main/java/io/cryostat/net/AgentClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ Future<Boolean> ping() {

Future<MBeanMetrics> mbeanMetrics() {
Future<HttpResponse<String>> f =
invoke(HttpMethod.GET, "/mbean-metrics", BodyCodec.string());
invoke(HttpMethod.GET, "/mbean-metrics/", BodyCodec.string());
return f.map(HttpResponse::body)
// uses Gson rather than Vertx's Jackson because Gson is able to handle MBeanMetrics
// with no additional fuss. Jackson complains about private final fields.
Expand All @@ -111,7 +111,7 @@ Future<IRecordingDescriptor> startRecording(StartRecordingRequest req) {
Future<HttpResponse<String>> f =
invoke(
HttpMethod.POST,
"/recordings",
"/recordings/",
Buffer.buffer(gson.toJson(req)),
BodyCodec.string());
return f.map(
Expand All @@ -129,8 +129,48 @@ Future<IRecordingDescriptor> startRecording(StartRecordingRequest req) {
});
}

Future<Void> stopRecording(long id) {
Future<HttpResponse<Void>> f =
invoke(
HttpMethod.PATCH,
String.format("/recordings/%d", id),
Buffer.buffer(),
BodyCodec.none());
return f.map(
resp -> {
int statusCode = resp.statusCode();
if (HttpStatusCodeIdentifier.isSuccessCode(statusCode)) {
return null;
} else if (statusCode == 403) {
throw new UnsupportedOperationException();
} else {
throw new RuntimeException("Unknown failure");
}
});
}

Future<Void> deleteRecording(long id) {
Future<HttpResponse<Void>> f =
invoke(
HttpMethod.DELETE,
String.format("/recordings/%d", id),
Buffer.buffer(),
BodyCodec.none());
return f.map(
resp -> {
int statusCode = resp.statusCode();
if (HttpStatusCodeIdentifier.isSuccessCode(statusCode)) {
return null;
} else if (statusCode == 403) {
throw new UnsupportedOperationException();
} else {
throw new RuntimeException("Unknown failure");
}
});
}

Future<List<IRecordingDescriptor>> activeRecordings() {
Future<HttpResponse<String>> f = invoke(HttpMethod.GET, "/recordings", BodyCodec.string());
Future<HttpResponse<String>> f = invoke(HttpMethod.GET, "/recordings/", BodyCodec.string());
return f.map(HttpResponse::body)
.map(
s ->
Expand All @@ -145,14 +185,14 @@ Future<List<IRecordingDescriptor>> activeRecordings() {

Future<Collection<? extends IEventTypeInfo>> eventTypes() {
Future<HttpResponse<JsonArray>> f =
invoke(HttpMethod.GET, "/event-types", BodyCodec.jsonArray());
invoke(HttpMethod.GET, "/event-types/", BodyCodec.jsonArray());
return f.map(HttpResponse::body)
.map(arr -> arr.stream().map(o -> new AgentEventTypeInfo((JsonObject) o)).toList());
}

Future<IConstrainedMap<EventOptionID>> eventSettings() {
Future<HttpResponse<JsonArray>> f =
invoke(HttpMethod.GET, "/event-settings", BodyCodec.jsonArray());
invoke(HttpMethod.GET, "/event-settings/", BodyCodec.jsonArray());
return f.map(HttpResponse::body)
.map(
arr -> {
Expand Down Expand Up @@ -206,7 +246,7 @@ Future<IConstrainedMap<EventOptionID>> eventSettings() {

Future<List<String>> eventTemplates() {
Future<HttpResponse<JsonArray>> f =
invoke(HttpMethod.GET, "/event-templates", BodyCodec.jsonArray());
invoke(HttpMethod.GET, "/event-templates/", BodyCodec.jsonArray());
return f.map(HttpResponse::body).map(arr -> arr.stream().map(Object::toString).toList());
}

Expand Down
20 changes: 17 additions & 3 deletions src/main/java/io/cryostat/net/AgentJFRService.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,14 @@ public String getVersion() {

@Override
public void close(IRecordingDescriptor descriptor) throws FlightRecorderException {
throw new UnimplementedException();
try {
client.deleteRecording(descriptor.getId())
.toCompletionStage()
.toCompletableFuture()
.get();
} catch (InterruptedException | ExecutionException e) {
throw new FlightRecorderException("Failed to stop recording", e);
}
}

@Override
Expand Down Expand Up @@ -205,8 +212,15 @@ public IRecordingDescriptor start(
}

@Override
public void stop(IRecordingDescriptor arg0) throws FlightRecorderException {
throw new UnimplementedException();
public void stop(IRecordingDescriptor descriptor) throws FlightRecorderException {
try {
client.stopRecording(descriptor.getId())
.toCompletionStage()
.toCompletableFuture()
.get();
} catch (InterruptedException | ExecutionException e) {
throw new FlightRecorderException("Failed to stop recording", e);
}
}

@Override
Expand Down

0 comments on commit a27bf79

Please sign in to comment.