Skip to content

Commit

Permalink
feat(agent): implement Agent HTTP recording retrieval (#1607)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewazores committed Sep 13, 2023
1 parent 44c9344 commit f23066c
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 13 deletions.
16 changes: 16 additions & 0 deletions src/main/java/io/cryostat/net/AgentClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,22 @@ Future<IRecordingDescriptor> startRecording(StartRecordingRequest req) {
});
}

Future<Buffer> openStream(long id) {
Future<HttpResponse<Buffer>> f =
invoke(HttpMethod.GET, "/recordings/" + id, BodyCodec.buffer());
return f.map(
resp -> {
int statusCode = resp.statusCode();
if (HttpStatusCodeIdentifier.isSuccessCode(statusCode)) {
return resp.body();
} else if (statusCode == 403) {
throw new UnsupportedOperationException();
} else {
throw new RuntimeException("Unknown failure");
}
});
}

Future<Void> stopRecording(long id) {
Future<HttpResponse<Void>> f =
invoke(
Expand Down
23 changes: 19 additions & 4 deletions src/main/java/io/cryostat/net/AgentJFRService.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package io.cryostat.net;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
Expand Down Expand Up @@ -51,6 +53,8 @@
import io.cryostat.core.templates.Template;
import io.cryostat.core.templates.TemplateType;

import io.vertx.core.Future;
import io.vertx.core.buffer.Buffer;
import org.jsoup.nodes.Document;

class AgentJFRService implements CryostatFlightRecorderService {
Expand Down Expand Up @@ -186,20 +190,31 @@ public boolean isEnabled() {
}

@Override
public InputStream openStream(IRecordingDescriptor arg0, boolean arg1)
public InputStream openStream(IRecordingDescriptor descriptor, boolean removeOnClose)
throws FlightRecorderException {
throw new UnimplementedException();
Future<Buffer> f = client.openStream(descriptor.getId());
try {
Buffer b = f.toCompletionStage().toCompletableFuture().get();
return new BufferedInputStream(new ByteArrayInputStream(b.getBytes()));
} catch (ExecutionException | InterruptedException e) {
logger.warn(e);
throw new FlightRecorderException("Failed to open remote recording stream", e);
}
}

@Override
public InputStream openStream(IRecordingDescriptor arg0, IQuantity arg1, boolean arg2)
public InputStream openStream(
IRecordingDescriptor descriptor, IQuantity lastPartDuration, boolean removeOnClose)
throws FlightRecorderException {
throw new UnimplementedException();
}

@Override
public InputStream openStream(
IRecordingDescriptor arg0, IQuantity arg1, IQuantity arg2, boolean arg3)
IRecordingDescriptor descriptor,
IQuantity startTime,
IQuantity endTime,
boolean removeOnClose)
throws FlightRecorderException {
throw new UnimplementedException();
}
Expand Down
10 changes: 2 additions & 8 deletions src/main/java/io/cryostat/net/web/WebServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
import io.cryostat.MainModule;
import io.cryostat.core.log.Logger;
import io.cryostat.core.net.JFRConnection;
import io.cryostat.net.AgentConnection;
import io.cryostat.net.AuthManager;
import io.cryostat.net.HttpServer;
import io.cryostat.net.NetworkConfiguration;
Expand All @@ -50,6 +49,7 @@
import io.cryostat.net.web.http.api.ApiVersion;
import io.cryostat.net.web.http.api.v2.ApiException;
import io.cryostat.util.HttpStatusCodeIdentifier;
import io.cryostat.util.URIUtil;

import com.google.gson.Gson;
import io.vertx.core.AbstractVerticle;
Expand Down Expand Up @@ -296,13 +296,7 @@ public String getAssetDownloadURL(ApiVersion apiVersion, String... pathSegments)
}

private String getTargetId(JFRConnection conn) throws IOException {
// TODO this is a hack, the JFRConnection interface should be refactored to expose a more
// general connection URL / targetId method since the JMX implementation is now only one
// possible implementation
if (conn instanceof AgentConnection) {
return ((AgentConnection) conn).getUri().toString();
}
return conn.getJMXURL().toString();
return URIUtil.getConnectionUri(conn).toString();
}

public FileUpload getTempFileUpload(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -916,7 +916,7 @@ private void validateRecordingPath(

Path writeRecordingToDestination(JFRConnection connection, IRecordingDescriptor descriptor)
throws IOException, URISyntaxException, FlightRecorderException, Exception {
URI serviceUri = URIUtil.convert(connection.getJMXURL());
URI serviceUri = URIUtil.getConnectionUri(connection);
String jvmId = jvmIdHelper.getJvmId(serviceUri.toString());
Path specificRecordingsPath = getRecordingSubdirectoryPath(jvmId);
if (!fs.exists(specificRecordingsPath)) {
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/io/cryostat/util/URIUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,15 @@
*/
package io.cryostat.util;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

import javax.management.remote.JMXServiceURL;

import io.cryostat.core.net.JFRConnection;
import io.cryostat.net.AgentConnection;

public class URIUtil {
private URIUtil() {}

Expand Down Expand Up @@ -48,4 +52,14 @@ public static URI getRmiTarget(JMXServiceURL serviceUrl) throws URISyntaxExcepti
}
return new URI(pathPart.substring("/jndi/".length(), pathPart.length()));
}

public static URI getConnectionUri(JFRConnection connection) throws IOException {
// TODO this is a hack, the JFRConnection interface should be refactored to expose a more
// general connection URL / targetId method since the JMX implementation is now only one
// possible implementation
if (connection instanceof AgentConnection) {
return ((AgentConnection) connection).getUri();
}
return URI.create(connection.getJMXURL().toString());
}
}

0 comments on commit f23066c

Please sign in to comment.