From c0e8becd8b177590e3d1c61657b3b70fc59be92e Mon Sep 17 00:00:00 2001
From: Nils Christian Ehmke <nie@informatik.uni-kiel.de>
Date: Tue, 16 Dec 2014 13:14:20 +0100
Subject: [PATCH] Failed traces can now be filtered

---
 .../FailedTracesSubViewController.java        | 36 +++++++++++++
 ...lureContainingTracesSubViewController.java | 36 +++++++++++++
 .../gui/controller/MainViewController.java    | 12 ++++-
 .../controller/TracesSubViewController.java   |  5 +-
 src/main/java/kieker/gui/model/DataModel.java | 16 +++++-
 .../java/kieker/gui/model/MainViewModel.java  |  2 +-
 .../model/domain/AbstractExecutionEntry.java  | 14 +++++
 .../importer/ImportAnalysisConfiguration.java | 51 +++++++++++++------
 .../stages/FailureContainingTraceFilter.java  | 22 ++++++++
 src/main/java/kieker/gui/view/MainView.java   | 39 ++++++++++++--
 .../java/kieker/gui/view/TracesSubView.java   | 23 +++++++--
 11 files changed, 224 insertions(+), 32 deletions(-)
 create mode 100644 src/main/java/kieker/gui/controller/FailedTracesSubViewController.java
 create mode 100644 src/main/java/kieker/gui/controller/FailureContainingTracesSubViewController.java
 create mode 100644 src/main/java/kieker/gui/model/importer/stages/FailureContainingTraceFilter.java

