Commit 1612a692 authored by Nils Christian Ehmke's avatar Nils Christian Ehmke

Added JavaDoc and comments

parent 851a88ad
...@@ -13,6 +13,11 @@ import kieker.diagnosis.service.traces.TracesFilter; ...@@ -13,6 +13,11 @@ import kieker.diagnosis.service.traces.TracesFilter;
import kieker.diagnosis.service.traces.TracesService; import kieker.diagnosis.service.traces.TracesService;
import kieker.diagnosis.ui.main.MainController; import kieker.diagnosis.ui.main.MainController;
/**
* The controller of the traces tab.
*
* @author Nils Christian Ehmke
*/
@Singleton @Singleton
class TracesController extends ControllerBase<TracesViewModel> { class TracesController extends ControllerBase<TracesViewModel> {
...@@ -29,18 +34,23 @@ class TracesController extends ControllerBase<TracesViewModel> { ...@@ -29,18 +34,23 @@ class TracesController extends ControllerBase<TracesViewModel> {
getViewModel( ).updatePresentationFilter( new TracesFilter( ) ); getViewModel( ).updatePresentationFilter( new TracesFilter( ) );
} }
/**
* This action is performed when settings or data are changed and the view has to be refreshed. The actual refresh is only performed when
* {@link #performRefresh()} is called. This method prepares only the refresh.
*/
public void performPrepareRefresh( ) { public void performPrepareRefresh( ) {
// Find the trace roots to display // Find the trace roots to display
final TracesService tracesService = getService( TracesService.class ); final TracesService tracesService = getService( TracesService.class );
ivTraceRoots = tracesService.searchTraces( new TracesFilter( ) ); ivTraceRoots = tracesService.searchTraces( new TracesFilter( ) );
ivTotalTraces = tracesService.countTraces( ); ivTotalTraces = tracesService.countTraces( );
// Get the duration suffix
final SettingsService settingsService = getService( SettingsService.class ); final SettingsService settingsService = getService( SettingsService.class );
ivDurationSuffix = settingsService.getCurrentDurationSuffix( ); ivDurationSuffix = settingsService.getCurrentDurationSuffix( );
} }
/** /**
* This action is performed, when a refresh of the view is required * This action is performed, when a refresh of the view is required. The preparation of the refresh is performed in {@link #performPrepareRefresh()}.
*/ */
public void performRefresh( ) { public void performRefresh( ) {
// Reset the filter // Reset the filter
...@@ -56,13 +66,16 @@ class TracesController extends ControllerBase<TracesViewModel> { ...@@ -56,13 +66,16 @@ class TracesController extends ControllerBase<TracesViewModel> {
} }
/** /**
* This action is performed, when the selection of the table changes * This action is performed, when the selection of the table changes.
*/ */
public void performSelectionChange( ) { public void performSelectionChange( ) {
final MethodCall methodCall = getViewModel( ).getSelected( ); final MethodCall methodCall = getViewModel( ).getSelected( );
getViewModel( ).updatePresentationDetails( methodCall ); getViewModel( ).updatePresentationDetails( methodCall );
} }
/**
* This action is performed, when the user wants to perform a search.
*/
public void performSearch( ) { public void performSearch( ) {
try { try {
// Get the filter input from the user // Get the filter input from the user
...@@ -71,7 +84,6 @@ class TracesController extends ControllerBase<TracesViewModel> { ...@@ -71,7 +84,6 @@ class TracesController extends ControllerBase<TracesViewModel> {
// Find the trace roots to display // Find the trace roots to display
final TracesService tracesService = getService( TracesService.class ); final TracesService tracesService = getService( TracesService.class );
final List<MethodCall> traceRoots = tracesService.searchTraces( filter ); final List<MethodCall> traceRoots = tracesService.searchTraces( filter );
final int totalTraces = tracesService.countTraces( ); final int totalTraces = tracesService.countTraces( );
// Update the view // Update the view
...@@ -83,6 +95,14 @@ class TracesController extends ControllerBase<TracesViewModel> { ...@@ -83,6 +95,14 @@ class TracesController extends ControllerBase<TracesViewModel> {
} }
/**
* This action is performed, when someone requested a jump into the traces tab. The real action is determined based on the type of the parameter. If the
* parameter is a {@link TracesFilter}, the filter is simply applied. If the parameter is a {@link MethodCall}, the trace for the method call is shown and
* the view tries to navigate directly to the method call. If the method call is not visible, the trace is still shown.
*
* @param aParameter
* The parameter.
*/
public void performSetParameter( final Object aParameter ) { public void performSetParameter( final Object aParameter ) {
if ( aParameter instanceof MethodCall ) { if ( aParameter instanceof MethodCall ) {
final MethodCall methodCall = (MethodCall) aParameter; final MethodCall methodCall = (MethodCall) aParameter;
...@@ -105,8 +125,12 @@ class TracesController extends ControllerBase<TracesViewModel> { ...@@ -105,8 +125,12 @@ class TracesController extends ControllerBase<TracesViewModel> {
} }
} }
/**
* This action is performed, when the user wants to save the current filter as a filter favorite.
*/
public void performSaveAsFavorite( ) { public void performSaveAsFavorite( ) {
try { try {
// We simply save the filter's content and delegate to the main controller.
final TracesFilter filter = getViewModel( ).savePresentationFilter( ); final TracesFilter filter = getViewModel( ).savePresentationFilter( );
getController( MainController.class ).performSaveAsFavorite( TracesView.class, filter ); getController( MainController.class ).performSaveAsFavorite( TracesView.class, filter );
} catch ( final BusinessException ex ) { } catch ( final BusinessException ex ) {
......
...@@ -32,6 +32,11 @@ import kieker.diagnosis.ui.traces.components.MethodCellValueFactory; ...@@ -32,6 +32,11 @@ import kieker.diagnosis.ui.traces.components.MethodCellValueFactory;
import kieker.diagnosis.ui.traces.components.StyledRow; import kieker.diagnosis.ui.traces.components.StyledRow;
import kieker.diagnosis.ui.traces.components.TimestampCellValueFactory; import kieker.diagnosis.ui.traces.components.TimestampCellValueFactory;
/**
* The view of the traces tab.
*
* @author Nils Christian Ehmke
*/
@Singleton @Singleton
public class TracesView extends ViewBase<TracesController> { public class TracesView extends ViewBase<TracesController> {
......
...@@ -27,6 +27,11 @@ import kieker.diagnosis.ui.traces.aggregator.TraceDepthAggregator; ...@@ -27,6 +27,11 @@ import kieker.diagnosis.ui.traces.aggregator.TraceDepthAggregator;
import kieker.diagnosis.ui.traces.aggregator.TraceSizeAggregator; import kieker.diagnosis.ui.traces.aggregator.TraceSizeAggregator;
import kieker.diagnosis.ui.traces.components.MethodCallTreeItem; import kieker.diagnosis.ui.traces.components.MethodCallTreeItem;
/**
* The view model of the traces tab.
*
* @author Nils Christian Ehmke
*/
@Singleton @Singleton
class TracesViewModel extends ViewModelBase<TracesView> { class TracesViewModel extends ViewModelBase<TracesView> {
......
...@@ -7,12 +7,33 @@ import java.util.stream.Collectors; ...@@ -7,12 +7,33 @@ import java.util.stream.Collectors;
import kieker.diagnosis.service.data.MethodCall; import kieker.diagnosis.service.data.MethodCall;
/**
* Implementation of this class are responsible for aggregating method calls in a trace by various parameters.
*
* @author Nils Christian Ehmke
*/
public abstract class Aggregator { public abstract class Aggregator {
private final ResourceBundle ivResourceBundle = ResourceBundle.getBundle( Aggregator.class.getName( ) ); private final ResourceBundle ivResourceBundle = ResourceBundle.getBundle( Aggregator.class.getName( ) );
/**
* Aggregates the given list of method calls. This means that the resulting list should contain real method calls and (aggregated) pseudo method calls.
*
* @param aCalls
* The method calls to aggregate.
*
* @return The aggregated list.
*/
public abstract List<MethodCall> aggregate( List<MethodCall> aCalls ); public abstract List<MethodCall> aggregate( List<MethodCall> aCalls );
/**
* This is a helper method to aggregate a list of method calls into a single pseudo method call.
*
* @param aList
* The methods to be aggregated.
*
* @return A single pseudo method call.
*/
protected final MethodCall aggregateToSingleCall( final List<MethodCall> aList ) { protected final MethodCall aggregateToSingleCall( final List<MethodCall> aList ) {
final double percent = aList.parallelStream( ).map( MethodCall::getPercent ).collect( Collectors.summingDouble( Float::doubleValue ) ); final double percent = aList.parallelStream( ).map( MethodCall::getPercent ).collect( Collectors.summingDouble( Float::doubleValue ) );
final long duration = aList.parallelStream( ).map( MethodCall::getDuration ).collect( Collectors.summingLong( Long::longValue ) ); final long duration = aList.parallelStream( ).map( MethodCall::getDuration ).collect( Collectors.summingLong( Long::longValue ) );
......
...@@ -4,6 +4,11 @@ import java.util.Comparator; ...@@ -4,6 +4,11 @@ import java.util.Comparator;
import kieker.diagnosis.service.data.MethodCall; import kieker.diagnosis.service.data.MethodCall;
/**
* This aggregator aggregates method calls by duration. That means that method calls in a trace with lower duration are aggregated into a single method call.
*
* @author Nils Christian Ehmke
*/
public final class DurationAggregator extends PropertyAggregator { public final class DurationAggregator extends PropertyAggregator {
public DurationAggregator( final int aMaxCalls ) { public DurationAggregator( final int aMaxCalls ) {
......
...@@ -4,6 +4,11 @@ import java.util.List; ...@@ -4,6 +4,11 @@ import java.util.List;
import kieker.diagnosis.service.data.MethodCall; import kieker.diagnosis.service.data.MethodCall;
/**
* This aggregator is a pseudo aggregator which does not do anything. It is basically the identity function on method call aggregation.
*
* @author Nils Christian Ehmke
*/
public final class IdentityAggregator extends Aggregator { public final class IdentityAggregator extends Aggregator {
@Override @Override
......
...@@ -16,16 +16,20 @@ public abstract class PropertyAggregator extends Aggregator { ...@@ -16,16 +16,20 @@ public abstract class PropertyAggregator extends Aggregator {
} }
@Override @Override
public List<MethodCall> aggregate( final List<MethodCall> aCalls ) { public final List<MethodCall> aggregate( final List<MethodCall> aCalls ) {
final List<MethodCall> accepted = new ArrayList<>( ); final List<MethodCall> accepted = new ArrayList<>( );
// Sort the methods by the comparator of the concrete implementation
final Iterator<MethodCall> iterator = aCalls.stream( ).sorted( getComparator( ) ).iterator( ); final Iterator<MethodCall> iterator = aCalls.stream( ).sorted( getComparator( ) ).iterator( );
// Get the first n method calls (where n is the maximal numbers of allowed method calls)
int maxCalls = ivMaxCalls; int maxCalls = ivMaxCalls;
while ( maxCalls > 0 && iterator.hasNext( ) ) { while ( maxCalls > 0 && iterator.hasNext( ) ) {
accepted.add( iterator.next( ) ); accepted.add( iterator.next( ) );
maxCalls--; maxCalls--;
} }
// The remaining method calls - if there are any - have to be aggregated.
final List<MethodCall> toBeAggregated = new ArrayList<>( ); final List<MethodCall> toBeAggregated = new ArrayList<>( );
while ( iterator.hasNext( ) ) { while ( iterator.hasNext( ) ) {
toBeAggregated.add( iterator.next( ) ); toBeAggregated.add( iterator.next( ) );
...@@ -35,7 +39,7 @@ public abstract class PropertyAggregator extends Aggregator { ...@@ -35,7 +39,7 @@ public abstract class PropertyAggregator extends Aggregator {
final MethodCall methodCall = aggregateToSingleCall( toBeAggregated ); final MethodCall methodCall = aggregateToSingleCall( toBeAggregated );
accepted.add( methodCall ); accepted.add( methodCall );
} else { } else {
// if the list is empty or contains only a single method call, we do not want to aggregate // If the list is empty or contains only a single method call, we do not want to aggregate
accepted.addAll( toBeAggregated ); accepted.addAll( toBeAggregated );
} }
......
...@@ -5,6 +5,11 @@ import java.util.List; ...@@ -5,6 +5,11 @@ import java.util.List;
import kieker.diagnosis.service.data.MethodCall; import kieker.diagnosis.service.data.MethodCall;
/**
* This aggregator aggregates method calls by a given threshold. That means that method calls below this threshold are aggregated into a single method call.
*
* @author Nils Christian Ehmke
*/
public final class ThresholdAggregator extends Aggregator { public final class ThresholdAggregator extends Aggregator {
private final float ivThreshold; private final float ivThreshold;
...@@ -18,6 +23,7 @@ public final class ThresholdAggregator extends Aggregator { ...@@ -18,6 +23,7 @@ public final class ThresholdAggregator extends Aggregator {
final List<MethodCall> underThreshold = new ArrayList<>( ); final List<MethodCall> underThreshold = new ArrayList<>( );
final List<MethodCall> overThreshold = new ArrayList<>( ); final List<MethodCall> overThreshold = new ArrayList<>( );
// Separate the method calls with the threshold.
for ( final MethodCall call : calls ) { for ( final MethodCall call : calls ) {
if ( call.getPercent( ) < ivThreshold ) { if ( call.getPercent( ) < ivThreshold ) {
underThreshold.add( call ); underThreshold.add( call );
...@@ -27,10 +33,11 @@ public final class ThresholdAggregator extends Aggregator { ...@@ -27,10 +33,11 @@ public final class ThresholdAggregator extends Aggregator {
} }
if ( underThreshold.size( ) > 1 ) { if ( underThreshold.size( ) > 1 ) {
// If there are multiple method calls below the threshold, we want to aggregate them
final MethodCall methodCall = aggregateToSingleCall( underThreshold ); final MethodCall methodCall = aggregateToSingleCall( underThreshold );
overThreshold.add( methodCall ); overThreshold.add( methodCall );
} else { } else {
// if the list is empty or contains only a single method call, we do not want to aggregate // If the list is empty or contains only a single method call, we do not want to aggregate
overThreshold.addAll( underThreshold ); overThreshold.addAll( underThreshold );
} }
......
...@@ -4,6 +4,12 @@ import java.util.Comparator; ...@@ -4,6 +4,12 @@ import java.util.Comparator;
import kieker.diagnosis.service.data.MethodCall; import kieker.diagnosis.service.data.MethodCall;
/**
* This aggregator aggregates method calls by trace depth. That means that method calls in a trace with lower trace depth are aggregated into a single method
* call.
*
* @author Nils Christian Ehmke
*/
public final class TraceDepthAggregator extends PropertyAggregator { public final class TraceDepthAggregator extends PropertyAggregator {
public TraceDepthAggregator( final int aMaxCalls ) { public TraceDepthAggregator( final int aMaxCalls ) {
......
...@@ -4,6 +4,12 @@ import java.util.Comparator; ...@@ -4,6 +4,12 @@ import java.util.Comparator;
import kieker.diagnosis.service.data.MethodCall; import kieker.diagnosis.service.data.MethodCall;
/**
* This aggregator aggregates method calls by trace size. That means that method calls in a trace with lower trace size are aggregated into a single method
* call.
*
* @author Nils Christian Ehmke
*/
public final class TraceSizeAggregator extends PropertyAggregator { public final class TraceSizeAggregator extends PropertyAggregator {
public TraceSizeAggregator( final int aMaxCalls ) { public TraceSizeAggregator( final int aMaxCalls ) {
......
...@@ -12,6 +12,12 @@ import kieker.diagnosis.service.data.MethodCall; ...@@ -12,6 +12,12 @@ import kieker.diagnosis.service.data.MethodCall;
import kieker.diagnosis.service.settings.ClassAppearance; import kieker.diagnosis.service.settings.ClassAppearance;
import kieker.diagnosis.service.settings.properties.ClassAppearanceProperty; import kieker.diagnosis.service.settings.properties.ClassAppearanceProperty;
/**
* This is a cell factory for a tree table which shows the class of a method call in the configured manner. It has to be in the CDI context, as it has to have
* access to the application properties.
*
* @author Nils Christian Ehmke
*/
@Singleton @Singleton
public class ClassCellValueFactory implements Callback<CellDataFeatures<MethodCall, String>, ObservableValue<String>> { public class ClassCellValueFactory implements Callback<CellDataFeatures<MethodCall, String>, ObservableValue<String>> {
......
...@@ -13,6 +13,12 @@ import kieker.diagnosis.architecture.service.properties.PropertiesService; ...@@ -13,6 +13,12 @@ import kieker.diagnosis.architecture.service.properties.PropertiesService;
import kieker.diagnosis.service.data.MethodCall; import kieker.diagnosis.service.data.MethodCall;
import kieker.diagnosis.service.settings.properties.TimeUnitProperty; import kieker.diagnosis.service.settings.properties.TimeUnitProperty;
/**
* This is a cell factory for a tree table which shows the duration of a method call in the configured manner. It has to be in the CDI context, as it has to
* have access to the application properties.
*
* @author Nils Christian Ehmke
*/
@Singleton @Singleton
public class DurationCellValueFactory implements Callback<CellDataFeatures<MethodCall, Long>, ObservableValue<Long>> { public class DurationCellValueFactory implements Callback<CellDataFeatures<MethodCall, Long>, ObservableValue<Long>> {
......
...@@ -10,6 +10,12 @@ import kieker.diagnosis.architecture.common.ClassUtil; ...@@ -10,6 +10,12 @@ import kieker.diagnosis.architecture.common.ClassUtil;
import kieker.diagnosis.service.data.MethodCall; import kieker.diagnosis.service.data.MethodCall;
import kieker.diagnosis.ui.traces.aggregator.Aggregator; import kieker.diagnosis.ui.traces.aggregator.Aggregator;
/**
* This is an item for a tree table, which contains a method call. The children are loaded in a lazy way. The item enriches and aggregates the children based on
* the current application settings.
*
* @author Nils Christian Ehmke
*/
public final class MethodCallTreeItem extends TreeItem<MethodCall> { public final class MethodCallTreeItem extends TreeItem<MethodCall> {
private final ResourceBundle ivResourceBundle = ResourceBundle.getBundle( ClassUtil.getRealName( getClass( ) ) ); private final ResourceBundle ivResourceBundle = ResourceBundle.getBundle( ClassUtil.getRealName( getClass( ) ) );
...@@ -18,6 +24,16 @@ public final class MethodCallTreeItem extends TreeItem<MethodCall> { ...@@ -18,6 +24,16 @@ public final class MethodCallTreeItem extends TreeItem<MethodCall> {
private final boolean ivShowUnmonitoredTime; private final boolean ivShowUnmonitoredTime;
private final Aggregator ivAggregator; private final Aggregator ivAggregator;
/**
* Creates a new tree item.
*
* @param aMethodCall
* The method call to be contained in the new item.
* @param aShowUnmonitoredTime
* Determines whether the node should show the unmonitored time.
* @param aAggregator
* The aggregator which is used to aggregate the children of the node.
*/
public MethodCallTreeItem( final MethodCall aMethodCall, final boolean aShowUnmonitoredTime, final Aggregator aAggregator ) { public MethodCallTreeItem( final MethodCall aMethodCall, final boolean aShowUnmonitoredTime, final Aggregator aAggregator ) {
super( aMethodCall ); super( aMethodCall );
...@@ -27,6 +43,7 @@ public final class MethodCallTreeItem extends TreeItem<MethodCall> { ...@@ -27,6 +43,7 @@ public final class MethodCallTreeItem extends TreeItem<MethodCall> {
@Override @Override
public final ObservableList<TreeItem<MethodCall>> getChildren( ) { public final ObservableList<TreeItem<MethodCall>> getChildren( ) {
// Initialize the children in a lazy way.
if ( !ivChildrenInitialized ) { if ( !ivChildrenInitialized ) {
ivChildrenInitialized = true; ivChildrenInitialized = true;
initializeChildren( ); initializeChildren( );
...@@ -43,8 +60,10 @@ public final class MethodCallTreeItem extends TreeItem<MethodCall> { ...@@ -43,8 +60,10 @@ public final class MethodCallTreeItem extends TreeItem<MethodCall> {
private void initializeChildren( ) { private void initializeChildren( ) {
final List<TreeItem<MethodCall>> result = new ArrayList<>( ); final List<TreeItem<MethodCall>> result = new ArrayList<>( );
// Aggregate the method calls if necessary
final List<MethodCall> children = ivAggregator.aggregate( getValue( ).getChildren( ) ); final List<MethodCall> children = ivAggregator.aggregate( getValue( ).getChildren( ) );
// Show the unmonitored time if necessary
if ( ivShowUnmonitoredTime ) { if ( ivShowUnmonitoredTime ) {
// Calculate the unmonitored time // Calculate the unmonitored time
float percent = 0.0f; float percent = 0.0f;
...@@ -69,6 +88,7 @@ public final class MethodCallTreeItem extends TreeItem<MethodCall> { ...@@ -69,6 +88,7 @@ public final class MethodCallTreeItem extends TreeItem<MethodCall> {
result.add( new MethodCallTreeItem( methodCall, false, ivAggregator ) ); result.add( new MethodCallTreeItem( methodCall, false, ivAggregator ) );
} }
// Now convert the children into items
for ( final MethodCall child : children ) { for ( final MethodCall child : children ) {
result.add( new MethodCallTreeItem( child, ivShowUnmonitoredTime, ivAggregator ) ); result.add( new MethodCallTreeItem( child, ivShowUnmonitoredTime, ivAggregator ) );
} }
......
...@@ -12,6 +12,12 @@ import kieker.diagnosis.service.data.MethodCall; ...@@ -12,6 +12,12 @@ import kieker.diagnosis.service.data.MethodCall;
import kieker.diagnosis.service.settings.MethodAppearance; import kieker.diagnosis.service.settings.MethodAppearance;
import kieker.diagnosis.service.settings.properties.MethodAppearanceProperty; import kieker.diagnosis.service.settings.properties.MethodAppearanceProperty;
/**
* This is a cell factory for a tree table which shows the method of a method call in the configured manner. It has to be in the CDI context, as it has to have
* access to the application properties.
*
* @author Nils Christian Ehmke
*/
@Singleton @Singleton
public class MethodCellValueFactory implements Callback<CellDataFeatures<MethodCall, String>, ObservableValue<String>> { public class MethodCellValueFactory implements Callback<CellDataFeatures<MethodCall, String>, ObservableValue<String>> {
......
...@@ -3,12 +3,18 @@ package kieker.diagnosis.ui.traces.components; ...@@ -3,12 +3,18 @@ package kieker.diagnosis.ui.traces.components;
import javafx.scene.control.TreeTableRow; import javafx.scene.control.TreeTableRow;
import kieker.diagnosis.service.data.MethodCall; import kieker.diagnosis.service.data.MethodCall;
/**
* This is a row for a tree table which is aware of a method call being failed. If the method call has an exception, it is styled accordingly.
*
* @author Nils Christian Ehmke
*/
public final class StyledRow extends TreeTableRow<MethodCall> { public final class StyledRow extends TreeTableRow<MethodCall> {
@Override @Override
protected void updateItem( final MethodCall aItem, final boolean aEmpty ) { protected void updateItem( final MethodCall aItem, final boolean aEmpty ) {
super.updateItem( aItem, aEmpty ); super.updateItem( aItem, aEmpty );
// Remove a potential style class from an earlier run
getStyleClass( ).remove( "failed" ); getStyleClass( ).remove( "failed" );
if ( aItem != null && aItem.getException( ) != null ) { if ( aItem != null && aItem.getException( ) != null ) {
......
...@@ -12,6 +12,12 @@ import kieker.diagnosis.service.data.MethodCall; ...@@ -12,6 +12,12 @@ import kieker.diagnosis.service.data.MethodCall;
import kieker.diagnosis.service.settings.TimestampAppearance; import kieker.diagnosis.service.settings.TimestampAppearance;
import kieker.diagnosis.service.settings.properties.TimestampProperty; import kieker.diagnosis.service.settings.properties.TimestampProperty;
/**
* This is a cell factory for a tree table which shows the timestamp of a method call in the configured manner. It has to be in the CDI context, as it has to
* have access to the application properties.
*
* @author Nils Christian Ehmke
*/
@Singleton @Singleton
public class TimestampCellValueFactory implements Callback<CellDataFeatures<MethodCall, String>, ObservableValue<String>> { public class TimestampCellValueFactory implements Callback<CellDataFeatures<MethodCall, String>, ObservableValue<String>> {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment