• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.caliper.runner;
18 
19 import static java.util.logging.Level.SEVERE;
20 
21 import com.google.caliper.api.ResultProcessor;
22 import com.google.caliper.config.CaliperConfig;
23 import com.google.caliper.config.InvalidConfigurationException;
24 import com.google.caliper.config.ResultProcessorConfig;
25 import com.google.caliper.model.Run;
26 import com.google.caliper.model.Trial;
27 import com.google.caliper.options.CaliperDirectory;
28 import com.google.common.base.Charsets;
29 import com.google.common.base.Optional;
30 import com.google.common.io.Files;
31 import com.google.gson.Gson;
32 import com.google.gson.stream.JsonWriter;
33 
34 import org.joda.time.format.ISODateTimeFormat;
35 
36 import java.io.File;
37 import java.io.FileOutputStream;
38 import java.io.IOException;
39 import java.io.OutputStreamWriter;
40 import java.util.logging.Logger;
41 
42 import javax.inject.Inject;
43 
44 /**
45  * {@link ResultProcessor} that dumps the output data to a file in JSON format. By default, the
46  * output will be dumped to a file called
47  * {@code ~/.caliper/results/[benchmark classname].[timestamp].json}; if it exists and is a file,
48  * the file will be overwritten.  The location can be overridden as either a file or a directory
49  * using either the {@code file} or {@code dir} options respectively.
50  */
51 final class OutputFileDumper implements ResultProcessor {
52   private static final Logger logger = Logger.getLogger(OutputFileDumper.class.getName());
53 
54   private final Run run;
55   private final Gson gson;
56   private final File resultFile;
57   private final File workFile;
58 
59   private Optional<JsonWriter> writer = Optional.absent();
60 
OutputFileDumper(Run run, BenchmarkClass benchmarkClass, Gson gson, CaliperConfig caliperConfig, @CaliperDirectory File caliperDirectory)61   @Inject OutputFileDumper(Run run,
62       BenchmarkClass benchmarkClass,
63       Gson gson,
64       CaliperConfig caliperConfig,
65       @CaliperDirectory File caliperDirectory) throws InvalidConfigurationException {
66     this.run = run;
67     ResultProcessorConfig config = caliperConfig.getResultProcessorConfig(OutputFileDumper.class);
68     if (config.options().containsKey("file")) {
69       this.resultFile = new File(config.options().get("file"));
70       logger.finer("found an output file in the configuration");
71     } else if (config.options().containsKey("dir")) {
72       File dir = new File(config.options().get("dir"));
73       if (dir.isFile()) {
74         throw new InvalidConfigurationException("specified a directory, but it's a file");
75       }
76       this.resultFile = new File(dir, createFileName(benchmarkClass.name()));
77       logger.finer("found an output directory in the configuration");
78     } else {
79       this.resultFile =
80           new File(new File(caliperDirectory, "results"), createFileName(benchmarkClass.name()));
81       logger.fine("found no configuration");
82     }
83     logger.fine(String.format("using %s for results", resultFile));
84     this.gson = gson;
85     this.workFile = new File(resultFile.getPath() + ".tmp");
86   }
87 
createFileName(String benchmarkName)88   private String createFileName(String benchmarkName) {
89     return String.format("%s.%s.json", benchmarkName, createTimestamp());
90   }
91 
createTimestamp()92   private String createTimestamp() {
93     return ISODateTimeFormat.dateTimeNoMillis().print(run.startTime());
94   }
95 
processTrial(Trial trial)96   @Override public void processTrial(Trial trial) {
97     if (!writer.isPresent()) {
98       try {
99         Files.createParentDirs(workFile);
100         JsonWriter writer =
101             new JsonWriter(new OutputStreamWriter(new FileOutputStream(workFile), Charsets.UTF_8));
102         writer.setIndent("  ");  // always pretty print
103         writer.beginArray();
104         this.writer = Optional.of(writer);
105       } catch (IOException e) {
106         logger.log(SEVERE, String.format(
107             "An error occured writing trial %s. Results in %s will be incomplete.", trial.id(),
108             resultFile), e);
109       }
110     }
111     if (writer.isPresent()) {
112       gson.toJson(trial, Trial.class, writer.get());
113     }
114   }
115 
close()116   @Override public void close() throws IOException {
117     if (writer.isPresent()) {
118       writer.get().endArray().close();
119     }
120     if (workFile.exists()) {
121       Files.move(workFile, resultFile);
122     }
123   }
124 }
125