Tracing tool for Squeak/Smalltalk. Includes a debugger-like browser for records.
Metacello new
baseline: 'MessageSendRecorder';
repository: 'github://hpi-swa/MessageSendRecorder:master/packages';
load.
In general, you have to set up a MessageSendRecorder
with an instance of MessageSend
to then #record
a tree (or trace) of sends, which you can #browse
. The methods you watch define the granularity of the tree the recorder records.
For example, you can watch all methods in the Morphic and Graphics package to then record all sends involved for drawing the current world:
recorder := MessageSendRecorder new
watchPackageNamed: #Graphics;
watchPackageNamed: #Morphic;
setMessageSend: (MessageSend receiver: Project current world selector: #imageForm);
yourself.
You can then record and browse the results:
recorder record.
recorder topRecord browse.
You can also record the duration of each call, which can then be used to post-process the recording with additional information such as ration or time-to-run in milliseconds:
recorder record: #duration.
recorder collectTimeRatio. "post-record processing"
recorder collectTimeToRun. "post-record processing"
recorder topRecord browse.
The record browser looks like a debugger because it shows similar information:
You can configure the recorder with before/after blocks to write more information into the records such as argument classes and return values. Any extra information is stored in MessageSendRecordExtension
, which can dynamically add missing instance variables.
recorder
setBefore: { [:record :rcvr :args :context | record extension receiverObject: rcvr] }
after: { [:record :rcvr :args :result :context | record extension returnValue: result] }.
Beware of resource-intensive operations such as full object copies!
You can run the recorder multiple times to, for example, record extra information only later on. The recorder will complain with a MsrRecordNotFound
exception if the sends do not match the initial recording and hence indicate non-deterministic behavior.
recorder record. "initial recording"
recorder record: #duration. "additional run"
Note that the MsrRandumNumberWrapper
will provide a fixed seed and thus a deterministic way to re-record behavior that uses random numbers.
It is possible to just record critical information - such as full copies of arguments - for a specific send. After the initial recording, you can do that for any record in the tree:
recorder record.
"..."
recorder recordInto: aRecord before: "..." after: "..."
Note that that record must be reachable from the recorder's topRecord
.
It is possible to use a helper wrapper to then start the recording when that helper is triggered:
recorder recordSend: #openInWorld to: myMorph.
Note that the recorder needs to be configured as mentioned above. If that send is never triggered, method wrappers may lay around in your Squeak image.
There are examples in this project that #recordNextKeyStroke
or #recordNextMouseUp
to learn more about Morphic event handling. :smile: