Skip to content

Commit

Permalink
fix(archives): correct recording metadata in S3 tags (#105)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewazores authored Nov 21, 2023
1 parent 20e0304 commit de4db51
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 47 deletions.
36 changes: 27 additions & 9 deletions src/main/java/io/cryostat/recordings/RecordingHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.ResponseBuilder;
import jdk.jfr.RecordingState;
import org.apache.commons.codec.binary.Base32;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
Expand Down Expand Up @@ -122,6 +123,8 @@ public class RecordingHelper {
@Inject Clock clock;
@Inject S3Presigner presigner;

@Inject Base32 base32;

@Inject
@Named(Producers.BASE64_URL)
Base64 base64Url;
Expand Down Expand Up @@ -369,7 +372,7 @@ public String saveRecording(ActiveRecording recording, Instant expiry) throws Ex
String filename =
String.format("%s_%s_%s.jfr", transformedAlias, recording.name, timestamp);
int mib = 1024 * 1024;
String key = String.format("%s/%s", recording.target.jvmId, filename);
String key = archivedRecordingKey(recording.target.jvmId, filename);
String multipartId = null;
List<Pair<Integer, String>> parts = new ArrayList<>();
try (var stream = remoteRecordingStreamFactory.open(recording);
Expand All @@ -380,9 +383,7 @@ public String saveRecording(ActiveRecording recording, Instant expiry) throws Ex
.bucket(archiveBucket)
.key(key)
.contentType(JFR_MIME)
.tagging(
createMetadataTagging(
new Metadata(recording.metadata, expiry)));
.tagging(createActiveRecordingTagging(recording, expiry));
if (expiry != null && expiry.isAfter(Instant.now())) {
builder = builder.expires(expiry);
}
Expand Down Expand Up @@ -467,12 +468,17 @@ public String saveRecording(ActiveRecording recording, Instant expiry) throws Ex
throw e;
}
if (expiry == null) {
LinkedRecordingDescriptor serializedRecording = toExternalForm(recording);
bus.publish(
MessagingServer.class.getName(),
new Notification(
"ActiveRecordingSaved",
new RecordingEvent(
recording.target.connectUrl, toExternalForm(recording))));
new RecordingEvent(recording.target.connectUrl, serializedRecording)));
bus.publish(
MessagingServer.class.getName(),
new Notification(
"ArchivedRecordingCreated",
new RecordingEvent(recording.target.connectUrl, serializedRecording)));
}
return filename;
}
Expand All @@ -497,7 +503,11 @@ private Optional<Metadata> getArchivedRecordingMetadata(String storageKey) {
}
}

