
 [index entries: _debug_ _debugger_ _debugging_
                 _profile_ _profiler_ _profiling_
                 _coverage_ ]

_Errortrace_ is a stack-trace-on-exceptions/profiler/coverage tool for
 MzScheme.  Errortrace is not a complete debugger, and a real debugger
 in DrScheme is expected soon; meanwhile, using errortrace might be
 better than nothing.

Quick instructions
------------------

  0) Throw away .zo versions of your source

  1) Prefix your program with
      (require (lib "errortrace.ss" "errortrace"))
     or start MzScheme with the -M flag:
      mzscheme -M errortrace

  2) When an exception occurs, the exception handler
     prints something like a stack trace, most recent
     contexts first

The errortrace module is odd; don't import it into another
module. Instead, the errortrace module is meant to be invoked from the
top-level, so that it can install an evaluation handler, exception
handler, etc.

To reuse parts of the code of errortrace, import
_errortrace-lib.ss_. It contains all of the names here but
does not set the eval-handler or the error-display-handler.

Exception Information
---------------------

Invoking the errortrace.ss module sets the eval handler to instrument
Scheme source code.

 NOTE: errortrace has no effect on code loaded as compiled byte code
 (i.e., from a .zo file) or native code (i.e., from a .dll or .so
 file).

The errortrace.ss module also sets a debug info handler to record
information about the context of exceptions, and an exception handler
to print out information recorded by the debug info handler. The load
handler is changed to correlate source code with source files.

Errortrace's instrumentation can be explicitly disabled via the
`instrumenting-enabled' boolean parameter. Instrumentation is on by
default. The `instrumenting-enabled' parameter affects only the way
that source code is compiled, not the way that exception information
is reported.

> (instrumenting-enabled) - returns #t if error tracing instrumentation is
  enabled, #f otherwise
> (instrumenting-enabled on?) - enables/disables error tracing
  instrumentation

The instrumentation for storing exception information slows most
programs by a factor of 2 or 3.

Do not load errortrace before writing .zo files. Errortrace
instruments S-expressions with unprintable values; this works fine if
the instrumented S-expression is passed to the default eval handler,
but neither the S-expression nor its byte-code form can be marshalled
to a string.

The `print-error-trace' procedure takes a port and exception and
prints the errortrace-collected debugging information contained in the
exception. It is used by the exception handler installed by
errortrace.

> (print-error-trace output-port exn) - prints the errortrace
  information in `exn' to `output-port'.

The `error-context-display-depth' parameter controls how much context
errortrace's exception handler displays. The default value is 10000.

> (error-context-display-depth) - returns the current context display
  depth
> (error-context-display-depth d) - sets the context display depth to
  `d'

Profiling
---------

Errortrace's profiling instrumentation is off by default. Enable
profiling instrumentation with the `profiling-enabled' boolean
parameter (but setting `instrumentation-enabled' to #f also disables
profiling):

> (profiling-enabled) - returns #t if profiling instrumentation is
  enabled, #f otherwise
> (profiling-enabled on?) - enables/disables profiling instrumentation

> (profiling-record-enabled) - returns #t if profiling info is
  recorded for instrumented code, #f otherwise; the default is #t
> (profiling-record-enabled on?) - enables/disables the recording of
  profiling info (independent of whether newly evaluated code is
  instrumented)

Profiling records:

 * the number of times a procedure was called.

 * the number of milliseconds consumed by the procedure's body across
   all calls (including the time consumed by any nested non-tail call
   within the procedure, but not including time consumed by a
   tail-call from the procedure).

 * an inferred name for the procedure.

 * the procedure's source in the form of a syntax object (which might,
   in turn, provide a source location file and position).

 * optionally, information about the procedure call path (something
   like the stack trace) for every call to the procedure. Path
   information is collected when the `profile-paths-enabled' boolean
   parameter is #t; the default is #f, but setting the parameter to #t
   immediately affects all procedure instrumented for profiling
   information:

>   (profile-paths-enabled) - returns #t if profiling collects path
    information, #f otherwise
>   (profile-paths-enabled on?) - enables/disables collecting path
    information for profiling

Profiling information is accumulated in a hash table. If a procedure
is redefined, new profiling information is accumulated for the new
version of the procedure, but the old information is also preserved.

To retrieve all profiling information accumulated so far, call
`get-profile-results':

