Skip to content

Commit

Permalink
Fixed a bug where traces on recursive functions were coming out
Browse files Browse the repository at this point in the history
backwards!

Timestamps in microseconds for time spent in functions

Copy/Delete traces

Trace all exported functions in a module.
  • Loading branch information
Andy Till committed Jul 28, 2015
1 parent 336bc3c commit 1ac80ff
Show file tree
Hide file tree
Showing 12 changed files with 274 additions and 108 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>andytill</groupId>
<artifactId>erlyberly</artifactId>
<version>0.6.2</version>
<version>0.6.3</version>
<packaging>jar</packaging>

<name>erlyberly</name>
Expand Down
28 changes: 14 additions & 14 deletions src/main/java/erlyberly/CallGraphView.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package erlyberly;

import java.util.Arrays;
import java.util.List;

import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;

Expand All @@ -14,6 +17,14 @@


public class CallGraphView extends TreeView<ModFunc> {

/**
* A list of module names that will not be expanded in the call graph tree, since
* they have lots of sub-calls, cluttering up the tree and it is assumed most usage
* will be for application calls, not for the standard libs.
*/
private static List<String> UNEXPANDED_MODULES = Arrays.asList(
"erlang", "gen_server", "io", "io_lib", "lists", "rpc", "unicode");

private ModFuncContextMenu modFuncContextMenu;

Expand Down Expand Up @@ -70,7 +81,9 @@ private void populateCallGraph(TreeItem<ModFunc> parentModFuncItem, OtpErlangTup
TreeItem<ModFunc> modFuncItem;

modFuncItem = new TreeItem<>(modFunc);
modFuncItem.setExpanded(true);
String atomString = module.atomValue();
boolean value = !UNEXPANDED_MODULES.contains(atomString);
modFuncItem.setExpanded(value);

parentModFuncItem.getChildren().add(modFuncItem);

Expand All @@ -82,17 +95,4 @@ private void populateCallGraph(TreeItem<ModFunc> parentModFuncItem, OtpErlangTup
e.printStackTrace();
}
}

class CGModFunc {
private final ModFunc modFunc;

public CGModFunc(ModFunc aModFunc) {
modFunc = aModFunc;
}

@Override
public String toString() {
return modFunc.toFullString();
}
}
}
49 changes: 21 additions & 28 deletions src/main/java/erlyberly/DbgView.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,12 @@
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.Separator;
import javafx.scene.control.SplitPane;
import javafx.scene.control.SplitPane.Divider;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
Expand Down Expand Up @@ -94,8 +93,15 @@ public class DbgView implements Initializable {

private ModFuncContextMenu modFuncContextMenu;

/**
* Set insertTracesAtTop=true in the .erlyberly file in your home directory to
* make traces be inserted at the top of the list.
*/
private boolean insertTracesAtTop;

@Override
public void initialize(URL url, ResourceBundle r) {
insertTracesAtTop = PrefBind.getOrDefault("insertTracesAtTop", "false").equals("true");

modFuncContextMenu = new ModFuncContextMenu(dbgController);
modulesTree
Expand All @@ -122,7 +128,7 @@ public void initialize(URL url, ResourceBundle r) {
tracesBox.setCellFactory(new TraceLogListCellFactory());

modulesTree.setCellFactory(new ModFuncTreeCellFactory(dbgController));
modulesTree.setOnKeyReleased(this::onKeyReleaseInModuleTree);
/*modulesTree.setOnKeyPressed(this::onKeyPressInModuleTree);*/
modulesTree.setContextMenu(modFuncContextMenu);

Bindings.bindContentBidirectional(tracesBox.getItems(), filteredTraces);
Expand All @@ -132,26 +138,14 @@ public void initialize(URL url, ResourceBundle r) {
addTraceLogFloatySearchControl();

dbgController.initialize(url, r);
}

/**
* if <code>ctrl+t</code> is released while focus is on the tree view, then check the
* selected item is a function and toggle tracing for it.
*/
private void onKeyReleaseInModuleTree(KeyEvent e) {

TreeItem<ModFunc> item = modulesTree.getSelectionModel().getSelectedItem();
TraceContextMenu traceContextMenu = new TraceContextMenu();
traceContextMenu.setItems(traceLogs);
traceContextMenu
.setSelectedItems(tracesBox.getSelectionModel().getSelectedItems());

if(!e.isControlDown())
return;
if(e.getCode() != KeyCode.T)
return;
if(item == null || item.getValue() == null)
return;
if(item.getValue().isModule())
return;

toggleTraceModFunc(item.getValue());
tracesBox.setContextMenu(traceContextMenu);
tracesBox.selectionModelProperty().get().setSelectionMode(SelectionMode.MULTIPLE);
}

private FxmlLoadable addModulesFloatySearchControl() {
Expand Down Expand Up @@ -199,7 +193,10 @@ private FxmlLoadable addTraceLogFloatySearchControl() {
public void traceLogsChanged(ListChangeListener.Change<? extends TraceLog> e) {
while(e.next()) {
for (TraceLog trace : e.getAddedSubList()) {
traceLogs.add(0, trace);
if(insertTracesAtTop)
traceLogs.add(0, trace);
else
traceLogs.add(trace);
}
}
}
Expand Down Expand Up @@ -318,7 +315,8 @@ private void showTraceTermView(final TraceLog traceLog) {

StringBuilder sb = new StringBuilder(traceLog.getPidString());
sb.append(" ");
traceLog.appendFunctionToString(sb);
boolean appendArity = false;
traceLog.appendFunctionToString(sb, appendArity);

showWindow(splitPane, sb);
}
Expand Down Expand Up @@ -355,11 +353,6 @@ private boolean isMatchingModFunc(String searchText, TreeItem<ModFunc> t) {
return true;
return t.getValue().toString().contains(searchText);
}

private void toggleTraceModFunc(ModFunc function) {
dbgController.toggleTraceModFunc(function);
}


private void onConnected(Observable o) {
boolean connected = ErlyBerly.nodeAPI().connectedProperty().get();
Expand Down
33 changes: 30 additions & 3 deletions src/main/java/erlyberly/ModFuncContextMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.control.TextArea;
import javafx.scene.control.TreeItem;
import javafx.scene.input.KeyCombination;
import javafx.stage.Stage;

import com.ericsson.otp.erlang.OtpErlangException;
Expand Down Expand Up @@ -47,10 +48,15 @@ public ModFuncContextMenu(DbgController aDbgController) {
selectedItem = new SimpleObjectProperty<>();
selectedTreeItem = new SimpleObjectProperty<>();

MenuItem seqTraceMenuItem, functionTraceMenuItem, moduleTraceMenuItem, callGraphMenuItem, moduleSourceCodeItem, moduleAbstCodeItem;
MenuItem functionTraceMenuItem, exportsTraceMenuItem, moduleTraceMenuItem, seqTraceMenuItem, callGraphMenuItem, moduleSourceCodeItem, moduleAbstCodeItem;

functionTraceMenuItem = new MenuItem("Function Trace");
functionTraceMenuItem.setOnAction(this::onFunctionTrace);
functionTraceMenuItem.setAccelerator(KeyCombination.keyCombination("shortcut+t"));

exportsTraceMenuItem = new MenuItem("Exported Function Trace");
exportsTraceMenuItem.setOnAction(this::onExportedFunctionTrace);
exportsTraceMenuItem.setAccelerator(KeyCombination.keyCombination("shortcut+e"));

moduleTraceMenuItem = new MenuItem("Recursive Trace");
moduleTraceMenuItem.setOnAction(this::onModuleTrace);
Expand All @@ -66,10 +72,9 @@ public ModFuncContextMenu(DbgController aDbgController) {

callGraphMenuItem = new MenuItem("View Call Graph");
callGraphMenuItem.setOnAction(this::onViewCallGraph);


getItems().addAll(
functionTraceMenuItem, moduleTraceMenuItem, seqTraceMenuItem,
functionTraceMenuItem, exportsTraceMenuItem, moduleTraceMenuItem, seqTraceMenuItem,
new SeparatorMenuItem(),
callGraphMenuItem, moduleSourceCodeItem, moduleAbstCodeItem);
}
Expand Down Expand Up @@ -134,6 +139,28 @@ private void onModuleTrace(ActionEvent e) {

toggleTraceMod(funcs);
}

private void onExportedFunctionTrace(ActionEvent e) {
TreeItem<ModFunc> selectedItem = selectedTreeItemProperty().get();

if(selectedItem == null)
return;

// get all the functions we may trace
HashSet<ModFunc> funcs = new HashSet<ModFunc>();
recurseModFuncItems(selectedItem, funcs);

// filter the exported ones
HashSet<ModFunc> exported = new HashSet<ModFunc>();
for (ModFunc modFunc : funcs) {
if(modFunc.isExported()) {
exported.add(modFunc);
}
}

// trace 'em
toggleTraceMod(exported);
}

private void recurseModFuncItems(TreeItem<ModFunc> item, HashSet<ModFunc> funcs) {
if(item == null)
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/erlyberly/PrefBind.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class PrefBind {
private static File erlyberlyConfig;

private static boolean awaitingStore;

public static void bind(final String propName, StringProperty stringProp) {
if(props == null) {
return;
Expand Down Expand Up @@ -88,4 +88,12 @@ public static void setup() throws IOException {

props = properties;
}

public static Object get(Object key) {
return props.get(key);
}

public static Object getOrDefault(String key, Object theDefault) {
return props.getOrDefault(key, theDefault);
}
}
6 changes: 3 additions & 3 deletions src/main/java/erlyberly/TopBarView.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@
import floatyfield.FloatyFieldView;

public class TopBarView implements Initializable {
private static final KeyCodeCombination TOGGLE_HIDE_PROCESSES_SHORTCUT = new KeyCodeCombination(KeyCode.P, KeyCombination.CONTROL_DOWN);
private static final KeyCodeCombination TOGGLE_HIDE_PROCESSES_SHORTCUT = new KeyCodeCombination(KeyCode.P, KeyCombination.SHORTCUT_DOWN);

private static final KeyCodeCombination TOGGLE_HIDE_MODULES_SHORTCUT = new KeyCodeCombination(KeyCode.M, KeyCombination.CONTROL_DOWN);
private static final KeyCodeCombination TOGGLE_HIDE_MODULES_SHORTCUT = new KeyCodeCombination(KeyCode.M, KeyCombination.SHORTCUT_DOWN);

private static final KeyCodeCombination REFRESH_MODULES_SHORTCUT = new KeyCodeCombination(KeyCode.R, KeyCombination.CONTROL_DOWN);
private static final KeyCodeCombination REFRESH_MODULES_SHORTCUT = new KeyCodeCombination(KeyCode.R, KeyCombination.SHORTCUT_DOWN);

@FXML
private ToggleButton hideProcessesButton;
Expand Down
81 changes: 81 additions & 0 deletions src/main/java/erlyberly/TraceContextMenu.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package erlyberly;


import java.util.ArrayList;

import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.KeyCombination;

public class TraceContextMenu extends ContextMenu {

private ObservableList<TraceLog> items, selectedItems;

public TraceContextMenu() {
getItems().add(menuItem("Copy All", "shortcut+c", this::onCopy));
getItems().add(menuItem("Copy Function Call", null, this::onCopyCalls));
getItems().add(menuItem("Delete", "delete", this::onDelete));
}

private MenuItem menuItem(String text, String accelerator, EventHandler<ActionEvent> e) {
MenuItem menuItem;

menuItem = new MenuItem(text);
menuItem.setOnAction(e);

if(accelerator != null)
menuItem.setAccelerator(KeyCombination.keyCombination(accelerator));

return menuItem;
}

private void onCopy(ActionEvent e) {
StringBuilder sbuilder = new StringBuilder();

for (TraceLog traceLog : selectedItems) {
sbuilder.append(traceLog.toString()).append("\n");
}

copyToClipboard(sbuilder);
}

private void onCopyCalls(ActionEvent e) {
StringBuilder sbuilder = new StringBuilder();

for (TraceLog traceLog : selectedItems) {
sbuilder.append(traceLog.toCallString()).append("\n");
}

copyToClipboard(sbuilder);
}

private void copyToClipboard(StringBuilder sbuilder) {
final Clipboard clipboard = Clipboard.getSystemClipboard();
final ClipboardContent content = new ClipboardContent();

content.putString(sbuilder.toString());
clipboard.setContent(content);
}

private void onDelete(ActionEvent e) {
ArrayList<TraceLog> arrayList = new ArrayList<TraceLog>(selectedItems);

for (TraceLog traceLog : arrayList) {
items.remove(traceLog);
}
}


public void setSelectedItems(ObservableList<TraceLog> selectedItems2) {
selectedItems = selectedItems2;
}

public void setItems(ObservableList<TraceLog> items2) {
items = items2;
}
}
Loading

0 comments on commit 1ac80ff

Please sign in to comment.