Skip to content

Commit

Permalink
feat(diagnostic): implement diagnostics class with gc invocation oper…
Browse files Browse the repository at this point in the history
…ation
  • Loading branch information
andrewazores committed Sep 10, 2024
1 parent 9e2a375 commit 08ae0f6
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 0 deletions.
42 changes: 42 additions & 0 deletions src/main/java/io/cryostat/diagnostic/Diagnostics.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright The Cryostat Authors.
*
* Licensed 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 io.cryostat.diagnostic;

import io.cryostat.targets.Target;
import io.cryostat.targets.TargetConnectionManager;

import io.smallrye.common.annotation.Blocking;
import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Inject;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import org.jboss.resteasy.reactive.RestPath;

@Path("/api/beta/diagnostics/targets/{targetId}")
public class Diagnostics {

@Inject TargetConnectionManager targetConnectionManager;

@Path("/gc")
@RolesAllowed("write")
@Blocking
@POST
public void gc(@RestPath long targetId) {
targetConnectionManager.executeConnectedTask(
Target.getTargetById(targetId),
conn -> conn.invokeMBeanOperation("java.lang:type=Memory", "gc", null, null, Void.class));
}
}
56 changes: 56 additions & 0 deletions src/main/java/io/cryostat/targets/AgentClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import org.openjdk.jmc.common.unit.IConstrainedMap;
Expand Down Expand Up @@ -108,6 +109,53 @@ Uni<MBeanMetrics> mbeanMetrics() {
.map(Unchecked.function(s -> mapper.readValue(s, MBeanMetrics.class)));
}

<T> Uni<T> invokeMBeanOperation(
String beanName,
String operation,
Object[] parameters,
String[] signature,
Class<T> returnType) {
try {
var req = new MBeanInvocationRequest(beanName, operation, parameters, signature);
return invoke(
HttpMethod.POST,
"/mbean-invoke/",
Buffer.buffer(mapper.writeValueAsBytes(req)),
BodyCodec.buffer())
.map(
Unchecked.function(
resp -> {
int statusCode = resp.statusCode();
if (HttpStatusCodeIdentifier.isSuccessCode(statusCode)) {
return resp;
} else if (statusCode == 403) {
logger.errorv(
"invokeMBeanOperation {0} ({1}) for {2} failed:"
+ " HTTP 403",
beanName, operation, getUri());
throw new ForbiddenException(
new UnsupportedOperationException(
"startRecording"));
} else {
logger.errorv(
"invokeMBeanOperation for {0} for ({1}) {2}"
+ " failed: HTTP {3}",
beanName, operation, getUri(), statusCode);
throw new AgentApiException(statusCode);
}
}))
.map(HttpResponse::bodyAsBuffer)
.map(
buff -> {
// TODO implement conditional handling based on expected returnType
return null;
});
} catch (JsonProcessingException e) {
logger.error("invokeMBeanOperation request failed", e);
return Uni.createFrom().failure(e);
}
}

Uni<IRecordingDescriptor> startRecording(StartRecordingRequest req) {
try {
return invoke(
Expand Down Expand Up @@ -568,4 +616,12 @@ public IOptionDescriptor<?> getOptionInfo(String s) {
return getOptionDescriptors().get(s);
}
}

static record MBeanInvocationRequest(
String beanName, String operation, Object[] parameters, String[] signature) {
MBeanInvocationRequest {
Objects.requireNonNull(beanName);
Objects.requireNonNull(operation);
}
}
}
12 changes: 12 additions & 0 deletions src/main/java/io/cryostat/targets/AgentConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,18 @@ public JvmIdentifier getJvmIdentifier() throws IDException, IOException {
}
}

@Override
public <T> T invokeMBeanOperation(
String beanName,
String operation,
Object[] parameters,
String[] signature,
Class<T> returnType) {
return client.invokeMBeanOperation(beanName, operation, parameters, signature, returnType)
.await()
.atMost(client.getTimeout());
}

@Override
public int getPort() {
return getUri().getPort();
Expand Down

0 comments on commit 08ae0f6

Please sign in to comment.