Specifying Debugpoints

Debugpoints are specified using a JSON document encoded in the database character set.

Each debugpoint has the following elements:
  • A location in the source code where the information is collected

  • An action that describes what information to collect

  • An optional condition that controls when debug information should be collected

Example 9-1 JSON Template for Specifying Debugpoints

{
at: <location-spec>,
action: [ <action-spec>, ... ],
[ condition: <condition-spec> ]
}

Debugpoint Locations

Debugpoint locations are specified via the line number in the source code of the application being debugged.

The name of the MLE module to be debugged is specified via the name field and the location within the module where debug information is to be collected is specified via the line field. Example 9-4 provides an example JSON document with sample values.

Debugpoint Actions

MLE post-execution debugging supports two kinds of actions: watch and snapshot.

The watch action allows you to log the value of the variable named in the id field. The optional depth field provides you with control over the depth to which values of composite type variables are logged.

The snapshot action logs the stack trace at the point the snapshot action is invoked, along with the values of the local variables in each stack frame. A higher cost of performance is required by snapshot compared with watch but it provides a greater depth of information. As with the watch action, the optional depth field can be used to control the depth of logging for each variable. The depth parameter for the snapshot action applies to all variables captured by the action.

More precisely, the depth parameter controls how deeply you traverse the object tree in order to capture the value of a variable. For example, consider the following variable with nested objects:

let x = {
a: {
    val: 42
},
b: 3.14
};

If the depth field is defined as 2, the object tree would be traversed and the value of the nested object a would be captured, which in this case is 42. If depth is specified as 1, the traversal would end at the first level, which would produce the following results:

x = {
"a": {
    "<unreachable>": true
};
"b": 3.14
}

The framesLimit field provides you with control over the number of stack frames to be logged. The default is to log all stack frames. framesLimit only applies to snapshot. Take, for example, a call hierarchy where a() calls b() and b() calls c(). If you take a snapshot in c(), framesLimit=1 would only capture the bottom-most stack frame (in this case, c()), framesLimit=2 would capture the bottom two (in this case, c() and b()), and so on.

Example 9-2 JSON Template for Specifying Watch Action

To watch a variable, type must be set to watch. The id parameter is used to identify the variable or variables to watch and must be provided as either a string or an array of strings. The depth parameter is optional and is defined by a number.

actions: [
  { type: "watch", 
    id: <string[]> | <string>,
    [depth : <number>] }
]

Example 9-3 JSON Template for Specifying Snapshot Action

To use the snapshot action, the type parameter must be set to snapshot. The framesLimit and depth fields are optionally provided as numbers.

actions: [
  { type: "snapshot", 
    [framesLimit: <number>],
    [depth : <number>] }
]

Debugpoint Conditions

Both watch and snapshot can be controlled via conditions specified in the condition field.

The expression is evaluated in the context of the application at the location specified in the debugpoint and the associated action is triggered only if the expression evaluates to true.

There are no restrictions on the type of expression that can be included in the condition field. You must ensure that evaluating any expressions does not alter the behavior of the program being debugged.

Example 9-4 Watching a Variable in an MLE Module

The following code specifies a debugpoint for a module, myModule1, with two associated actions. A watch action for variable x with the logging depth restricted to 3, and a watch action for variable y with no restrictions on logging depth. The debugpoint also has an associated condition so that the debugpoint actions only trigger if the condition (x.id>100) is met.

{
	"at" : {
		"name" : "myModule1",
		"line" : 314
	},
	"actions" : [
		{ "type": "watch", "id" : "x", "depth" : 3 },
		{ "type": "watch", "id" : "y" }
	],
	"condition" : "x.id > 100"
}