Coding with Debug Instrumentation

To use debug instrumentation, you need to put special statements into your code. As the code runs, these debug statements will output information into the log (assuming the coverage is enabled, as described in Customizing Debug Instrumentation).

The primary special statement for instrumentation is zlog. This statement has one parameter, a formula.

    zlog formula

When the code runs, Panorama calculates the formula and puts the result into the log. So when you look at the log, you can see the result of that formula at that particular instant in time. Here’s an example of a short program with zlog statements added to monitor the progress of the program. I’ve put this into a procedure named Test Loop.

    zlog "Start program."
    for n,1,5
        zlog n
    endloop
    zlog "Finished."

If you run this program, the log output will look like this. (Don’t forget to enable the coverage for the procedure. If the coverage is off, the zlog statements will be ignored.) Notice that the start of each line begins with `[Test Loop]`, the name of the procedure. This helps you keep track in the log of what code is running, especially useful in large complicated databases with lots of procedures.

    [Test Loop] Start program.
    [Test Loop] 1
    [Test Loop] 2
    [Test Loop] 3
    [Test Loop] 4
    [Test Loop] 5
    [Test Loop] Finished.

#### Displaying Variables in the Log

It’s very common to display a variable or field in the log. Of course you can construct a formula to do that manually, but there is a function called labelize( that can help make that easier. This function displays not only the value of the variable or field, but its name. Here’s a revised version of the program that uses this function.

    zlog "Start program."
    for n,1,5
        zlog labelize(n)
    endloop
    zlog "Finished."

The log output looks very similar, except that now the variable name is displayed as well as the value. If you have a complicated log with pages of output, this can be invaluable.

    [Test Loop] Start program.
    [Test Loop] n: 1
    [Test Loop] n: 2
    [Test Loop] n: 3
    [Test Loop] n: 4
    [Test Loop] n: 5
    [Test Loop] Finished.

If the variable contains multiple lines of text, the labelize( function will automatically switch to a multi-line format.

    zlog "Start program."
    let Address = "1234 Tank Farm Road"+cr()+"Suite 72"+cr()+"San Luis Obispo, CA"
    zlog labelize(Address)

Here’s what a multi line value looks like in the log:

    [Test] Start program.
    [Test] === Address ============
    [Test] 1234 Tank Farm Road
    [Test] Suite 72
    [Test] San Luis Obispo, CA
    [Test] === END OF Address ============

By the way, there is no reason you can’t use multiple labelize( functions in one zlog statement, like this.

    let dbname = info("databasename")
    let fname = info("fieldname")
    zlog labelize(fname)+" in "+labelize(dbname)

The log output from this code will look something like this:

    [Test] fname: Phone in dbname: Contacts

However, this won’t work if any of the variables or fields contain multiple lines. In that case, you should only use a single labelize( function.

If you don’t like the format the labelize( function uses for the label and data, you can customize it. See labelize( for further information.

#### Displaying Formulas in the Log

The labelize( function only works with an individual variable or field name. You cannot use it with a general formula. For example, this code won’t work.

    zlog labelize(FirstName+" "+LastName))

In fact, it will result in an error that will stop the program. There are three possible solutions. First, you could just set up the required formula yourself.

    zlog "Full Name: "+FirstName+" "+LastName

Alternately, you could set up a temporary variable and use that.

    let fullname = FirstName+" "+LastName
    zlog labelize(fullname)

Finally, you can use the labelizeformula( function, as shown below. Note that the entire formula must be quoted, in this case with curly braces ({ and }).

    zlog labelizeformula({FirstName+" "+LastName})

The result will look like this:

    [Test] FirstName+" "+LastName --> Mary McCormack

If the formula result contains multiple lines of text, the labelizeformula( function will automatically switch to a multi-line format.

    zlog labelizeformula({listfiles(info("desktopfolder"))})

Depending on the contents of your desktop folder, the output will look something like this:

    [Test] === listfiles(info("desktopfolder")) ============
    [Test] AMW46_Registration.pdf
    [Test] Cataract Simulations.sox
    [Test] Chevy Chase Flag Crosswalk.napkin
    [Test] Colorado Boulevard Flag Crosswalk.napkin
    [Test] Golden Gate Bridge Photo.jpg
    [Test] Mount Fuji in Winter.jpg
    [Test] Personnel Roster.pandb
    [Test] Real Estate Listings.pandb
    [Test] US Airports.pandb
    [Test] === END OF listfiles(info("desktopfolder")) ============

#### Displaying Info Functions in the Log

The results of the info( function can be displayed using the labelizeformula( function, but this is so common that Panorama has a special function to make this easier, labelizeinfo(. For example, to display the name of the current database, use this code:

    zlog labelizeinfo("databasename")

The result will look something like this:

    [Test] info("databasename") --> US Airports

If the function result contains more than one line, a different default pattern is used. For example, the code:

    zlog labelizeinfo("files")

will put something like this into the log:

    [Test] === info("files") ============
    [Test] Contacts
    [Test] Orders
    [Test] Products
    [Test] === END OF info("files") ============

#### Displaying a Dictionary in the Log

If you need to display a dictionary (see Data Dictionaries), use the zlogdictionary statement. For example, the code:

    zlogdictionary windowinfo("","ALL")

will put something like this into the log:

    [Test] == DICTIONARY windowinfo("","ALL") ============
    [Test] DATABASE="Formula Workshop"
    [Test] HORIZONTALSCROLLBAR=0
    [Test] VARIABLES="
    [Test] theWizardFormula
    [Test] resultFormat
    [Test] theWizardFormulaResult
    [Test] theWizardFormulaError
    [Test] theFormulaDatabase"
    [Test] OPTIONS="NoToolBar NoHorzScroll NoVertScroll"
    [Test] VERTICALSCROLLBAR=0
    [Test] TOOLBAR=0
    [Test] TYPE="Form"
    [Test] LASTTIMEINFRONT=3673970363
    [Test] NAME="Formula Workshop"
    [Test] PROCEDURE=""
    [Test] FORM="Formula"
    [Test] === END OF DICTIONARY windowinfo("","ALL") ============

The parameter must be just a dictionary, you cannot mix in anything else.

#### Extra Logging Code

It’s rarely necessary, but if you need to run additional code only when logging is enabled, you can use the zlogging( function to check whether logging is currently enabled. For example if for some reason you wanted to display a message only when logging is enabled, you could do that.

    if zlogging()
        message "Logging is enabled"
    endif

Remember, you don’t need to use zlogging( when you are using the zlog and zlogdictionary statements, these statements already check whether logging is enabled.

#### Code Instrumentation in Anonymous Procedures

The zlog statement only works in code within a named procedure (see Procedures to learn about named vs. anonymous procedures). Use the zlogalways statement if you need output log information from code in an execute, starttimer, or other anonymous procedure. See the zlogalways statement for full details on how to do this.

#### Hard Coding Coverage

Usually instrumentation coverage is enabled or disabled in the Instrumentation panel as described in Customizing Debug Instrumentation Coverage, but the zlogcoverage statement allows coverage to be controlled by the program itself. This statement has one parameter, which may be always, never or normal (it can also be `""`, which is the same as normal).

    zlog "This will appear if coverage is enabled in Instrumentation panel."
    zlogcoverage "always"
    zlog "This will always appear."
    zlogcoverage "never"
    zlog "This will never appear."
    zlogcoverage "normal"
    zlog "Again, will appear if coverage for this procedure is enabled in Instrumentation panel."

Note that coverage is only enabled for this exact procedure, not for any subroutines called by this procedure.

See Also

- Client/Server Debug Instrumentation -- using instrumentation with Panorama X server and clients.
- Crash Proof Debug Instrumentation Monitoring -- real time crash-proof instrumentation monitoring
- Customizing Debug Instrumentation Coverage -- specifying what code is being debugged at the moment.
- Debug Instrumentation -- conditional logging of the internal state of Panorama program code.
- Debug Instrumentation Log Window -- dynamically monitor debug instrumentation output as your program runs.
- Debug Instrumentation Monitoring using an External Program -- monitoring debug instrumentation with an external program (Terminal.app, BBEdit.app).
- Debug Instrumentation Text File -- configuring and accessing the debug instrumentation log (text) file.
- info("runningunderterminal") -- returns the name of the terminal program if Panorama was launched under one, otherwise it returns empty text.
- labelize( -- returns the value of a field or variable along with a label. This saves typing when you need to display fields or variables when logging and debugging.
- labelizeformula( -- returns the value of a formula along with the formula itself as a label.
- labelizeinfo( -- returns the value of an info( function, along with the function itself as a label.
- labelizepattern( -- formats a text value using a label and a pattern.
- Recording Code Triggers in Debug Instrumentation -- the code triggers option automatically tracks whenever any code is triggered, whether from a menu, a button, or implicitly (for example when data is entered).
- Recording Control Flow in Debug Instrumentation -- configure debug instrumentation to automatically log when control flow is non-linear, for example a call, return, goto, etc.
- setzlog -- turns instrumentation coverage on or off for a specific procedure (or all procedures within a database).
- zlog -- outputs a message to the instrumentation log (if instrumentation is enabled).
- zlogalways -- unconditionally outputs a message to the instrumentation log.
- zlogcoverage -- allows instrumentation coverage to be turned on or off within a procedure.
- zlogdictionary -- outputs a data dictionary to the instrumentation log (if instrumentation is enabled).
- zlogging( -- returns true if zlogging is enabled for the current database and procedure, otherwise false.

History

Version | Status | Notes
10.2 | New | New in this version.