blob: 8e654d569b5afebcda06c85be64f8a346d3be468 [file] [log] [blame]
/*
* Copyright (C) 2011 Google Inc.
*
* 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 com.google.caliper.runner;
import static java.util.logging.Level.SEVERE;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE;
import com.google.caliper.api.ResultProcessor;
import com.google.caliper.config.InvalidConfigurationException;
import com.google.caliper.config.ResultProcessorConfig;
import com.google.caliper.model.Trial;
import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.gson.Gson;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.WebResource;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.UUID;
import java.util.logging.Logger;
import javax.annotation.Nullable;
/**
* {@link ResultProcessor} implementation that uploads the JSON-serialized results to the Caliper
* webapp.
*/
abstract class ResultsUploader implements ResultProcessor {
private static final Logger logger = Logger.getLogger(ResultsUploader.class.getName());
private static final String POST_PATH = "/data/trials";
private static final String RESULTS_PATH_PATTERN = "/runs/%s";
private final PrintWriter stdout;
private final Client client;
private final Gson gson;
private final Optional<UUID> apiKey;
private final Optional<URI> uploadUri;
private Optional<UUID> runId = Optional.absent();
private boolean failure = false;
ResultsUploader(PrintWriter stdout, Gson gson, Client client,
ResultProcessorConfig resultProcessorConfig) throws InvalidConfigurationException {
this.stdout = stdout;
this.client = client;
this.gson = gson;
@Nullable String apiKeyString = resultProcessorConfig.options().get("key");
Optional<UUID> apiKey = Optional.absent();
if (Strings.isNullOrEmpty(apiKeyString)) {
logger.info("No api key specified. Uploading results anonymously.");
} else {
try {
apiKey = Optional.of(UUID.fromString(apiKeyString));
} catch (IllegalArgumentException e) {
throw new InvalidConfigurationException(String.format(
"The specified API key (%s) is not valid. API keys are UUIDs and should look like %s.",
apiKeyString, new UUID(0L, 0L)));
}
}
this.apiKey = apiKey;
@Nullable String urlString = resultProcessorConfig.options().get("url");
if (Strings.isNullOrEmpty(urlString)) {
logger.info("No upload URL was specified. Results will not be uploaded.");
this.uploadUri = Optional.absent();
} else {
try {
this.uploadUri = Optional.of(new URI(urlString).resolve(POST_PATH));
} catch (URISyntaxException e) {
throw new InvalidConfigurationException(urlString + " is an invalid upload url", e);
}
}
}
@Override public final void processTrial(Trial trial) {
if (uploadUri.isPresent()) {
WebResource resource = client.resource(uploadUri.get());
if (apiKey.isPresent()) {
resource = resource.queryParam("key", apiKey.get().toString());
}
boolean threw = true;
try {
// TODO(gak): make the json part happen automagically
resource.type(APPLICATION_JSON_TYPE).post(gson.toJson(ImmutableList.of(trial)));
// only set the run id if a result has been successfully uploaded
runId = Optional.of(trial.run().id());
threw = false;
} catch (ClientHandlerException e) {
logUploadFailure(trial, e);
} catch (UniformInterfaceException e) {
logUploadFailure(trial, e);
logger.fine("Failed upload response: " + e.getResponse().getStatus());
} finally {
failure |= threw;
}
}
}
private static void logUploadFailure(Trial trial, Exception e) {
logger.log(SEVERE, String.format(
"Could not upload trial %s. Consider uploading it manually.", trial.id()), e);
}
@Override public final void close() {
if (uploadUri.isPresent()) {
if (runId.isPresent()) {
stdout.printf("Results have been uploaded. View them at: %s%n",
uploadUri.get().resolve(String.format(RESULTS_PATH_PATTERN, runId.get())));
}
if (failure) {
// TODO(gak): implement some retry
stdout.println("Some trials failed to upload. Consider uploading them manually.");
}
} else {
logger.fine("No upload URL was provided, so results were not uploaded.");
}
}
}