Skip to content

Commit

Permalink
feat(recordings): include jvmId in Notifications to -web (#1689)
Browse files Browse the repository at this point in the history
  • Loading branch information
mwangggg authored Oct 30, 2023
1 parent d33cc44 commit 3202849
Show file tree
Hide file tree
Showing 15 changed files with 344 additions and 321 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
*/
package io.cryostat.messaging.notifications;

import java.time.Instant;
import java.util.HashMap;
import java.util.Map;

import io.cryostat.net.web.http.HttpMimeType;

Expand Down Expand Up @@ -84,10 +85,30 @@ public Notification<T> build() {
}
}

public static class OwnedResourceBuilder extends Builder<Map<String, Object>> {

private final Map<String, Object> map = new HashMap<>();

OwnedResourceBuilder(NotificationSource source, String category) {
super(source);
metaType(HttpMimeType.JSON);
metaCategory(category);
message(map);
}

public OwnedResourceBuilder messageEntry(String key, Object value) {
if (value == null) {
this.map.remove(key);
} else {
this.map.put(key, value);
}
return this;
}
}

public static class Meta {
private final String category;
private final MetaType type;
private final long serverTime = Instant.now().getEpochSecond();

public Meta(String category, MetaType type) {
this.category = category;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,32 @@
*/
package io.cryostat.messaging.notifications;

import io.cryostat.recordings.JvmIdHelper;
import io.cryostat.recordings.JvmIdHelper.JvmIdGetException;

public class NotificationFactory {

private final NotificationSource source;
private final JvmIdHelper jvmIdHelper;

NotificationFactory(NotificationSource source) {
NotificationFactory(NotificationSource source, JvmIdHelper jvmIdHelper) {
this.source = source;
this.jvmIdHelper = jvmIdHelper;
}

public <T> Notification.Builder<T> createBuilder() {
return new Notification.Builder<T>(source);
}

public Notification.OwnedResourceBuilder createOwnedResourceBuilder(
String notificationCategory) {
return new Notification.OwnedResourceBuilder(source, notificationCategory);
}

public Notification.OwnedResourceBuilder createOwnedResourceBuilder(
String targetId, String notificationCategory) throws JvmIdGetException {
return new Notification.OwnedResourceBuilder(source, notificationCategory)
.messageEntry("target", targetId)
.messageEntry("jvmId", jvmIdHelper.getJvmId(targetId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

import javax.inject.Singleton;

import io.cryostat.recordings.JvmIdHelper;

import dagger.Lazy;
import dagger.Module;
import dagger.Provides;
Expand All @@ -34,7 +36,8 @@ static NotificationSource provideNotificationSource(Lazy<Set<NotificationListene

@Provides
@Singleton
static NotificationFactory provideNotificationFactory(NotificationSource source) {
return new NotificationFactory(source);
static NotificationFactory provideNotificationFactory(
NotificationSource source, JvmIdHelper idHelper) {
return new NotificationFactory(source, idHelper);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,22 +84,22 @@ Path copyRecordingToFile(
if (!Objects.equals(rec.getName(), recordingName)) {
continue;
}
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(path.toFile()))) {
try (conn;
InputStream in = conn.getService().openStream(rec, false)) {
byte[] buff = new byte[READ_BUFFER_SIZE];
int n = 0;
while ((n = in.read(buff)) != -1) {
out.write(buff, 0, n);
if (!targetConnectionManager.markConnectionInUse(cd)) {
throw new IOException(
"Target connection unexpectedly closed while streaming"
+ " recording");
}
try (conn;
OutputStream out =
new BufferedOutputStream(new FileOutputStream(path.toFile()));
InputStream in = conn.getService().openStream(rec, false)) {
byte[] buff = new byte[READ_BUFFER_SIZE];
int n = 0;
while ((n = in.read(buff)) != -1) {
out.write(buff, 0, n);
if (!targetConnectionManager.markConnectionInUse(cd)) {
throw new IOException(
"Target connection unexpectedly closed while streaming"
+ " recording");
}
out.flush();
return path;
}
out.flush();
return path;
}
}
throw new RecordingNotFoundException(cd.getTargetId(), recordingName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import io.cryostat.net.web.http.api.v2.ApiException;
import io.cryostat.recordings.JvmIdHelper;
import io.cryostat.recordings.JvmIdHelper.JvmIdDoesNotExistException;
import io.cryostat.recordings.JvmIdHelper.JvmIdGetException;
import io.cryostat.recordings.RecordingArchiveHelper;
import io.cryostat.recordings.RecordingMetadataManager;
import io.cryostat.recordings.RecordingMetadataManager.Metadata;
Expand Down Expand Up @@ -274,35 +275,30 @@ public void handleAuthenticated(RoutingContext ctx) throws Exception {
try {

notificationFactory
.createBuilder()
.metaCategory(NOTIFICATION_CATEGORY)
.metaType(HttpMimeType.JSON)
.message(
Map.of(
"recording",
new ArchivedRecordingInfo(
connectUrl,
fsName,
webServer
.get()
.getArchivedDownloadURL(
connectUrl,
fsName),
webServer
.get()
.getArchivedReportURL(
connectUrl,
fsName),
metadata,
size,
archivedTime),
"target",
connectUrl))
.createOwnedResourceBuilder(
connectUrl, NOTIFICATION_CATEGORY)
.messageEntry(
"recording",
new ArchivedRecordingInfo(
connectUrl,
fsName,
webServer
.get()
.getArchivedDownloadURL(
connectUrl, fsName),
webServer
.get()
.getArchivedReportURL(
connectUrl, fsName),
metadata,
size,
archivedTime))
.build()
.send();
} catch (URISyntaxException
| UnknownHostException
| SocketException e) {
| SocketException
| JvmIdGetException e) {
logger.error(e);
throw new ApiException(500, e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
import io.cryostat.net.security.ResourceAction;
import io.cryostat.net.web.http.HttpMimeType;
import io.cryostat.net.web.http.api.ApiVersion;
import io.cryostat.recordings.JvmIdHelper;
import io.cryostat.recordings.JvmIdHelper.JvmIdGetException;

import com.google.gson.Gson;
import io.vertx.core.http.HttpMethod;
Expand Down Expand Up @@ -76,6 +78,7 @@ class TargetProbePostHandler extends AbstractV2RequestHandler<Void> {
private final NotificationFactory notificationFactory;
private final LocalProbeTemplateService probeTemplateService;
private final FileSystem fs;
private final JvmIdHelper jvmIdHelper;
private final TargetConnectionManager connectionManager;
private final Environment env;
private static final String NOTIFICATION_CATEGORY = "ProbeTemplateApplied";
Expand All @@ -88,13 +91,15 @@ class TargetProbePostHandler extends AbstractV2RequestHandler<Void> {
FileSystem fs,
AuthManager auth,
CredentialsManager credentialsManager,
JvmIdHelper jvmIdHelper,
TargetConnectionManager connectionManager,
Environment env,
Gson gson) {
super(auth, credentialsManager, gson);
this.logger = logger;
this.notificationFactory = notificationFactory;
this.probeTemplateService = service;
this.jvmIdHelper = jvmIdHelper;
this.connectionManager = connectionManager;
this.env = env;
this.fs = fs;
Expand Down Expand Up @@ -151,20 +156,17 @@ public IntermediateResponse<Void> handle(RequestParameters requestParams) throws
new ByteArrayInputStream(
templateContent.getBytes(StandardCharsets.UTF_8)));
List<Event> events = Arrays.asList(template.getEvents());
notificationFactory
.createBuilder()
.metaCategory(NOTIFICATION_CATEGORY)
.metaType(HttpMimeType.JSON)
.message(
Map.of(
"targetId",
targetId,
"probeTemplate",
probeTemplate,
"events",
events))
.build()
.send();
try {
notificationFactory
.createOwnedResourceBuilder(targetId, NOTIFICATION_CATEGORY)
.messageEntry("probeTemplate", probeTemplate)
.messageEntry("events", events)
.build()
.send();
} catch (JvmIdGetException e) {
logger.info("Retain null jvmId for target [{}]", targetId);
logger.info(e);
}
return new IntermediateResponse<Void>().body(null);
});
}
Expand Down
38 changes: 10 additions & 28 deletions src/main/java/io/cryostat/recordings/RecordingArchiveHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CancellationException;
Expand Down Expand Up @@ -66,7 +65,6 @@
import io.cryostat.net.TargetConnectionManager;
import io.cryostat.net.web.WebModule;
import io.cryostat.net.web.WebServer;
import io.cryostat.net.web.http.HttpMimeType;
import io.cryostat.net.web.http.api.v2.ApiException;
import io.cryostat.platform.PlatformClient;
import io.cryostat.recordings.JvmIdHelper.JvmIdGetException;
Expand Down Expand Up @@ -385,36 +383,24 @@ public Future<ArchivedRecordingInfo> saveRecording(
validateSavePath(recordingName, savePath);
Path filenamePath = savePath.getFileName();
String filename = filenamePath.toString();
String targetId = connectionDescriptor.getTargetId();
Metadata metadata =
recordingMetadataManager
.copyMetadataToArchives(connectionDescriptor, recordingName, filename)
.get();
ArchivedRecordingInfo archivedRecordingInfo =
new ArchivedRecordingInfo(
connectionDescriptor.getTargetId(),
targetId,
filename,
webServerProvider
.get()
.getArchivedDownloadURL(
connectionDescriptor.getTargetId(), filename),
webServerProvider
.get()
.getArchivedReportURL(
connectionDescriptor.getTargetId(), filename),
webServerProvider.get().getArchivedDownloadURL(targetId, filename),
webServerProvider.get().getArchivedReportURL(targetId, filename),
metadata,
getFileSize(filename),
getArchivedTime(filename));
future.complete(archivedRecordingInfo);
notificationFactory
.createBuilder()
.metaCategory(SAVE_NOTIFICATION_CATEGORY)
.metaType(HttpMimeType.JSON)
.message(
Map.of(
"recording",
archivedRecordingInfo,
"target",
connectionDescriptor.getTargetId()))
.createOwnedResourceBuilder(targetId, SAVE_NOTIFICATION_CATEGORY)
.messageEntry("recording", archivedRecordingInfo)
.build()
.send();
} catch (Exception e) {
Expand Down Expand Up @@ -451,10 +437,8 @@ public Future<ArchivedRecordingInfo> deleteRecordingFromPath(
getFileSize(filename),
getArchivedTime(filename));
notificationFactory
.createBuilder()
.metaCategory(DELETE_NOTIFICATION_CATEGORY)
.metaType(HttpMimeType.JSON)
.message(Map.of("recording", archivedRecordingInfo, "target", targetId))
.createOwnedResourceBuilder(targetId, DELETE_NOTIFICATION_CATEGORY)
.messageEntry("recording", archivedRecordingInfo)
.build()
.send();
fs.deleteIfExists(recordingPath);
Expand Down Expand Up @@ -515,10 +499,8 @@ private CompletableFuture<ArchivedRecordingInfo> handleDeleteRecordingRequest(
getFileSize(filename),
getArchivedTime(filename));
notificationFactory
.createBuilder()
.metaCategory(DELETE_NOTIFICATION_CATEGORY)
.metaType(HttpMimeType.JSON)
.message(Map.of("recording", archivedRecordingInfo, "target", targetId))
.createOwnedResourceBuilder(targetId, DELETE_NOTIFICATION_CATEGORY)
.messageEntry("recording", archivedRecordingInfo)
.build()
.send();
checkEmptySubdirectory(parentPath);
Expand Down
30 changes: 7 additions & 23 deletions src/main/java/io/cryostat/recordings/RecordingMetadataManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
import io.cryostat.messaging.notifications.NotificationFactory;
import io.cryostat.net.ConnectionDescriptor;
import io.cryostat.net.TargetConnectionManager;
import io.cryostat.net.web.http.HttpMimeType;
import io.cryostat.platform.PlatformClient;
import io.cryostat.platform.ServiceRef;
import io.cryostat.platform.TargetDiscoveryEvent;
Expand Down Expand Up @@ -514,17 +513,9 @@ public Future<Metadata> setRecordingMetadataFromPath(
StandardOpenOption.TRUNCATE_EXISTING);

notificationFactory
.createBuilder()
.metaCategory(RecordingMetadataManager.NOTIFICATION_CATEGORY)
.metaType(HttpMimeType.JSON)
.message(
Map.of(
"recordingName",
recordingName,
"target",
connectUrl,
"metadata",
metadata))
.createOwnedResourceBuilder(connectUrl, NOTIFICATION_CATEGORY)
.messageEntry("recordingName", recordingName)
.messageEntry("metadata", metadata)
.build()
.send();

Expand Down Expand Up @@ -557,17 +548,10 @@ public Future<Metadata> setRecordingMetadata(

if (issueNotification) {
notificationFactory
.createBuilder()
.metaCategory(RecordingMetadataManager.NOTIFICATION_CATEGORY)
.metaType(HttpMimeType.JSON)
.message(
Map.of(
"recordingName",
recordingName,
"target",
connectionDescriptor.getTargetId(),
"metadata",
metadata))
.createOwnedResourceBuilder(
connectionDescriptor.getTargetId(), NOTIFICATION_CATEGORY)
.messageEntry("recordingName", recordingName)
.messageEntry("metadata", metadata)
.build()
.send();
}
Expand Down
Loading

0 comments on commit 3202849

Please sign in to comment.