diff --git a/src/main/java/kieker/gui/controller/FailedTracesSubViewController.java b/src/main/java/kieker/gui/controller/FailedTracesSubViewController.java
new file mode 100644
index 00000000..cbef6bc2
--- /dev/null
+++ b/src/main/java/kieker/gui/controller/FailedTracesSubViewController.java
@@ -0,0 +1,36 @@
+package kieker.gui.controller;
+
+import kieker.gui.model.DataModel;
+import kieker.gui.model.PropertiesModel;
+import kieker.gui.model.TracesSubViewModel;
+import kieker.gui.model.domain.ExecutionEntry;
+import kieker.gui.view.TracesSubView;
+
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+
+public class FailedTracesSubViewController implements SelectionListener {
+
+	private final TracesSubViewModel tracesSubViewModel;
+	private final TracesSubView view;
+
+	public FailedTracesSubViewController(final DataModel model, final PropertiesModel propertiesModel) {
+		this.tracesSubViewModel = new TracesSubViewModel();
+		this.view = new TracesSubView(TracesSubView.Type.SHOW_JUST_FAILED_TRACES, model, this.tracesSubViewModel, propertiesModel, this);
+	}
+
+	public TracesSubView getView() {
+		return this.view;
+	}
+
+	@Override
+	public void widgetSelected(final SelectionEvent e) {
+		if (e.item.getData() instanceof ExecutionEntry) {
+			this.tracesSubViewModel.setCurrentActiveTrace((ExecutionEntry) e.item.getData());
+		}
+	}
+
+	@Override
+	public void widgetDefaultSelected(final SelectionEvent e) {}
+
+}
diff --git a/src/main/java/kieker/gui/controller/FailureContainingTracesSubViewController.java b/src/main/java/kieker/gui/controller/FailureContainingTracesSubViewController.java
new file mode 100644
index 00000000..934e80b5
--- /dev/null
+++ b/src/main/java/kieker/gui/controller/FailureContainingTracesSubViewController.java
@@ -0,0 +1,36 @@
+package kieker.gui.controller;
+
+import kieker.gui.model.DataModel;
+import kieker.gui.model.PropertiesModel;
+import kieker.gui.model.TracesSubViewModel;
+import kieker.gui.model.domain.ExecutionEntry;
+import kieker.gui.view.TracesSubView;
+
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+
+public class FailureContainingTracesSubViewController implements SelectionListener {
+
+	private final TracesSubViewModel tracesSubViewModel;
+	private final TracesSubView view;
+
+	public FailureContainingTracesSubViewController(final DataModel model, final PropertiesModel propertiesModel) {
+		this.tracesSubViewModel = new TracesSubViewModel();
+		this.view = new TracesSubView(TracesSubView.Type.SHOW_JUST_FAILURE_CONTAINING_TRACES, model, this.tracesSubViewModel, propertiesModel, this);
+	}
+
+	public TracesSubView getView() {
+		return this.view;
+	}
+
+	@Override
+	public void widgetSelected(final SelectionEvent e) {
+		if (e.item.getData() instanceof ExecutionEntry) {
+			this.tracesSubViewModel.setCurrentActiveTrace((ExecutionEntry) e.item.getData());
+		}
+	}
+
+	@Override
+	public void widgetDefaultSelected(final SelectionEvent e) {}
+
+}
diff --git a/src/main/java/kieker/gui/controller/MainViewController.java b/src/main/java/kieker/gui/controller/MainViewController.java
index 2ce82ddc..f64137eb 100644
--- a/src/main/java/kieker/gui/controller/MainViewController.java
+++ b/src/main/java/kieker/gui/controller/MainViewController.java
@@ -27,12 +27,16 @@ public class MainViewController implements SelectionListener {
 		final RecordsSubViewController subView1Controller = new RecordsSubViewController(this.dataModel);
 		final TracesSubViewController subView2Controller = new TracesSubViewController(this.dataModel, this.propertiesModel);
 		final AggregatedTracesSubViewController subView3Controller = new AggregatedTracesSubViewController(this.dataModel, this.propertiesModel);
+		final FailedTracesSubViewController subView4Controller = new FailedTracesSubViewController(this.dataModel, this.propertiesModel);
+		final FailureContainingTracesSubViewController subView5Controller = new FailureContainingTracesSubViewController(this.dataModel, this.propertiesModel);
 
 		final RecordsSubView subView1 = subView1Controller.getView();
 		final TracesSubView subView2 = subView2Controller.getView();
 		final AggregatedTracesSubView subView3 = subView3Controller.getView();
+		final TracesSubView subView4 = subView4Controller.getView();
+		final TracesSubView subView5 = subView5Controller.getView();
 
-		this.view = new MainView(this.dataModel, this.mainViewModel, this, subView1, subView2, subView3);
+		this.view = new MainView(this.dataModel, this.mainViewModel, this, subView1, subView2, subView4, subView3, subView5);
 	}
 
 	public void showView() {
@@ -53,6 +57,12 @@ public class MainViewController implements SelectionListener {
 		if (e.item == this.view.getTrtmAggregatedTraces()) {
 			this.mainViewModel.setCurrentActiveSubView(SubView.AGGREGATED_TRACES_SUB_VIEW);
 		}
+		if (e.item == this.view.getTrtmJustFailedTraces()) {
+			this.mainViewModel.setCurrentActiveSubView(SubView.FAILED_TRACES_SUB_VIEW);
+		}
+		if (e.item == this.view.getTrtmJustTracesContaining()) {
+			this.mainViewModel.setCurrentActiveSubView(SubView.FAILURE_CONTAINING_TRACES_SUB_VIEW);
+		}
 
 		if (e.widget == this.view.getMntmOpenMonitoringLog()) {
 			final String selectedDirectory = this.view.getDialog().open();
diff --git a/src/main/java/kieker/gui/controller/TracesSubViewController.java b/src/main/java/kieker/gui/controller/TracesSubViewController.java
index 0c4134d6..8a860321 100644
--- a/src/main/java/kieker/gui/controller/TracesSubViewController.java
+++ b/src/main/java/kieker/gui/controller/TracesSubViewController.java
@@ -12,14 +12,11 @@ import org.eclipse.swt.events.SelectionListener;
 public class TracesSubViewController implements SelectionListener {
 
 	private final TracesSubViewModel tracesSubViewModel;
-	private final DataModel model;
 	private final TracesSubView view;
 
 	public TracesSubViewController(final DataModel model, final PropertiesModel propertiesModel) {
-		this.model = model;
-
 		this.tracesSubViewModel = new TracesSubViewModel();
-		this.view = new TracesSubView(this.model, this.tracesSubViewModel, propertiesModel, this);
+		this.view = new TracesSubView(TracesSubView.Type.SHOW_ALL_TRACES, model, this.tracesSubViewModel, propertiesModel, this);
 	}
 
 	public TracesSubView getView() {
diff --git a/src/main/java/kieker/gui/model/DataModel.java b/src/main/java/kieker/gui/model/DataModel.java
index 0c87a696..1569c7c9 100644
--- a/src/main/java/kieker/gui/model/DataModel.java
+++ b/src/main/java/kieker/gui/model/DataModel.java
@@ -23,8 +23,10 @@ public final class DataModel extends Observable {
 
 	private List<RecordEntry> records = Collections.emptyList();
 	private List<ExecutionEntry> traces = Collections.emptyList();
-	private List<AggregatedExecutionEntry> aggregatedTraces;
-	private String shortTimeUnit;
+	private List<ExecutionEntry> failureContainingTraces = Collections.emptyList();
+	private List<ExecutionEntry> failedTraces = Collections.emptyList();
+	private List<AggregatedExecutionEntry> aggregatedTraces = Collections.emptyList();
+	private String shortTimeUnit = "";
 
 	public DataModel() {}
 
@@ -39,6 +41,8 @@ public final class DataModel extends Observable {
 		// Store the results from the analysis
 		this.records = analysisConfiguration.getRecordsList();
 		this.traces = analysisConfiguration.getTracesList();
+		this.failedTraces = analysisConfiguration.getFailedTracesList();
+		this.failureContainingTraces = analysisConfiguration.getFailureContainingTracesList();
 		this.aggregatedTraces = analysisConfiguration.getAggregatedTraces();
 
 		final List<KiekerMetadataRecord> metadataRecords = analysisConfiguration.getMetadataRecords();
@@ -94,6 +98,14 @@ public final class DataModel extends Observable {
 		return new ArrayList<>(this.traces);
 	}
 
+	public List<ExecutionEntry> getFailedTracesCopy() {
+		return new ArrayList<>(this.failedTraces);
+	}
+
+	public List<ExecutionEntry> getFailureContainingTracesCopy() {
+		return new ArrayList<>(this.failureContainingTraces);
+	}
+
 	public List<AggregatedExecutionEntry> getAggregatedTracesCopy() {
 		return new ArrayList<>(this.aggregatedTraces);
 	}
diff --git a/src/main/java/kieker/gui/model/MainViewModel.java b/src/main/java/kieker/gui/model/MainViewModel.java
index 372364c8..8f80b61f 100644
--- a/src/main/java/kieker/gui/model/MainViewModel.java
+++ b/src/main/java/kieker/gui/model/MainViewModel.java
@@ -18,7 +18,7 @@ public final class MainViewModel extends Observable {
 	}
 
 	public enum SubView {
-		RECORDS_SUB_VIEW, TRACES_SUB_VIEW, AGGREGATED_TRACES_SUB_VIEW, NONE
+		RECORDS_SUB_VIEW, TRACES_SUB_VIEW, FAILED_TRACES_SUB_VIEW, AGGREGATED_TRACES_SUB_VIEW, NONE, FAILURE_CONTAINING_TRACES_SUB_VIEW
 	}
 
 }
diff --git a/src/main/java/kieker/gui/model/domain/AbstractExecutionEntry.java b/src/main/java/kieker/gui/model/domain/AbstractExecutionEntry.java
index 28089c44..00c5ac4f 100644
--- a/src/main/java/kieker/gui/model/domain/AbstractExecutionEntry.java
+++ b/src/main/java/kieker/gui/model/domain/AbstractExecutionEntry.java
@@ -44,6 +44,20 @@ public abstract class AbstractExecutionEntry<T extends AbstractExecutionEntry<T>
 		return (this.failedCause != null);
 	}
 
+	public boolean containsFailure() {
+		if (this.isFailed()) {
+			return true;
+		}
+
+		for (final T child : this.children) {
+			if (child.containsFailure()) {
+				return true;
+			}
+		}
+
+		return false;
+	}
+
 	public String getFailedCause() {
 		return this.failedCause;
 	}
diff --git a/src/main/java/kieker/gui/model/importer/ImportAnalysisConfiguration.java b/src/main/java/kieker/gui/model/importer/ImportAnalysisConfiguration.java
index d68162cd..6868d94b 100644
--- a/src/main/java/kieker/gui/model/importer/ImportAnalysisConfiguration.java
+++ b/src/main/java/kieker/gui/model/importer/ImportAnalysisConfiguration.java
@@ -26,7 +26,8 @@ import kieker.common.record.misc.KiekerMetadataRecord;
 import kieker.gui.model.domain.AggregatedExecutionEntry;
 import kieker.gui.model.domain.ExecutionEntry;
 import kieker.gui.model.domain.RecordEntry;
-import kieker.gui.model.importer.stages.Cloner;
+import kieker.gui.model.importer.stages.FailedTraceFilter;
+import kieker.gui.model.importer.stages.FailureContainingTraceFilter;
 import kieker.gui.model.importer.stages.RecordSimplificator;
 import kieker.gui.model.importer.stages.TraceAggregator;
 import kieker.gui.model.importer.stages.TraceReconstructor;
@@ -37,6 +38,8 @@ import teetime.framework.pipe.PipeFactoryRegistry.ThreadCommunication;
 import teetime.stage.CollectorSink;
 import teetime.stage.InitialElementProducer;
 import teetime.stage.MultipleInstanceOfFilter;
+import teetime.stage.basic.distributor.CopyByReferenceStrategy;
+import teetime.stage.basic.distributor.Distributor;
 import teetime.stage.className.ClassNameRegistryRepository;
 import teetime.stage.io.filesystem.Dir2RecordsFilter;
 
@@ -47,42 +50,52 @@ import teetime.stage.io.filesystem.Dir2RecordsFilter;
  */
 public final class ImportAnalysisConfiguration extends AnalysisConfiguration {
 
-	private final List<RecordEntry> recordsList = new Vector<>(100000);
-	private final List<ExecutionEntry> tracesList = new Vector<>(100000);
-	private final List<AggregatedExecutionEntry> aggregatedTraces = new Vector<>(100000);
-	private final List<KiekerMetadataRecord> metadataRecords = new Vector<>(100000);
+	private final List<RecordEntry> recordsList = new Vector<>(1000);
+	private final List<ExecutionEntry> failedTracesList = new Vector<>(1000);
+	private final List<ExecutionEntry> failureContainingTracesList = new Vector<>(1000);
+	private final List<ExecutionEntry> tracesList = new Vector<>(1000);
+	private final List<AggregatedExecutionEntry> aggregatedTraces = new Vector<>(1000);
+	private final List<KiekerMetadataRecord> metadataRecords = new Vector<>(1000);
 
 	public ImportAnalysisConfiguration(final File importDirectory) {
 		// Create the stages
 		final InitialElementProducer<File> producer = new InitialElementProducer<>(importDirectory);
 		final Dir2RecordsFilter reader = new Dir2RecordsFilter(new ClassNameRegistryRepository());
-
 		final MultipleInstanceOfFilter<IMonitoringRecord> typeFilter = new MultipleInstanceOfFilter<>();
-
-		final Cloner<IFlowRecord> fstDistributor = new Cloner<>();
+		final Distributor<IFlowRecord> fstDistributor = new Distributor<>();
 		final RecordSimplificator recordSimplificator = new RecordSimplificator();
 		final CollectorSink<RecordEntry> recordCollector = new CollectorSink<>(this.recordsList);
 		final TraceReconstructor traceReconstructor = new TraceReconstructor();
-		final Cloner<ExecutionEntry> sndDistributor = new Cloner<>();
+		final Distributor<ExecutionEntry> sndDistributor = new Distributor<>();
 		final CollectorSink<ExecutionEntry> traceCollector = new CollectorSink<>(this.tracesList);
+		final FailedTraceFilter failedTraceFilter = new FailedTraceFilter();
+		final CollectorSink<ExecutionEntry> failedTraceCollector = new CollectorSink<>(this.failedTracesList);
+		final FailureContainingTraceFilter failureContainingTraceFilter = new FailureContainingTraceFilter();
+		final CollectorSink<ExecutionEntry> failureContainingTraceCollector = new CollectorSink<>(this.failureContainingTracesList);
 		final TraceAggregator traceAggregator = new TraceAggregator();
 		final CollectorSink<AggregatedExecutionEntry> aggregatedTraceCollector = new CollectorSink<>(this.aggregatedTraces);
 		final CollectorSink<KiekerMetadataRecord> metadataCollector = new CollectorSink<>(this.metadataRecords);
 
+		// Configure the stages
+		fstDistributor.setStrategy(new CopyByReferenceStrategy<IFlowRecord>());
+		sndDistributor.setStrategy(new CopyByReferenceStrategy<ExecutionEntry>());
+
 		// Connect the stages
 		final IPipeFactory pipeFactory = AnalysisConfiguration.PIPE_FACTORY_REGISTRY.getPipeFactory(ThreadCommunication.INTRA, PipeOrdering.ARBITRARY, false);
 		pipeFactory.create(producer.getOutputPort(), reader.getInputPort());
 		pipeFactory.create(reader.getOutputPort(), typeFilter.getInputPort());
-
 		pipeFactory.create(typeFilter.getOutputPortForType(IFlowRecord.class), fstDistributor.getInputPort());
-		pipeFactory.create(fstDistributor.getFirstOutputPort(), recordSimplificator.getInputPort());
+		pipeFactory.create(fstDistributor.getNewOutputPort(), recordSimplificator.getInputPort());
 		pipeFactory.create(recordSimplificator.getOutputPort(), recordCollector.getInputPort());
-		pipeFactory.create(fstDistributor.getSecondOutputPort(), traceReconstructor.getInputPort());
+		pipeFactory.create(fstDistributor.getNewOutputPort(), traceReconstructor.getInputPort());
 		pipeFactory.create(traceReconstructor.getOutputPort(), sndDistributor.getInputPort());
-		pipeFactory.create(sndDistributor.getFirstOutputPort(), traceCollector.getInputPort());
-		pipeFactory.create(sndDistributor.getSecondOutputPort(), traceAggregator.getInputPort());
+		pipeFactory.create(sndDistributor.getNewOutputPort(), traceAggregator.getInputPort());
+		pipeFactory.create(sndDistributor.getNewOutputPort(), traceCollector.getInputPort());
+		pipeFactory.create(sndDistributor.getNewOutputPort(), failedTraceFilter.getInputPort());
+		pipeFactory.create(failedTraceFilter.getOutputPort(), failedTraceCollector.getInputPort());
+		pipeFactory.create(sndDistributor.getNewOutputPort(), failureContainingTraceFilter.getInputPort());
+		pipeFactory.create(failureContainingTraceFilter.getOutputPort(), failureContainingTraceCollector.getInputPort());
 		pipeFactory.create(traceAggregator.getOutputPort(), aggregatedTraceCollector.getInputPort());
-
 		pipeFactory.create(typeFilter.getOutputPortForType(KiekerMetadataRecord.class), metadataCollector.getInputPort());
 
 		// Make sure that the producer is executed by the analysis
@@ -97,6 +110,14 @@ public final class ImportAnalysisConfiguration extends AnalysisConfiguration {
 		return this.tracesList;
 	}
 
+	public List<ExecutionEntry> getFailedTracesList() {
+		return this.failedTracesList;
+	}
+
+	public List<ExecutionEntry> getFailureContainingTracesList() {
+		return this.failureContainingTracesList;
+	}
+
 	public List<AggregatedExecutionEntry> getAggregatedTraces() {
 		return this.aggregatedTraces;
 	}
diff --git a/src/main/java/kieker/gui/model/importer/stages/FailureContainingTraceFilter.java b/src/main/java/kieker/gui/model/importer/stages/FailureContainingTraceFilter.java
new file mode 100644
index 00000000..cf4138b1
--- /dev/null
+++ b/src/main/java/kieker/gui/model/importer/stages/FailureContainingTraceFilter.java
@@ -0,0 +1,22 @@
+package kieker.gui.model.importer.stages;
+
+import kieker.gui.model.domain.ExecutionEntry;
+import teetime.framework.AbstractConsumerStage;
+import teetime.framework.OutputPort;
+
+public final class FailureContainingTraceFilter extends AbstractConsumerStage<ExecutionEntry> {
+
+	private final OutputPort<ExecutionEntry> outputPort = super.createOutputPort();
+
+	@Override
+	protected void execute(final ExecutionEntry element) {
+		if (element.containsFailure()) {
+			this.outputPort.send(element);
+		}
+	}
+
+	public OutputPort<ExecutionEntry> getOutputPort() {
+		return this.outputPort;
+	}
+
+}
diff --git a/src/main/java/kieker/gui/view/MainView.java b/src/main/java/kieker/gui/view/MainView.java
index 9aab701e..1acbae1a 100644
--- a/src/main/java/kieker/gui/view/MainView.java
+++ b/src/main/java/kieker/gui/view/MainView.java
@@ -26,6 +26,7 @@ public class MainView implements Observer {
 	private final MainViewModel mainViewModel;
 	private final RecordsSubView recordsSubView;
 	private final TracesSubView tracesSubView;
+	private final TracesSubView failedTracesSubView;
 	private final AggregatedTracesSubView aggregatedTracesSubView;
 	private final MainViewController controller;
 
@@ -36,7 +37,6 @@ public class MainView implements Observer {
 	private TreeItem trtmExplorer;
 	private TreeItem trtmRecords;
 	private TreeItem trtmTraces;
-	private TreeItem trtmAggregatedTraces;
 	private MenuItem mntmExit;
 	private MenuItem mntmShortOperationNames;
 	private MenuItem mntmLongOperationNames;
@@ -44,13 +44,20 @@ public class MainView implements Observer {
 	private MenuItem mntmLongComponentNames;
 	private MenuItem mntmOpenMonitoringLog;
 	private DirectoryDialog dialog;
+	private TreeItem trtmAggregatedTraces;
+	private TreeItem trtmJustFailedTraces;
+	private final TracesSubView failureContainingTracesSubView;
+	private TreeItem trtmJustTracesContaining;
 
 	public MainView(final DataModel dataModel, final MainViewModel mainViewModel, final MainViewController controller, final RecordsSubView recordsSubView,
-			final TracesSubView tracesSubView, final AggregatedTracesSubView aggregatedTracesSubView) {
+			final TracesSubView tracesSubView, final TracesSubView failedTracesSubView, final AggregatedTracesSubView aggregatedTracesSubView,
+			final TracesSubView failureContainingTracesSubView) {
 		this.dataModel = dataModel;
 		this.mainViewModel = mainViewModel;
 		this.recordsSubView = recordsSubView;
 		this.tracesSubView = tracesSubView;
+		this.failureContainingTracesSubView = failureContainingTracesSubView;
+		this.failedTracesSubView = failedTracesSubView;
 		this.aggregatedTracesSubView = aggregatedTracesSubView;
 
 		this.controller = controller;
@@ -64,7 +71,7 @@ public class MainView implements Observer {
 		this.shell.open();
 		this.shell.layout();
 
-	
+		this.dataModel.loadMonitoringLogFromFS("example/monitoring log");
 
 		while (!this.shell.isDisposed()) {
 			if (!display.readAndDispatch()) {
@@ -89,10 +96,18 @@ public class MainView implements Observer {
 		return this.trtmTraces;
 	}
 
+	public TreeItem getTrtmJustFailedTraces() {
+		return this.trtmJustFailedTraces;
+	}
+
 	public TreeItem getTrtmAggregatedTraces() {
 		return this.trtmAggregatedTraces;
 	}
 
+	public TreeItem getTrtmJustTracesContaining() {
+		return this.trtmJustTracesContaining;
+	}
+
 	public MenuItem getMntmExit() {
 		return this.mntmExit;
 	}
@@ -146,9 +161,15 @@ public class MainView implements Observer {
 		this.trtmTraces = new TreeItem(this.trtmExplorer, SWT.NONE);
 		this.trtmTraces.setText("Traces");
 
-		this.trtmAggregatedTraces = new TreeItem(this.trtmTraces, SWT.NONE);
-		this.trtmAggregatedTraces.setText("Aggregated Traces");
+		this.trtmJustFailedTraces = new TreeItem(this.trtmTraces, SWT.NONE);
+		this.trtmJustFailedTraces.setText("Just Failed Traces");
+
+		this.trtmJustTracesContaining = new TreeItem(this.trtmTraces, SWT.NONE);
+		this.trtmJustTracesContaining.setText("Just Traces Containing Failures");
 		this.trtmTraces.setExpanded(true);
+
+		this.trtmAggregatedTraces = new TreeItem(this.trtmExplorer, 0);
+		this.trtmAggregatedTraces.setText("Aggregated Traces");
 		this.trtmExplorer.setExpanded(true);
 
 		this.subViewLayout = new StackLayout();
@@ -158,7 +179,9 @@ public class MainView implements Observer {
 
 		this.recordsSubView.createComposite(this.subViewComposite);
 		this.tracesSubView.createComposite(this.subViewComposite);
+		this.failedTracesSubView.createComposite(this.subViewComposite);
 		this.aggregatedTracesSubView.createComposite(this.subViewComposite);
+		this.failureContainingTracesSubView.createComposite(this.subViewComposite);
 
 		final Menu menu = new Menu(this.shell, SWT.BAR);
 		this.shell.setMenuBar(menu);
@@ -240,6 +263,12 @@ public class MainView implements Observer {
 		case AGGREGATED_TRACES_SUB_VIEW:
 			subViewToShow = this.aggregatedTracesSubView.getComposite();
 			break;
+		case FAILED_TRACES_SUB_VIEW:
+			subViewToShow = this.failedTracesSubView.getComposite();
+			break;
+		case FAILURE_CONTAINING_TRACES_SUB_VIEW:
+			subViewToShow = this.failureContainingTracesSubView.getComposite();
+			break;
 		default:
 			subViewToShow = null;
 			break;
diff --git a/src/main/java/kieker/gui/view/TracesSubView.java b/src/main/java/kieker/gui/view/TracesSubView.java
index 830a1a12..e3a198c7 100644
--- a/src/main/java/kieker/gui/view/TracesSubView.java
+++ b/src/main/java/kieker/gui/view/TracesSubView.java
@@ -4,7 +4,6 @@ import java.util.List;
 import java.util.Observable;
 import java.util.Observer;
 
-import kieker.gui.controller.TracesSubViewController;
 import kieker.gui.model.DataModel;
 import kieker.gui.model.PropertiesModel;
 import kieker.gui.model.TracesSubViewModel;
@@ -18,6 +17,7 @@ import kieker.gui.view.util.TreeColumnSortListener;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.events.SelectionListener;
 import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.layout.FillLayout;
 import org.eclipse.swt.layout.GridLayout;
@@ -35,7 +35,7 @@ public class TracesSubView implements Observer {
 
 	private final DataModel model;
 	private final TracesSubViewModel tracesSubViewModel;
-	private final TracesSubViewController controller;
+	private final SelectionListener controller;
 	private Composite composite;
 	private Tree tree;
 	private Composite detailComposite;
@@ -49,8 +49,10 @@ public class TracesSubView implements Observer {
 	private Label lblExecutionContainerDisplay;
 	private Label lblFailed;
 	private final PropertiesModel propertiesModel;
+	private final Type type;
 
-	public TracesSubView(final DataModel model, final TracesSubViewModel tracesSubViewModel, final PropertiesModel propertiesModel, final TracesSubViewController controller) {
+	public TracesSubView(final Type type, final DataModel model, final TracesSubViewModel tracesSubViewModel, final PropertiesModel propertiesModel,
+			final SelectionListener controller) {
 		this.model = model;
 		this.propertiesModel = propertiesModel;
 		this.tracesSubViewModel = tracesSubViewModel;
@@ -59,6 +61,8 @@ public class TracesSubView implements Observer {
 		model.addObserver(this);
 		tracesSubViewModel.addObserver(this);
 		propertiesModel.addObserver(this);
+
+		this.type = type;
 	}
 
 	/**
@@ -204,7 +208,14 @@ public class TracesSubView implements Observer {
 	}
 
 	private void updateTree() {
-		final List<ExecutionEntry> records = this.model.getTracesCopy();
+		final List<ExecutionEntry> records;
+		if (this.type == Type.SHOW_JUST_FAILED_TRACES) {
+			records = this.model.getFailedTracesCopy();
+		} else if (this.type == Type.SHOW_JUST_FAILURE_CONTAINING_TRACES) {
+			records = this.model.getFailureContainingTracesCopy();
+		} else {
+			records = this.model.getTracesCopy();
+		}
 
 		this.tree.setData(records);
 		this.tree.setItemCount(records.size());
@@ -295,4 +306,8 @@ public class TracesSubView implements Observer {
 		}
 	}
 
+	public enum Type {
+		SHOW_ALL_TRACES, SHOW_JUST_FAILED_TRACES, SHOW_JUST_FAILURE_CONTAINING_TRACES
+	}
+
 }
-- 
GitLab