> (get-profile-results) - returns a list of lists that contain:

  * the number of times the procedure was called;

  * the number of milliseconds of process time consumed by the
    procedure;

  * the inferred name or #f of the procedure;

  * the syntax source of the procedure; and

  * a list of call paths, recorded while `profile-paths-enabled' is
    set to #t. Each call path is a list containing two-element lists;
    each two-element list contains the calling proceure's name or
    source expression and the calling procedure's source file or #f.

Depending of the source program, profiling usually induces a factor of
2 to 4 slowdown (in addition to any slowdown from the exception
information instrumentation).

> (output-profile-results paths? sort-time?)

Gets the current profile results and displays them. It optionally
shows paths information (if it is recorded) and sorts by either time
or call counts.

Coverage
--------

Errortrace can track expression execution that is useful for checking
test coverage (i.e., simple expression coverage). Enable coverage
checking with the `execute-counts-enabled' boolean parameter (but
setting `instrumentation-enabled' to #f also disables execute
counting):

> (execute-counts-enabled) - returns #t if execute-counting
  instrumentation is enabled, #f otherwise
> (execute-counts-enabled on?) - enables/disables execute-counting
  instrumentation

> (get-execute-counts) - returns a list of pairs, one for each
  instrucmented expression. The first element of the pair is a syntax
  object (usually containing source location information) for the
  original expression, and the second element of the pair is the
  number of times that the expression has been evaluated.

> (annotate-executed-file filename-path) - writes the named file to
  the current output port, inserting an additional line between each
  source line to reflect execution counts (as reported by
  `get-execute-counts'). An expression underlined with "^" has been
  executed 0 times; an expression underlined with "." has been
  executed 1 time; and an expression underlined with "," has been
  executed multiple times.

_Re-using errortrace stack tracing_
-----------------------------------

The errortrace collection also includes a _stacktrace.ss_ library.
It exports the _stacktrace@_ unit and it import signature
_stacktrace-imports^_, and its export signature _stacktrace^_.

The export signature contains these names:

> annotate : syntax boolean -> syntax
> annotate-top : syntax boolean -> syntax
> st-mark-source : st-mark -> any
> st-mark-bindings : st-mark -> (listof (list syntax any))

The first two functions annotate expressions with errortrace
information.  The `annotate-top' function should be called with a
top-level expression, and `annotate' should be called with a nested
expression (e.g., by `profile-point'). The boolean argument indicates
whether the expression is a transformer expression (#t) or a normal
expression (#f).

The `st-mark-source' and `st-mark-bindings' functions extract
information from a particular kind of value. The value must be one
created by an expression that is generated during a use of `with-mark'
(see below); in particular, it must be the result of an expression
produced by `with-mark''s second argument. `st-mark-source' extracts
the value originally provided to the expresion-maker, and
`st-mark-bindings' returns local binding information (if available).

The import signature contains these names:

> with-mark : syntax (any -> syntax) syntax -> syntax

  This procedure is called by `annotate' and `annotate-top' to wrap
  expressions with `with-continuation-mark'. The first argument is the
  source expression and the thrid argument is the expression to be
  wrapped.

  The second argument is a function that takes any value V and
  incorporates it into a syntax object. The value V typically records
  the source lcation of the original expression. The return syntax
  object is suitable for use as a continuation-mark value
  expression. Use `st-mark-source' to extract V from the result of the
  expression.

> test-coverage-enabled : (parameter boolean)

  This parameter determines if the test coverage annotation
  is inserted into the code. This parameter controls how
  compilation happens -- it does not affect the dynamic
  behavior of the already compiled code. If the parameter is
  set, calls to test-covered are inserted into the code (and
  initialize-test-coverage-point is called during
  compilation). If not, no calls to test-covered are inserted.

> test-covered : symbol -> void

  During execution of the program, this is called for each
  point with the key for that program point that was passed
  to initialize-test-coverage-point.

> initialize-test-coverage-point : symbol syntax -> void

  During compilation of the program, this function is called
  with each sub-expression of the program. The first
  argument is a special key used to identify this program
  point. The second argument is the syntax of this program
  point. 

> profile-key : symbol

  only used for profiling paths

> profiling-enabled  : -> boolean

  determines if profiling information is currently collected
  (affects the behavior of compiling the code -- does not
  affect running code). If this always returns #f, 
  the other profiling functions are never called.

> initialize-profile-point : symbol (union #f syntax[symbol]) syntax -> void

  called as the program is compiled for each profiling point
  that might be encountered during the program's
  execution. The first argument is a key identifying this
  code. The second argument is the inferred name at this
  point and the final argument is the syntax of this expression.

> register-profile-start : symbol -> (union #f number)
 
  Called when some profiled code is about to be executed. If
  the result is a number, it is expected to be the current
  number of milliseconds. The symbol is a key that is unique
  to this fragment of code -- it is the same symbol passed
  to initialize-profile-point for this code fragment.
			      
> register-profile-done : symbol (union #f number) -> void

  This function is called when some profiled code is
  finished executing. The 

  Note that register-profile-start and register-profile-done
  can be called in a nested manner; in this case, the result
  of register-profile-point should be #f.

