Skip to content

Commit

Permalink
refactor, move datasource URL property into RecordingHelper
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewazores committed Feb 15, 2024
1 parent 73b0b8c commit 4b0bc67
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 59 deletions.
9 changes: 9 additions & 0 deletions src/main/java/io/cryostat/ExceptionMappers.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package io.cryostat;

import java.util.concurrent.CompletionException;

import org.openjdk.jmc.rjmx.ConnectionException;

import io.cryostat.targets.TargetConnectionManager;
Expand All @@ -24,6 +26,7 @@
import io.smallrye.mutiny.TimeoutException;
import jakarta.inject.Inject;
import jakarta.persistence.NoResultException;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.hibernate.exception.ConstraintViolationException;
import org.jboss.logging.Logger;
import org.jboss.resteasy.reactive.RestResponse;
Expand Down Expand Up @@ -100,4 +103,10 @@ public RestResponse<Object> mapEntityExistsException(EntityExistsException ex) {
.entity(ex.getMessage())
.build();
}

@ServerExceptionMapper
public RestResponse<Void> mapCompletionException(CompletionException ex) throws Throwable {
logger.warn(ex);
throw ExceptionUtils.getRootCause(ex);
}
}
78 changes: 68 additions & 10 deletions src/main/java/io/cryostat/recordings/RecordingHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.ByteBuffer;
Expand All @@ -35,6 +36,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand Down Expand Up @@ -64,10 +66,13 @@
import io.cryostat.ws.MessagingServer;
import io.cryostat.ws.Notification;

