diff --git a/tools/compile-results/src/main/java/moobench/tools/results/ChartAssemblerStage.java b/tools/compile-results/src/main/java/moobench/tools/results/ChartAssemblerStage.java
deleted file mode 100644
index 66a525b46faca72122c887e71ac21ea7a237ce61..0000000000000000000000000000000000000000
--- a/tools/compile-results/src/main/java/moobench/tools/results/ChartAssemblerStage.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * 
- */
-package moobench.tools.results;
-
-import java.util.List;
-import java.util.Map;
-
-import moobench.tools.results.data.Chart;
-import moobench.tools.results.data.Experiment;
-import moobench.tools.results.data.ExperimentLog;
-import moobench.tools.results.data.Measurements;
-import moobench.tools.results.data.ValueTuple;
-import teetime.stage.basic.AbstractTransformation;
-
-/**
- * @author Reiner Jung
- * @since 1.3.0
- *
- */
-public class ChartAssemblerStage extends AbstractTransformation<ExperimentLog, Chart> {
-
-	@Override
-	protected void execute(ExperimentLog element) throws Exception {
-		Chart chart = new Chart(element.getKind());
-		for (Experiment experiment : element.getExperiments()) {
-			long timestamp = Double.valueOf(experiment.getTimestamp()).longValue();
-			ValueTuple tuple = new ValueTuple(timestamp);
-			
-			addHeaderIfMissing(chart.getHeaders(), experiment.getMeasurements());
-			fillInData(chart.getHeaders(), tuple.getValues(), experiment.getMeasurements());
-			
-			chart.getValues().add(tuple);
-		}
-		
-		this.outputPort.send(chart);
-	}
-
-	private void fillInData(List<String> headers, List<Double> values, Map<String, Measurements> measurements) {
-		for (String key : headers) {
-			Measurements value = measurements.get(key);
-			if (value != null) {
-				values.add(value.getMean());
-			} else
-				values.add(Double.NaN);
-		}
-	}
-
-	private void addHeaderIfMissing(List<String> headers, Map<String, Measurements> measurements) {
-		for (String key : measurements.keySet()) {
-			if (!headers.stream().anyMatch(header -> header.equals(key))) {
-				headers.add(key);
-			}
-		}		
-	}
-
-}
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/CompileResultsMain.java b/tools/compile-results/src/main/java/moobench/tools/results/CompileResultsMain.java
index 9dd450d1a594012ba0e5bbdbf81bc3c224f0655f..c87e4082422fa5d4f926ff52718f671ebd244f0e 100644
--- a/tools/compile-results/src/main/java/moobench/tools/results/CompileResultsMain.java
+++ b/tools/compile-results/src/main/java/moobench/tools/results/CompileResultsMain.java
@@ -1,9 +1,23 @@
-/**
- * 
- */
+/***************************************************************************
+ * Copyright (C) 2022 Kieker (https://kieker-monitoring.net)
+
+ *
+ * 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 moobench.tools.results;
 
 import java.io.File;
+import java.nio.file.Path;
 
 import com.beust.jcommander.JCommander;
 
@@ -12,41 +26,47 @@ import kieker.common.exception.ConfigurationException;
 import kieker.tools.common.AbstractService;
 
 /**
- * Read the CSV output of the R script and the existing JSON file and append a
- * record to the JSON file based on the CSV dataset. Further compute a list of
- * the last 50 runs and the last relative values.
+ * Integrate new measurements into the YAML log and create derived outputs: HTML tables and
+ * JSON files for measruement overview and mean execution time graphs, respectively.
  *
  * @author Reiner Jung
+ * @since 1.3.0
  *
  */
 public class CompileResultsMain extends AbstractService<TeetimeConfiguration, Settings> {
 
-	 public static void main(final String[] args) {
-		 final CompileResultsMain main = new CompileResultsMain();
-		 System.exit(main.run("compile-result", "Compile Results", args, new Settings()));
-	 }
-	
-	@Override
-	protected TeetimeConfiguration createTeetimeConfiguration() throws ConfigurationException {
-		return new TeetimeConfiguration(this.parameterConfiguration);
-	}
-
-	@Override
-	protected File getConfigurationFile() {
-		return null;
-	}
-
-	@Override
-	protected boolean checkConfiguration(Configuration configuration, JCommander commander) {
-		return true;
-	}
-
-	@Override
-	protected boolean checkParameters(JCommander commander) throws ConfigurationException {
-		return true;
-	}
-
-	@Override
-	protected void shutdownService() {
-	}
+    public static void main(final String[] args) {
+        final CompileResultsMain main = new CompileResultsMain();
+        System.exit(main.run("compile-result", "Compile Results", args, new Settings()));
+    }
+
+    @Override
+    protected TeetimeConfiguration createTeetimeConfiguration() throws ConfigurationException {
+        return new TeetimeConfiguration(this.parameterConfiguration);
+    }
+
+    @Override
+    protected File getConfigurationFile() {
+        return null;
+    }
+
+    @Override
+    protected boolean checkConfiguration(final Configuration configuration, final JCommander commander) {
+        return true;
+    }
+
+    @Override
+    protected boolean checkParameters(final JCommander commander) throws ConfigurationException {
+        for (final Path inputPath : this.parameterConfiguration.getInputPaths()) {
+            if (!inputPath.toFile().isFile() || !inputPath.toFile().exists()) {
+                this.logger.error("Cannot read input file {}", inputPath.toString());
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    protected void shutdownService() {
+    }
 }
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/FileSink.java b/tools/compile-results/src/main/java/moobench/tools/results/FileSink.java
deleted file mode 100644
index df1b3e00e9398f502396756d1464a2f769e0d94b..0000000000000000000000000000000000000000
--- a/tools/compile-results/src/main/java/moobench/tools/results/FileSink.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package moobench.tools.results;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.nio.file.Files;
-
-import moobench.tools.results.data.OutputFile;
-import teetime.framework.AbstractConsumerStage;
-
-public class FileSink extends AbstractConsumerStage<OutputFile> {
-
-    @Override
-    protected void execute(final OutputFile outputFile) throws Exception {
-        try (final BufferedWriter writer = Files.newBufferedWriter(outputFile.getFilePath())) {
-            writer.write(outputFile.getContent());
-            writer.close();
-        } catch(final IOException e) {
-            this.logger.error("Cannot write file {}", outputFile.getFilePath().toString());
-        }
-    }
-
-}
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/JsonChartSink.java b/tools/compile-results/src/main/java/moobench/tools/results/JsonChartSink.java
new file mode 100644
index 0000000000000000000000000000000000000000..8cda0f4face798853f8a0130b841d4717c6b5ba9
--- /dev/null
+++ b/tools/compile-results/src/main/java/moobench/tools/results/JsonChartSink.java
@@ -0,0 +1,44 @@
+package moobench.tools.results;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import moobench.tools.results.data.Chart;
+import moobench.tools.results.data.ValueTuple;
+import teetime.framework.AbstractConsumerStage;
+
+public class JsonChartSink extends AbstractConsumerStage<Chart> {
+
+    private final Path path;
+
+    public JsonChartSink(final Path path) {
+        this.path = path;
+    }
+
+    @Override
+    protected void execute(final Chart chart) throws Exception {
+        final Path jsonLog = this.path.resolve(chart.getName() + "-partial.json");
+        final ObjectMapper mapper = new ObjectMapper();
+
+        final ObjectNode node = mapper.createObjectNode();
+        final ArrayNode arrayNode = node.putArray("results");
+
+        for(final ValueTuple value : chart.getValues()) {
+            final ObjectNode objectNode = mapper.createObjectNode();
+            for (int i = 0;i < chart.getHeaders().size();i++) {
+                final String name = chart.getHeaders().get(i);
+                final Double number = value.getValues().get(i);
+                objectNode.put(name, number);
+            }
+            objectNode.put("time", value.getTimestamp());
+            arrayNode.add(objectNode);
+        }
+
+        mapper.writeValue(Files.newBufferedWriter(jsonLog), node);
+    }
+
+}
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/JsonLogSink.java b/tools/compile-results/src/main/java/moobench/tools/results/JsonLogSink.java
deleted file mode 100644
index 9dd23fc882e55d1e5a9147d3916f523ba3ed5bd2..0000000000000000000000000000000000000000
--- a/tools/compile-results/src/main/java/moobench/tools/results/JsonLogSink.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package moobench.tools.results;
-
-import java.nio.file.Files;
-import java.nio.file.Path;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-import moobench.tools.results.data.Chart;
-import moobench.tools.results.data.ValueTuple;
-import teetime.framework.AbstractConsumerStage;
-
-public class JsonLogSink extends AbstractConsumerStage<Chart> {
-
-	private Path path;
-
-	public JsonLogSink(Path path) {
-		this.path = path;
-	}
-
-	@Override
-	protected void execute(Chart chart) throws Exception {
-		Path jsonLog = this.path.resolve(chart.getName() + ".json");
-	    ObjectMapper mapper = new ObjectMapper();
-	    
-		ObjectNode node = mapper.createObjectNode();
-		ArrayNode arrayNode = node.putArray("results");
-		
-		for(ValueTuple value : chart.getValues()) {
-			ObjectNode objectNode = mapper.createObjectNode();
-			for (int i = 0;i < chart.getHeaders().size();i++) {
-				String name = chart.getHeaders().get(i);
-				Double number = value.getValues().get(i);
-				objectNode.put(name, number);
-			}
-			objectNode.put("time", value.getTimestamp());
-			arrayNode.add(objectNode);
-		}
-		
-		mapper.writeValue(Files.newBufferedWriter(jsonLog), node);
-	}
-
-}
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/OrderedSet.java b/tools/compile-results/src/main/java/moobench/tools/results/OrderedSet.java
index b2f6bb66fb8bdc84963dbe66b8d215ec4a373e86..72a5a6c09b473e16ab8953b137c169ebdb384268 100644
--- a/tools/compile-results/src/main/java/moobench/tools/results/OrderedSet.java
+++ b/tools/compile-results/src/main/java/moobench/tools/results/OrderedSet.java
@@ -1,3 +1,19 @@
+/***************************************************************************
+ * Copyright (C) 2022 Kieker (https://kieker-monitoring.net)
+
+ *
+ * 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 moobench.tools.results;
 
 import java.util.ArrayList;
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/Settings.java b/tools/compile-results/src/main/java/moobench/tools/results/Settings.java
index 024471b4ed3604f608ee460c5b3b82644891ac56..aad1f0a5d28cfee9d8e454f9711d3d30af785b37 100644
--- a/tools/compile-results/src/main/java/moobench/tools/results/Settings.java
+++ b/tools/compile-results/src/main/java/moobench/tools/results/Settings.java
@@ -1,4 +1,19 @@
+/***************************************************************************
+ * Copyright (C) 2022 Kieker (https://kieker-monitoring.net)
 
+ *
+ * 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 moobench.tools.results;
 
 import java.nio.file.Path;
@@ -8,39 +23,39 @@ import com.beust.jcommander.Parameter;
 import com.beust.jcommander.converters.PathConverter;
 
 public class Settings {
-	
-	@Parameter(names = { "-i", "--input" }, variableArity = true, required = true, converter = PathConverter.class, description = "List of input data sets")
-	private List<Path> inputPaths;
-
-	@Parameter(names= { "-l", "--log" }, required = true, converter = PathConverter.class, description = "YAML log file root path")
-	private Path logPath;
-	
-	@Parameter(names= { "-t", "--table" }, required = true, converter = PathConverter.class, description = "Output HTML table for results")
-	private Path tablePath;
-	
-	@Parameter(names= { "-j", "--json-log" }, required = true, converter = PathConverter.class, description = "Partial JSON log for viewing")
-	private Path jsonLogPath;
-	
-	@Parameter(names= { "-w", "--window" }, required = true, description = "Time Window Size")
-	private Integer window;
-
-	public List<Path> getInputPaths() {
-		return inputPaths;
-	}
-	
-	public Path getLogPath() {
-		return logPath;
-	}
-	
-	public Path getTablePath() {
-		return tablePath;
-	}
-	
-	public Path getJsonLogPath() {
-		return jsonLogPath;
-	}
-	
-	public Integer getWindow() {
-		return window;
-	}
+
+    @Parameter(names = { "-i", "--input" }, variableArity = true, required = true, converter = PathConverter.class, description = "List of input data sets")
+    private List<Path> inputPaths;
+
+    @Parameter(names= { "-l", "--log" }, required = true, converter = PathConverter.class, description = "YAML log file root path")
+    private Path logPath;
+
+    @Parameter(names= { "-t", "--table" }, required = true, converter = PathConverter.class, description = "Output HTML table for results")
+    private Path tablePath;
+
+    @Parameter(names= { "-c", "--chart" }, required = true, converter = PathConverter.class, description = "Partial JSON log for charts")
+    private Path jsonChartPath;
+
+    @Parameter(names= { "-w", "--window" }, required = true, description = "Time Window Size")
+    private Integer window;
+
+    public List<Path> getInputPaths() {
+        return this.inputPaths;
+    }
+
+    public Path getLogPath() {
+        return this.logPath;
+    }
+
+    public Path getTablePath() {
+        return this.tablePath;
+    }
+
+    public Path getJsonChartPath() {
+        return this.jsonChartPath;
+    }
+
+    public Integer getWindow() {
+        return this.window;
+    }
 }
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/TailChartStage.java b/tools/compile-results/src/main/java/moobench/tools/results/TailChartStage.java
deleted file mode 100644
index 5d0e484918c8b7e438fe332a210c3c2ae89e3e7f..0000000000000000000000000000000000000000
--- a/tools/compile-results/src/main/java/moobench/tools/results/TailChartStage.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * 
- */
-package moobench.tools.results;
-
-import moobench.tools.results.data.Chart;
-import teetime.stage.basic.AbstractFilter;
-
-/**
- * @author reiner
- *
- */
-public class TailChartStage extends AbstractFilter<Chart> {
-
-	private Integer window;
-
-	public TailChartStage(Integer window) {
-		this.window = window;
-	}
-
-	@Override
-	protected void execute(Chart chart) throws Exception {
-		if (window != null) {
-			int size = chart.getValues().size();
-			if (size > window) {
-				Chart newChart = new Chart(chart.getName());
-				newChart.getHeaders().addAll(chart.getHeaders());
-				for (int i = size - window; i < size;i++) {
-					newChart.getValues().add(chart.getValues().get(i));
-				}
-				this.outputPort.send(newChart);
-			} else {
-				this.outputPort.send(chart);
-			}
-		} else {
-			this.outputPort.send(chart);
-		}
-	}
-
-}
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/TeetimeConfiguration.java b/tools/compile-results/src/main/java/moobench/tools/results/TeetimeConfiguration.java
index 90b56acf33b3bfe64942f24efe9288786e093187..5296ea78005eb2810503b3b67f27dbb262e441d1 100644
--- a/tools/compile-results/src/main/java/moobench/tools/results/TeetimeConfiguration.java
+++ b/tools/compile-results/src/main/java/moobench/tools/results/TeetimeConfiguration.java
@@ -1,3 +1,19 @@
+/***************************************************************************
+ * Copyright (C) 2022 Kieker (https://kieker-monitoring.net)
+
+ *
+ * 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 moobench.tools.results;
 
 import java.io.File;
@@ -7,6 +23,15 @@ import java.util.ArrayList;
 import java.util.List;
 
 import moobench.tools.results.data.ExperimentLog;
+import moobench.tools.results.stages.ChartAssemblerStage;
+import moobench.tools.results.stages.ComputeTableStage;
+import moobench.tools.results.stages.ElementProducer;
+import moobench.tools.results.stages.FileSink;
+import moobench.tools.results.stages.GenerateHtmlTableStage;
+import moobench.tools.results.stages.LogAppenderStage;
+import moobench.tools.results.stages.TailChartStage;
+import moobench.tools.results.stages.YamlLogSink;
+import moobench.tools.results.stages.YamlReaderStage;
 import teetime.framework.Configuration;
 import teetime.stage.basic.distributor.Distributor;
 import teetime.stage.basic.distributor.strategy.CopyByReferenceStrategy;
@@ -27,7 +52,8 @@ public class TeetimeConfiguration extends Configuration {
 
         final ChartAssemblerStage chartAssemblerStage = new ChartAssemblerStage();
         final TailChartStage tailChartStage = new TailChartStage(settings.getWindow());
-        final JsonLogSink jsonLogSink = new JsonLogSink(settings.getJsonLogPath());
+        final JsonChartSink jsonLogSink = new JsonChartSink(settings.getJsonChartPath());
+
         final ComputeTableStage computeTableStage = new ComputeTableStage();
         final GenerateHtmlTableStage generateHtmlTableStage = new GenerateHtmlTableStage(settings.getTablePath());
         final FileSink fileSink = new FileSink();
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/YamlLogSink.java b/tools/compile-results/src/main/java/moobench/tools/results/YamlLogSink.java
deleted file mode 100644
index de3d9186bb32e0c7b2fa4461a0d03519b4bbf029..0000000000000000000000000000000000000000
--- a/tools/compile-results/src/main/java/moobench/tools/results/YamlLogSink.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package moobench.tools.results;
-
-import java.io.FileWriter;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.yaml.snakeyaml.DumperOptions;
-import org.yaml.snakeyaml.Yaml;
-import org.yaml.snakeyaml.nodes.Node;
-import org.yaml.snakeyaml.nodes.Tag;
-import org.yaml.snakeyaml.representer.Represent;
-import org.yaml.snakeyaml.representer.Representer;
-
-import moobench.tools.results.data.ExperimentLog;
-import moobench.tools.results.data.Measurements;
-import teetime.framework.AbstractConsumerStage;
-
-public class YamlLogSink extends AbstractConsumerStage<ExperimentLog> {
-
-	Path logPath;
-	
-	public YamlLogSink(Path logPath) {
-		this.logPath = logPath;
-	}
-	
-	@Override
-	protected void execute(ExperimentLog log) throws Exception {
-		Path logPath = this.logPath.resolve(String.format("%s.yaml", log.getKind()));
-
-		Representer representer = new LogRepresenter();
-		DumperOptions options = new DumperOptions();
-		Yaml yaml = new Yaml(representer, options);
-    
-	    FileWriter writer = new FileWriter(logPath.toFile());
-	    yaml.dump(log, writer);        
-	}
-	
-	private class LogRepresenter extends Representer {
-		
-		public LogRepresenter() {
-	        this.representers.put(Measurements.class, new RepresentMeasurements());
-	    }
-		
-		private class RepresentMeasurements implements Represent {
-
-			@Override
-			public Node representData(Object data) {
-				Measurements measurements = (Measurements)data;
-				
-				List<Double> values = new ArrayList<>();
-				values.add(measurements.getMean());
-				values.add(measurements.getStandardDeviation());
-				values.add(measurements.getConvidence());
-				values.add(measurements.getLowerQuartile());
-				values.add(measurements.getMedian());
-				values.add(measurements.getUpperQuartile());
-				values.add(measurements.getMin());
-				values.add(measurements.getMax());
-				
-				return representSequence(new Tag("!!" + Measurements.class.getCanonicalName()), values, defaultFlowStyle);
-			}
-			
-		}
-	}
-
-}
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/data/Experiment.java b/tools/compile-results/src/main/java/moobench/tools/results/data/Experiment.java
index d08c2dc6506a2ac71971663913e0340d556db946..58d88c9b8a9b3d677343d61f74c48178ad0c9b58 100644
--- a/tools/compile-results/src/main/java/moobench/tools/results/data/Experiment.java
+++ b/tools/compile-results/src/main/java/moobench/tools/results/data/Experiment.java
@@ -1,6 +1,19 @@
-/**
- * 
- */
+/***************************************************************************
+ * Copyright (C) 2022 Kieker (https://kieker-monitoring.net)
+
+ *
+ * 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 moobench.tools.results.data;
 
 import java.util.HashMap;
@@ -12,27 +25,27 @@ import java.util.Map;
  */
 public class Experiment {
 
-	double timestamp;
-	Map<String,Measurements> measurements = new HashMap<>();
-	
-	public double getTimestamp() {
-		return timestamp;
-	}
-	
-	public void setTimestamp(double timestamp) {
-		this.timestamp = timestamp;
-	}
-	
-	public Map<String,Measurements> getMeasurements() {
-		return measurements;
-	}
-	public void setMeasurements(Map<String,Measurements> measurements) {
-		this.measurements = measurements;
-	}
-	
-	@Override
-	public String toString() {
-		return String.format("time: %f, measurements: %d\n", timestamp, measurements.size());
-	}
-	
+    double timestamp;
+    Map<String,Measurements> measurements = new HashMap<>();
+
+    public double getTimestamp() {
+        return this.timestamp;
+    }
+
+    public void setTimestamp(final double timestamp) {
+        this.timestamp = timestamp;
+    }
+
+    public Map<String,Measurements> getMeasurements() {
+        return this.measurements;
+    }
+    public void setMeasurements(final Map<String,Measurements> measurements) {
+        this.measurements = measurements;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("time: %f, measurements: %d\n", this.timestamp, this.measurements.size());
+    }
+
 }
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/data/ExperimentLog.java b/tools/compile-results/src/main/java/moobench/tools/results/data/ExperimentLog.java
index e619816cec2a48f300fcaebc6442cab8b8f2a122..f8f3b90cb1b09e1e9aac4d10ae0973203ba6f9eb 100644
--- a/tools/compile-results/src/main/java/moobench/tools/results/data/ExperimentLog.java
+++ b/tools/compile-results/src/main/java/moobench/tools/results/data/ExperimentLog.java
@@ -1,26 +1,42 @@
+/***************************************************************************
+ * Copyright (C) 2022 Kieker (https://kieker-monitoring.net)
+
+ *
+ * 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 moobench.tools.results.data;
 
 import java.util.ArrayList;
 import java.util.List;
 
 public class ExperimentLog {
-	
-	String kind;
-	List<Experiment> experiments = new ArrayList<>();
-	
-	public String getKind() {
-		return kind;
-	}
-	
-	public void setKind(String kind) {
-		this.kind = kind;
-	}
-	
-	public List<Experiment> getExperiments() {
-		return experiments;
-	}
-
-	public void setExperiments(List<Experiment> experiments) {
-		this.experiments = experiments;
-	}
+
+    String kind;
+    List<Experiment> experiments = new ArrayList<>();
+
+    public String getKind() {
+        return this.kind;
+    }
+
+    public void setKind(final String kind) {
+        this.kind = kind;
+    }
+
+    public List<Experiment> getExperiments() {
+        return this.experiments;
+    }
+
+    public void setExperiments(final List<Experiment> experiments) {
+        this.experiments = experiments;
+    }
 }
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/data/Measurements.java b/tools/compile-results/src/main/java/moobench/tools/results/data/Measurements.java
index a14f9bd44de1cdf04198cd0cf3993735822b7ffc..366ae35d85d0c98bb9941d4552265f6d3db8120f 100644
--- a/tools/compile-results/src/main/java/moobench/tools/results/data/Measurements.java
+++ b/tools/compile-results/src/main/java/moobench/tools/results/data/Measurements.java
@@ -1,63 +1,79 @@
+/***************************************************************************
+ * Copyright (C) 2022 Kieker (https://kieker-monitoring.net)
+
+ *
+ * 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 moobench.tools.results.data;
 
 public class Measurements {
-		
-	private Double mean;
-	private Double convidence;
-	private Double standardDeviation;
-	private Double lowerQuartile;
-	private Double median;
-	private Double upperQuartile;
-	private Double max;
-	private Double min;
-
-	public Measurements(Double mean, Double standardDeviation, Double convidence, Double lowerQuartile, Double median, Double upperQuartile, Double min, Double max) {
-		this.mean = mean;
-		this.convidence = convidence;
-		this.standardDeviation = standardDeviation;
-		this.lowerQuartile = lowerQuartile;
-		this.median = median;
-		this.upperQuartile = upperQuartile;
-		this.min = min;
-		this.max = max;
-	}
-	
-	public Double getMean() {
-		return mean;
-	}
-	
-	/**
-	 * Returns the convidence value, to get the convidence interval you need to compute the interval as
-	 * [mean-convidence:mean+convidence]
-	 * 
-	 * @return convidence value
-	 */
-	public Double getConvidence() {
-		return convidence;
-	}
-	
-	public Double getStandardDeviation() {
-		return standardDeviation;
-	}
-	
-	public Double getLowerQuartile() {
-		return lowerQuartile;
-	}
-	
-	public Double getMedian() {
-		return median;
-	}
-	
-	public Double getUpperQuartile() {
-		return upperQuartile;
-	}
-	
-	public Double getMin() {
-		return min;
-	}
-	
-	public Double getMax() {
-		return max;
-	}
+
+    private final Double mean;
+    private final Double convidence;
+    private final Double standardDeviation;
+    private final Double lowerQuartile;
+    private final Double median;
+    private final Double upperQuartile;
+    private final Double max;
+    private final Double min;
+
+    public Measurements(final Double mean, final Double standardDeviation, final Double convidence, final Double lowerQuartile, final Double median, final Double upperQuartile, final Double min, final Double max) {
+        this.mean = mean;
+        this.convidence = convidence;
+        this.standardDeviation = standardDeviation;
+        this.lowerQuartile = lowerQuartile;
+        this.median = median;
+        this.upperQuartile = upperQuartile;
+        this.min = min;
+        this.max = max;
+    }
+
+    public Double getMean() {
+        return this.mean;
+    }
+
+    /**
+     * Returns the convidence value, to get the convidence interval you need to compute the interval as
+     * [mean-convidence:mean+convidence]
+     *
+     * @return convidence value
+     */
+    public Double getConvidence() {
+        return this.convidence;
+    }
+
+    public Double getStandardDeviation() {
+        return this.standardDeviation;
+    }
+
+    public Double getLowerQuartile() {
+        return this.lowerQuartile;
+    }
+
+    public Double getMedian() {
+        return this.median;
+    }
+
+    public Double getUpperQuartile() {
+        return this.upperQuartile;
+    }
+
+    public Double getMin() {
+        return this.min;
+    }
+
+    public Double getMax() {
+        return this.max;
+    }
 
 }
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/data/OutputFile.java b/tools/compile-results/src/main/java/moobench/tools/results/data/OutputFile.java
index b1bdfe117964ac1dc5e10a152b7a7ebb89f26f49..4176bd6f5929f4cc93cf0a19009f653c4122e4fc 100644
--- a/tools/compile-results/src/main/java/moobench/tools/results/data/OutputFile.java
+++ b/tools/compile-results/src/main/java/moobench/tools/results/data/OutputFile.java
@@ -1,7 +1,29 @@
+/***************************************************************************
+ * Copyright (C) 2022 Kieker (https://kieker-monitoring.net)
+
+ *
+ * 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 moobench.tools.results.data;
 
 import java.nio.file.Path;
 
+/**
+ * Pass down file path and content for the file to a data sink.
+ *
+ * @author Reiner Jung
+ * @since 1.3.0
+ */
 public class OutputFile {
 
     Path filePath;
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/data/TableInformation.java b/tools/compile-results/src/main/java/moobench/tools/results/data/TableInformation.java
index 8a73e5d80ee8a7417e24af91ed03d81a32c96c81..e79bf6dab8a7eb5a5cdf268a8f51886d3613e828 100644
--- a/tools/compile-results/src/main/java/moobench/tools/results/data/TableInformation.java
+++ b/tools/compile-results/src/main/java/moobench/tools/results/data/TableInformation.java
@@ -1,3 +1,19 @@
+/***************************************************************************
+ * Copyright (C) 2022 Kieker (https://kieker-monitoring.net)
+
+ *
+ * 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 moobench.tools.results.data;
 
 public class TableInformation {
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/stages/ChartAssemblerStage.java b/tools/compile-results/src/main/java/moobench/tools/results/stages/ChartAssemblerStage.java
new file mode 100644
index 0000000000000000000000000000000000000000..a51709e14afd7b15906740978c7077d00b6fb229
--- /dev/null
+++ b/tools/compile-results/src/main/java/moobench/tools/results/stages/ChartAssemblerStage.java
@@ -0,0 +1,71 @@
+/***************************************************************************
+ * Copyright (C) 2022 Kieker (https://kieker-monitoring.net)
+
+ *
+ * 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 moobench.tools.results.stages;
+
+import java.util.List;
+import java.util.Map;
+
+import moobench.tools.results.data.Chart;
+import moobench.tools.results.data.Experiment;
+import moobench.tools.results.data.ExperimentLog;
+import moobench.tools.results.data.Measurements;
+import moobench.tools.results.data.ValueTuple;
+import teetime.stage.basic.AbstractTransformation;
+
+/**
+ * @author Reiner Jung
+ * @since 1.3.0
+ *
+ */
+public class ChartAssemblerStage extends AbstractTransformation<ExperimentLog, Chart> {
+
+    @Override
+    protected void execute(final ExperimentLog element) throws Exception {
+        final Chart chart = new Chart(element.getKind());
+        for (final Experiment experiment : element.getExperiments()) {
+            final long timestamp = Double.valueOf(experiment.getTimestamp()).longValue();
+            final ValueTuple tuple = new ValueTuple(timestamp);
+
+            this.addHeaderIfMissing(chart.getHeaders(), experiment.getMeasurements());
+            this.fillInData(chart.getHeaders(), tuple.getValues(), experiment.getMeasurements());
+
+            chart.getValues().add(tuple);
+        }
+
+        this.outputPort.send(chart);
+    }
+
+    private void fillInData(final List<String> headers, final List<Double> values, final Map<String, Measurements> measurements) {
+        for (final String key : headers) {
+            final Measurements value = measurements.get(key);
+            if (value != null) {
+                values.add(value.getMean());
+            } else {
+                values.add(Double.NaN);
+            }
+        }
+    }
+
+    private void addHeaderIfMissing(final List<String> headers, final Map<String, Measurements> measurements) {
+        for (final String key : measurements.keySet()) {
+            if (!headers.stream().anyMatch(header -> header.equals(key))) {
+                headers.add(key);
+            }
+        }
+    }
+
+}
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/ComputeTableStage.java b/tools/compile-results/src/main/java/moobench/tools/results/stages/ComputeTableStage.java
similarity index 76%
rename from tools/compile-results/src/main/java/moobench/tools/results/ComputeTableStage.java
rename to tools/compile-results/src/main/java/moobench/tools/results/stages/ComputeTableStage.java
index dd341abdc9eeaed100de5ddf7db9ea981d00c923..cb49ae82d0cf6aa79ce10c7be3ff855a471dafaa 100644
--- a/tools/compile-results/src/main/java/moobench/tools/results/ComputeTableStage.java
+++ b/tools/compile-results/src/main/java/moobench/tools/results/stages/ComputeTableStage.java
@@ -1,7 +1,20 @@
-/**
+/***************************************************************************
+ * Copyright (C) 2022 Kieker (https://kieker-monitoring.net)
+
  *
- */
-package moobench.tools.results;
+ * 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 moobench.tools.results.stages;
 
 import java.util.List;
 import java.util.Map.Entry;
@@ -13,8 +26,8 @@ import moobench.tools.results.data.TableInformation;
 import teetime.stage.basic.AbstractTransformation;
 
 /**
- * @author reiner
- *
+ * @author Reiner Jung
+ * @since 1.3.0
  */
 public class ComputeTableStage extends AbstractTransformation<ExperimentLog, TableInformation> {
 
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/ElementProducer.java b/tools/compile-results/src/main/java/moobench/tools/results/stages/ElementProducer.java
similarity index 93%
rename from tools/compile-results/src/main/java/moobench/tools/results/ElementProducer.java
rename to tools/compile-results/src/main/java/moobench/tools/results/stages/ElementProducer.java
index e27cafb71d0e05e4313ec50874dd2e94aec99c01..be43e385a1924894de99041536758eb6525bf55c 100644
--- a/tools/compile-results/src/main/java/moobench/tools/results/ElementProducer.java
+++ b/tools/compile-results/src/main/java/moobench/tools/results/stages/ElementProducer.java
@@ -1,7 +1,7 @@
 /**
  * 
  */
-package moobench.tools.results;
+package moobench.tools.results.stages;
 
 import java.util.List;
 
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/stages/FileSink.java b/tools/compile-results/src/main/java/moobench/tools/results/stages/FileSink.java
new file mode 100644
index 0000000000000000000000000000000000000000..a472a457278289921872165686ecc1bddba6dc76
--- /dev/null
+++ b/tools/compile-results/src/main/java/moobench/tools/results/stages/FileSink.java
@@ -0,0 +1,38 @@
+/***************************************************************************
+ * Copyright (C) 2022 Kieker (https://kieker-monitoring.net)
+
+ *
+ * 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 moobench.tools.results.stages;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.nio.file.Files;
+
+import moobench.tools.results.data.OutputFile;
+import teetime.framework.AbstractConsumerStage;
+
+public class FileSink extends AbstractConsumerStage<OutputFile> {
+
+    @Override
+    protected void execute(final OutputFile outputFile) throws Exception {
+        try (final BufferedWriter writer = Files.newBufferedWriter(outputFile.getFilePath())) {
+            writer.write(outputFile.getContent());
+            writer.close();
+        } catch(final IOException e) {
+            this.logger.error("Cannot write file {}", outputFile.getFilePath().toString());
+        }
+    }
+
+}
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/GenerateHtmlTableStage.java b/tools/compile-results/src/main/java/moobench/tools/results/stages/GenerateHtmlTableStage.java
similarity index 81%
rename from tools/compile-results/src/main/java/moobench/tools/results/GenerateHtmlTableStage.java
rename to tools/compile-results/src/main/java/moobench/tools/results/stages/GenerateHtmlTableStage.java
index 4780590a2bc3dbf3ec1044e6eb716c5985f241ff..47fa81a559cf2101a80207a8670f930e268b609f 100644
--- a/tools/compile-results/src/main/java/moobench/tools/results/GenerateHtmlTableStage.java
+++ b/tools/compile-results/src/main/java/moobench/tools/results/stages/GenerateHtmlTableStage.java
@@ -1,8 +1,9 @@
-package moobench.tools.results;
+package moobench.tools.results.stages;
 
 import java.nio.file.Path;
 import java.util.Set;
 
+import moobench.tools.results.OrderedSet;
 import moobench.tools.results.data.Measurements;
 import moobench.tools.results.data.OutputFile;
 import moobench.tools.results.data.TableInformation;
@@ -17,13 +18,13 @@ public class GenerateHtmlTableStage extends AbstractTransformation<TableInformat
     }
 
     @Override
-    protected void execute(final TableInformation element) throws Exception {
+    protected void execute(final TableInformation tableInformation) throws Exception {
         String content = "<table>\n" + "  <tr>\n" + "    <th>setup</th>\n" + "    <th>run</th>\n"
                 + "    <th>mean</th>\n" + "    <th>ci</th>\n" + "    <th>sd</th>\n" + "    <th>1.quartile</th>\n"
                 + "    <th>median</th>\n" + "    <th>3.quartile</th>\n" + "    <th>min</th>\n" + "    <th>max</th>\n"
                 + "  </tr>\n";
-        final Set<String> currentKeySet = element.getCurrent().getMeasurements().keySet();
-        final Set<String> previousKeySet = element.getPrevious().getMeasurements().keySet();
+        final Set<String> currentKeySet = tableInformation.getCurrent().getMeasurements().keySet();
+        final Set<String> previousKeySet = tableInformation.getPrevious().getMeasurements().keySet();
         final Set<String> completeKeySet = new OrderedSet<>();
         if (currentKeySet != null) {
             completeKeySet.addAll(currentKeySet);
@@ -33,11 +34,11 @@ public class GenerateHtmlTableStage extends AbstractTransformation<TableInformat
         }
 
         for (final String key : completeKeySet) {
-            content += this.addMode(key, element.getCurrent().getMeasurements().get(key),
-                    element.getPrevious().getMeasurements().get(key));
+            content += this.addMode(key, tableInformation.getCurrent().getMeasurements().get(key),
+                    tableInformation.getPrevious().getMeasurements().get(key));
         }
         content += "</table>\n";
-        this.outputPort.send(new OutputFile(this.tablePath.resolve(element.getName() + ".html"), content));
+        this.outputPort.send(new OutputFile(this.tablePath.resolve(tableInformation.getName() + "-table.html"), content));
     }
 
     private String addMode(final String key, final Measurements current, final Measurements previous) {
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/LogAppenderStage.java b/tools/compile-results/src/main/java/moobench/tools/results/stages/LogAppenderStage.java
similarity index 96%
rename from tools/compile-results/src/main/java/moobench/tools/results/LogAppenderStage.java
rename to tools/compile-results/src/main/java/moobench/tools/results/stages/LogAppenderStage.java
index 128eab4cf5052ab4ca8741e55caeade98ea12722..e1c4e9ea0d512db8362ba8c378d9a55535dd2950 100644
--- a/tools/compile-results/src/main/java/moobench/tools/results/LogAppenderStage.java
+++ b/tools/compile-results/src/main/java/moobench/tools/results/stages/LogAppenderStage.java
@@ -1,7 +1,7 @@
 /**
  * 
  */
-package moobench.tools.results;
+package moobench.tools.results.stages;
 
 import java.util.HashMap;
 import java.util.Map;
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/stages/TailChartStage.java b/tools/compile-results/src/main/java/moobench/tools/results/stages/TailChartStage.java
new file mode 100644
index 0000000000000000000000000000000000000000..f5e4a76d83aaa11edb2f8949037208f2766b5a2a
--- /dev/null
+++ b/tools/compile-results/src/main/java/moobench/tools/results/stages/TailChartStage.java
@@ -0,0 +1,52 @@
+/***************************************************************************
+ * Copyright (C) 2022 Kieker (https://kieker-monitoring.net)
+ *
+ * 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 moobench.tools.results.stages;
+
+import moobench.tools.results.data.Chart;
+import teetime.stage.basic.AbstractFilter;
+
+/**
+ * @author Reiner Jung
+ * @since 1.3.0
+ */
+public class TailChartStage extends AbstractFilter<Chart> {
+
+    private final Integer window;
+
+    public TailChartStage(final Integer window) {
+        this.window = window;
+    }
+
+    @Override
+    protected void execute(final Chart chart) throws Exception {
+        if (this.window != null) {
+            final int size = chart.getValues().size();
+            if (size > this.window) {
+                final Chart newChart = new Chart(chart.getName());
+                newChart.getHeaders().addAll(chart.getHeaders());
+                for (int i = size - this.window; i < size;i++) {
+                    newChart.getValues().add(chart.getValues().get(i));
+                }
+                this.outputPort.send(newChart);
+            } else {
+                this.outputPort.send(chart);
+            }
+        } else {
+            this.outputPort.send(chart);
+        }
+    }
+
+}
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/stages/YamlLogSink.java b/tools/compile-results/src/main/java/moobench/tools/results/stages/YamlLogSink.java
new file mode 100644
index 0000000000000000000000000000000000000000..5088dd9554195794e1b6b39eb95b31944aa19f76
--- /dev/null
+++ b/tools/compile-results/src/main/java/moobench/tools/results/stages/YamlLogSink.java
@@ -0,0 +1,83 @@
+/***************************************************************************
+ * Copyright (C) 2022 Kieker (https://kieker-monitoring.net)
+
+ *
+ * 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 moobench.tools.results.stages;
+
+import java.io.FileWriter;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.yaml.snakeyaml.DumperOptions;
+import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.nodes.Node;
+import org.yaml.snakeyaml.nodes.Tag;
+import org.yaml.snakeyaml.representer.Represent;
+import org.yaml.snakeyaml.representer.Representer;
+
+import moobench.tools.results.data.ExperimentLog;
+import moobench.tools.results.data.Measurements;
+import teetime.framework.AbstractConsumerStage;
+
+public class YamlLogSink extends AbstractConsumerStage<ExperimentLog> {
+
+    Path logPath;
+
+    public YamlLogSink(final Path logPath) {
+        this.logPath = logPath;
+    }
+
+    @Override
+    protected void execute(final ExperimentLog log) throws Exception {
+        final Path logPath = this.logPath.resolve(String.format("%s-log.yaml", log.getKind()));
+
+        final Representer representer = new LogRepresenter();
+        final DumperOptions options = new DumperOptions();
+        final Yaml yaml = new Yaml(representer, options);
+
+        final FileWriter writer = new FileWriter(logPath.toFile());
+        yaml.dump(log, writer);
+    }
+
+    private class LogRepresenter extends Representer {
+
+        public LogRepresenter() {
+            this.representers.put(Measurements.class, new RepresentMeasurements());
+        }
+
+        private class RepresentMeasurements implements Represent {
+
+            @Override
+            public Node representData(final Object data) {
+                final Measurements measurements = (Measurements)data;
+
+                final List<Double> values = new ArrayList<>();
+                values.add(measurements.getMean());
+                values.add(measurements.getStandardDeviation());
+                values.add(measurements.getConvidence());
+                values.add(measurements.getLowerQuartile());
+                values.add(measurements.getMedian());
+                values.add(measurements.getUpperQuartile());
+                values.add(measurements.getMin());
+                values.add(measurements.getMax());
+
+                return LogRepresenter.this.representSequence(new Tag("!!" + Measurements.class.getCanonicalName()), values, LogRepresenter.this.defaultFlowStyle);
+            }
+
+        }
+    }
+
+}
diff --git a/tools/compile-results/src/main/java/moobench/tools/results/YamlReaderStage.java b/tools/compile-results/src/main/java/moobench/tools/results/stages/YamlReaderStage.java
similarity index 94%
rename from tools/compile-results/src/main/java/moobench/tools/results/YamlReaderStage.java
rename to tools/compile-results/src/main/java/moobench/tools/results/stages/YamlReaderStage.java
index 0cbbe6c34793606988c285a3a007b41f4bc56791..43bfabf90bfffc7835d24bfdab27f63cc5f810e0 100644
--- a/tools/compile-results/src/main/java/moobench/tools/results/YamlReaderStage.java
+++ b/tools/compile-results/src/main/java/moobench/tools/results/stages/YamlReaderStage.java
@@ -1,4 +1,4 @@
-package moobench.tools.results;
+package moobench.tools.results.stages;
 
 import java.io.InputStream;
 import java.nio.file.Files;
diff --git a/upload.sh b/upload.sh
index af56104b231526f2aa5a181b523603b80edd75d1..af6b8f9947f130290ce84db73351fedecf47b814 100755
--- a/upload.sh
+++ b/upload.sh
@@ -37,17 +37,17 @@ checkExecutable compile-results "${COMPILE_RESULTS_BIN}"
 KEYSTORE="$1"
 UPDATE_SITE_RUL="$2"
 
-mkdir all
-cd all
+mkdir results
+cd results
 sftp -oNoHostAuthenticationForLocalhost=yes -oStrictHostKeyChecking=no -oUser=repo -F /dev/null -i ${KEYSTORE} ${UPDATE_SITE_URL}/kieker-java.yaml
 sftp -oNoHostAuthenticationForLocalhost=yes -oStrictHostKeyChecking=no -oUser=repo -F /dev/null -i ${KEYSTORE} ${UPDATE_SITE_URL}/kieker-python.yaml
 sftp -oNoHostAuthenticationForLocalhost=yes -oStrictHostKeyChecking=no -oUser=repo -F /dev/null -i ${KEYSTORE} ${UPDATE_SITE_URL}/opentelemetry.yaml
 sftp -oNoHostAuthenticationForLocalhost=yes -oStrictHostKeyChecking=no -oUser=repo -F /dev/null -i ${KEYSTORE} ${UPDATE_SITE_URL}/inspectit.yaml
 cd ..
-"${COMPILE_RESULTS_BIN}" -i *-results.yaml -l all -t all -j all -w 100
-cd all
+"${COMPILE_RESULTS_BIN}" -i *-results.yaml -l results -t results -j results -w 100
+cd results
 echo "put *.yaml" | sftp -oNoHostAuthenticationForLocalhost=yes -oStrictHostKeyChecking=no -oUser=repo  -F /dev/null -i ${KEYSTORE} ${UPDATE_SITE_URL}
 echo "put *.html" | sftp -oNoHostAuthenticationForLocalhost=yes -oStrictHostKeyChecking=no -oUser=repo  -F /dev/null -i ${KEYSTORE} ${UPDATE_SITE_URL}
 echo "put *.json" | sftp -oNoHostAuthenticationForLocalhost=yes -oStrictHostKeyChecking=no -oUser=repo  -F /dev/null -i ${KEYSTORE} ${UPDATE_SITE_URL}
-
+cd ..
 # end