private String decodeBase64(String encoded) {
String decodeBase32(String encoded) {
return new String(base32.decode(encoded), StandardCharsets.UTF_8);
}

String decodeBase64(String encoded) {
return new String(base64Url.decode(encoded), StandardCharsets.UTF_8);
}

Expand Down Expand Up @@ -588,7 +598,7 @@ public void deleteArchivedRecording(String jvmId, String filename) {
storage.deleteObject(
DeleteObjectRequest.builder()
.bucket(archiveBucket)
.key(String.format("%s/%s", jvmId, filename))
.key(archivedRecordingKey(jvmId, filename))
.build());
bus.publish(
MessagingServer.class.getName(),
Expand All @@ -597,8 +607,16 @@ public void deleteArchivedRecording(String jvmId, String filename) {
new RecordingEvent(URI.create("localhost:0"), Map.of("name", filename))));
}

Tagging createActiveRecordingTagging(ActiveRecording recording, Instant expiry) {
Map<String, String> labels = new HashMap<>(recording.metadata.labels());
labels.put("connectUrl", recording.target.connectUrl.toString());
labels.put("jvmId", recording.target.jvmId);
Metadata metadata = new Metadata(labels, expiry);
return createMetadataTagging(metadata);
}

// Metadata
private Tagging createMetadataTagging(Metadata metadata) {
Tagging createMetadataTagging(Metadata metadata) {
// TODO attach other metadata than labels somehow. Prefixed keys to create partitioning?
var tags = new ArrayList<Tag>();
tags.addAll(
Expand Down
45 changes: 7 additions & 38 deletions src/main/java/io/cryostat/recordings/Recordings.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
Expand Down Expand Up @@ -77,7 +76,6 @@
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.Response;
import jdk.jfr.RecordingState;
import org.apache.commons.codec.binary.Base32;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
Expand All @@ -99,8 +97,6 @@
import software.amazon.awssdk.services.s3.model.ObjectIdentifier;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Object;
import software.amazon.awssdk.services.s3.model.Tag;
import software.amazon.awssdk.services.s3.model.Tagging;
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest;
import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest;
Expand All @@ -121,8 +117,6 @@ public class Recordings {
@Inject ObjectMapper mapper;
@Inject RecordingHelper recordingHelper;

@Inject Base32 base32;

@Inject
@Named(Producers.BASE64_URL)
Base64 base64Url;
Expand Down Expand Up @@ -220,6 +214,7 @@ public void agentPush(
if (rawLabels != null) {
rawLabels.getMap().forEach((k, v) -> labels.put(k, v.toString()));
}
labels.put("jvmId", jvmId);
Metadata metadata = new Metadata(labels);
logger.infov(
"recording:{0}, labels:{1}, maxFiles:{2}", recording.fileName(), labels, maxFiles);
Expand Down Expand Up @@ -345,13 +340,15 @@ Map<String, Object> doUpload(FileUpload recording, Metadata metadata, String jvm
if (!filename.endsWith(".jfr")) {
filename = filename + ".jfr";
}
Map<String, String> labels = new HashMap<>(metadata.labels);
labels.put("jvmId", jvmId);
String key = recordingHelper.archivedRecordingKey(jvmId, filename);
storage.putObject(
PutObjectRequest.builder()
.bucket(archiveBucket)
.key(key)
.contentType(RecordingHelper.JFR_MIME)
.tagging(createMetadataTagging(metadata))
.tagging(recordingHelper.createMetadataTagging(new Metadata(labels)))
.build(),
RequestBody.fromFile(recording.filePath()));
logger.info("Upload complete");
Expand Down Expand Up @@ -663,7 +660,7 @@ public void deleteRecording(@RestPath long targetId, @RestPath long remoteId) th
@RolesAllowed("write")
public void deleteArchivedRecording(@RestPath String encodedJvmId, @RestPath String filename)
throws Exception {
var jvmId = decodeBase32(encodedJvmId);
var jvmId = recordingHelper.decodeBase32(encodedJvmId);
logger.infov("Handling archived recording deletion: {0} / {1}", jvmId, filename);
var metadata =
recordingHelper
Expand All @@ -676,7 +673,8 @@ public void deleteArchivedRecording(@RestPath String encodedJvmId, @RestPath Str
.map(c -> c.toString())
.orElseGet(() -> metadata.labels.computeIfAbsent("connectUrl", k -> jvmId));
logger.infov(
"Archived recording from connectUrl {0} has metadata: {1}", connectUrl, metadata);
"Archived recording from connectUrl \"{0}\" has metadata: {1}",
connectUrl, metadata);
logger.infov(
"Sending S3 deletion request for {0} {1}",
archiveBucket, recordingHelper.archivedRecordingKey(jvmId, filename));
Expand Down Expand Up @@ -834,35 +832,6 @@ public Response redirectPresignedDownload(@RestPath String encodedKey)
.build();
}

private Tagging createMetadataTagging(Metadata metadata) {
// TODO attach other metadata than labels somehow. Prefixed keys to create partitioning?
return Tagging.builder()
.tagSet(
metadata.labels.entrySet().stream()
.map(
e ->
Tag.builder()
.key(
base64Url.encodeAsString(
e.getKey()
.getBytes(
StandardCharsets
.UTF_8)))
.value(
base64Url.encodeAsString(
e.getValue()
.getBytes(
StandardCharsets
.UTF_8)))
.build())
.toList())
.build();
}

private String decodeBase32(String encoded) {
return new String(base32.decode(encoded), StandardCharsets.UTF_8);
}

private static Map<String, Object> getRecordingOptions(
IFlightRecorderService service, RecordingOptionsBuilder builder) throws Exception {
IConstrainedMap<String> recordingOptions = builder.build();
Expand Down

0 comments on commit de4db51

Please sign in to comment.