import io.quarkus.runtime.StartupEvent;
import io.vertx.ext.web.handler.HttpException;
import io.vertx.mutiny.core.eventbus.EventBus;
import io.vertx.mutiny.ext.web.client.WebClient;
import io.vertx.mutiny.ext.web.multipart.MultipartForm;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.ws.rs.BadRequestException;
Expand All @@ -78,6 +83,8 @@
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.validator.routines.UrlValidator;
import org.apache.hc.core5.http.HttpStatus;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.jboss.logging.Logger;
import org.jboss.resteasy.reactive.server.jaxrs.ResponseBuilderImpl;
Expand Down Expand Up @@ -135,6 +142,49 @@ public class RecordingHelper {
@ConfigProperty(name = ConfigProperties.CONNECTIONS_FAILED_TIMEOUT)
Duration connectionFailedTimeout;

@ConfigProperty(name = ConfigProperties.GRAFANA_DATASOURCE_URL)
Optional<String> grafanaDatasourceURLProperty;

CompletableFuture<URL> grafanaDatasourceURL = new CompletableFuture<>();

void onStart(@Observes StartupEvent evt) {
if (grafanaDatasourceURLProperty.isEmpty()) {
grafanaDatasourceURL.completeExceptionally(
new HttpException(
HttpStatus.SC_BAD_GATEWAY,
String.format(
"Configuration property %s is not set",
ConfigProperties.GRAFANA_DATASOURCE_URL)));
return;
}
try {
URL uploadUrl =
new URL(grafanaDatasourceURLProperty.orElseThrow(() -> new HttpException()));
boolean isValidUploadUrl =
new UrlValidator(UrlValidator.ALLOW_LOCAL_URLS).isValid(uploadUrl.toString());
if (!isValidUploadUrl) {
grafanaDatasourceURL.completeExceptionally(
new HttpException(
HttpStatus.SC_BAD_GATEWAY,
String.format(
"Configuration property %s=%s is not acceptable",
ConfigProperties.GRAFANA_DATASOURCE_URL,
grafanaDatasourceURLProperty.get())));
return;
}
grafanaDatasourceURL.complete(new URL(grafanaDatasourceURLProperty.get()));
} catch (MalformedURLException e) {
grafanaDatasourceURL.completeExceptionally(
new HttpException(
HttpStatus.SC_BAD_GATEWAY,
String.format(
"Configuration property %s=%s is not a valid URL",
ConfigProperties.GRAFANA_DATASOURCE_URL,
grafanaDatasourceURLProperty.get())));
return;
}
}

public ActiveRecording startRecording(
Target target,
IConstrainedMap<String> recordingOptions,
Expand Down Expand Up @@ -754,9 +804,7 @@ private Metadata taggingToMetadata(List<Tag> tagSet) {
}

// jfr-datasource handling
// TODO refactor this to take an ActiveRecording argument. uploadUrl should be an injected field
public Response uploadToJFRDatasource(long targetEntityId, long remoteId, URL uploadUrl)
throws Exception {
public Response uploadToJFRDatasource(long targetEntityId, long remoteId) throws Exception {
Target target = Target.getTargetById(targetEntityId);
Objects.requireNonNull(target, "Target from targetId not found");
ActiveRecording recording = target.getRecordingById(remoteId);
Expand All @@ -781,7 +829,13 @@ public Response uploadToJFRDatasource(long targetEntityId, long remoteId, URL up
ResponseBuilder builder = new ResponseBuilderImpl();
var asyncRequest =
webClient
.postAbs(uploadUrl.toURI().resolve("/load").normalize().toString())
.postAbs(
grafanaDatasourceURL
.get()
.toURI()
.resolve("/load")
.normalize()
.toString())
.addQueryParam("overwrite", "true")
.timeout(connectionFailedTimeout.toMillis())
.sendMultipartForm(form);
Expand All @@ -805,8 +859,7 @@ public Response uploadToJFRDatasource(long targetEntityId, long remoteId, URL up
}
}

public Response uploadToJFRDatasource(Pair<String, String> key, URL uploadUrl)
throws Exception {
public Response uploadToJFRDatasource(Pair<String, String> key) throws Exception {
GetObjectRequest getRequest =
GetObjectRequest.builder()
.bucket(archiveBucket)
Expand All @@ -829,7 +882,13 @@ public Response uploadToJFRDatasource(Pair<String, String> key, URL uploadUrl)
ResponseBuilder builder = new ResponseBuilderImpl();
var asyncRequest =
webClient
.postAbs(uploadUrl.toURI().resolve("/load").normalize().toString())
.postAbs(
grafanaDatasourceURL
.get()
.toURI()
.resolve("/load")
.normalize()
.toString())
.addQueryParam("overwrite", "true")
.timeout(connectionFailedTimeout.toMillis())
.sendMultipartForm(form);
Expand All @@ -853,9 +912,8 @@ public Response uploadToJFRDatasource(Pair<String, String> key, URL uploadUrl)
}
}

public Response uploadToJFRDatasource(String jvmId, String filename, URL uploadUrl)
throws Exception {
return uploadToJFRDatasource(Pair.of(jvmId, filename), uploadUrl);
public Response uploadToJFRDatasource(String jvmId, String filename) throws Exception {
return uploadToJFRDatasource(Pair.of(jvmId, filename));
}

Optional<Path> getRecordingCopyPath(
Expand Down
51 changes: 2 additions & 49 deletions src/main/java/io/cryostat/recordings/Recordings.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@
package io.cryostat.recordings;

import java.io.IOException;
import java.net.MalformedURLException;
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;
Expand Down Expand Up @@ -87,8 +85,6 @@
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.validator.routines.UrlValidator;
import org.apache.hc.core5.http.HttpStatus;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.jboss.logging.Logger;
import org.jboss.resteasy.reactive.RestForm;
Expand Down Expand Up @@ -135,9 +131,6 @@ public class Recordings {
@ConfigProperty(name = ConfigProperties.AWS_BUCKET_NAME_ARCHIVES)
String archiveBucket;

@ConfigProperty(name = ConfigProperties.GRAFANA_DATASOURCE_URL)
Optional<String> grafanaDatasourceURL;

@ConfigProperty(name = ConfigProperties.STORAGE_EXT_URL)
Optional<String> externalStorageUrl;

Expand Down Expand Up @@ -828,29 +821,7 @@ public Response uploadActiveToGrafanaV1(
@RolesAllowed("write")
public Response uploadActiveToGrafana(@RestPath long targetId, @RestPath long remoteId)
throws Exception {
try {
URL uploadUrl =
new URL(
grafanaDatasourceURL.orElseThrow(
() ->
new HttpException(
HttpStatus.SC_BAD_GATEWAY,
"GRAFANA_DATASOURCE_URL environment variable"
+ " does not exist")));
boolean isValidUploadUrl =
new UrlValidator(UrlValidator.ALLOW_LOCAL_URLS).isValid(uploadUrl.toString());
if (!isValidUploadUrl) {
throw new HttpException(
HttpStatus.SC_BAD_GATEWAY,
String.format(
"$%s=%s is an invalid datasource URL",
ConfigProperties.GRAFANA_DATASOURCE_URL, uploadUrl.toString()));
}

return recordingHelper.uploadToJFRDatasource(targetId, remoteId, uploadUrl);
} catch (MalformedURLException e) {
throw new HttpException(HttpStatus.SC_BAD_GATEWAY, e);
}
return recordingHelper.uploadToJFRDatasource(targetId, remoteId);
}

@POST
Expand All @@ -873,24 +844,6 @@ public Response uploadArchivedToGrafanaBeta(@RestPath String jvmId, @RestPath St
@Path("/api/v3/grafana/{encodedKey}")
@RolesAllowed("write")
public Response uploadArchivedToGrafana(@RestPath String encodedKey) throws Exception {
URL uploadUrl =
new URL(
grafanaDatasourceURL.orElseThrow(
() ->
new HttpException(
HttpStatus.SC_BAD_GATEWAY,
"GRAFANA_DATASOURCE_URL environment variable"
+ " does not exist")));
boolean isValidUploadUrl =
new UrlValidator(UrlValidator.ALLOW_LOCAL_URLS).isValid(uploadUrl.toString());
if (!isValidUploadUrl) {
throw new HttpException(
HttpStatus.SC_BAD_GATEWAY,
String.format(
"$%s=%s is an invalid datasource URL",
ConfigProperties.GRAFANA_DATASOURCE_URL, uploadUrl.toString()));
}

var key = recordingHelper.decodedKey(encodedKey);
var found =
recordingHelper.listArchivedRecordingObjects().stream()
Expand All @@ -902,7 +855,7 @@ public Response uploadArchivedToGrafana(@RestPath String encodedKey) throws Exce
if (!found) {
throw new NotFoundException();
}
return recordingHelper.uploadToJFRDatasource(key, uploadUrl);
return recordingHelper.uploadToJFRDatasource(key);
}

@GET
Expand Down

0 comments on commit 4b0bc67

Please sign in to comment.