CleanCode Perl Libraries
Multi-Lingual Library Maintainability
available: Perl available: Java available: JavaScript not available: Certified
Class
not available: Testable
Class
not available: Standalone
Mode
available: Diagnostic
Enabled

NAME

Data::Diagnostic - Provides configurable diagnostic logging of several message types to several output channels.

SYNOPSIS

        # initialize
        use Data::Diagnostic;
        Data::Diagnostic->init(...);
        $diag = Data::Diagnostic->new();
        
        # for specific trails
        $diag->enter();  # at top of a method
        $diag->leave();  # at bottom of a method
        $diag->create(); # in a constructor
        
        # for general info
        $diag->print("checking $itemName");
        $diag->warnPrint("field '$itemName' not in library");
        $diag->errPrint("fatal error: $errCode");
        
        # for tabular displays
        $diag->setTableName("My Contact List");
        $diag->setColumnNames({name=>1,city=>2,phone=>undef,fax=>undef});
        $diag->print(\%records);
        
        # for wrap-up
        $diag->print(Data::Diagnostic->getWarnCount() . " warning(s)");
        $diag->print(Data::Diagnostic->getErrCount() . " error(s)");
        Data::Diagnostic->exit();

In a nutshell:

REQUIRES

Perl5.005, Data::Handy, Log::Writer, Data::InputOptions, Data::DumperAbbrev

DESCRIPTION

Instrumenting Your Code

Each class that you wish to use diagnostics must have one or more Diagnostic objects-- each with its own diagnostic level--and be instrumented appropriately. What gets output and where it goes (that is, which specific diagnostics and which channels) is configurable from either the command-line or from a configuration file (or both), using an InputOptions object.

Quick Setup

This section discusses how to quickly convert an existing module to use diagnostics; the following sections provide much more detail.

Create one or more diagnostic objects per module:

        $diag = Diagnostic->new();

Change your STDERR print statements to errPrint or warnPrint method calls...

        print STDERR $msg => $diag->errPrint($msg);

...and your regular print statements to print method calls...

        print $msg if $DEBUG (or similar) => $diag->print($msg);

Initialize the Diagnostic package in your main program (more detail on how to construct a parameter list follows the step-by-step section):

        Data::Diagnostic->init(); # for errors and warnings only
        --OR--
        Data::Diagnostic->init(__PACKAGE__); # for diags for this package
        --OR--
        Data::Diagnostic->init("pkg1","pkg2",...); # for diags for listed packages
        --OR--
        Data::Diagnostic->init("pkg1",["v1",...]); # for variants of pkg1 diag
        --OR--
        Data::Diagnostic->init($settings); # for more advanced uses

Finally, to avoid a warning from the diagnostic object itself, always define your package's VERSION variable.

Details on Quick Setup

1. Create a Diagnostic object

        diag = new Diagnostic();

Note that you only need one Diagnostic object per class (not per instance), so it is recommended to assign it to a class variable. You may actually want more than one Diagnostic object to be able to report on different things independently, but even so, they should still all be class objects. Use the variant constructor to create more than one:

        diag = new Diagnostic(variation);

2. Hook up code tracing

Instrument your code by placing enter and leave method calls near the top and bottom, respectively, of the methods (and constructors) to be traced. Typically, use the no-argument form in constructors (since they do not technically have a method name). These methods will output ENTER and LEAVE labels to the currently selected output channels. In addition, they will indent or outdent subsequent messages to show the call sequence nested. The nesting prefix is configurable via the TRACE_INDENT property.

3. Hook up object creation diagnostics

Instrument your code by placing create method calls near the top of each constructor (or bottom--just be consistent). This method will output a message indicating creating an instance of the owning class to the currently selected output channels.

4. Hook up general diagnostics

Instrument your code by placing print method calls as needed to display static messages, variable values, etc. This method will output an arbitrary message to the currently selected output channels. You may pass a string or an arbitrary object.

5. Instrument warnings and errors

Use warnPrint and errPrint where appropriate. This is an invaluable tool for locating system problems. Say, for example, a program serves web pages. It is not always appropriate to indicate file system errors to the user nor to print to STDERR, but using errPrint can also capture the message to a log file. These methods will output an arbitrary message preceded with either a WARNING: or ERROR: label.

6. Register a version for your module

Assign a version number to your class's standard VERSION variable. (Unlike the Java version, we don't use a getVersion method since CPAN automated tools require the VERSION assignment to be inline.)

7. Create or modify configuration file

You are not required to use a configuration file--for simple situations it is not necessary; see discussion further on about this. If you're interested in diagnostics from multiple modules, or multiple diagnostics within a single module, then you'll probably want a configuration file.

Create a configuration file as described in the API for the InputOptions class. Add properties used by Diagnostic objects as listed below. Also, add className_DIAG properties for each class you have instrumented. See the discussion on Diagnostic Selection for further details.

8. Initialize diagnostics and settings

In your program initialization, invoke the init method with a variety of parameter choices, as shown in the introduction to this section above.

Output Channels

All of the possible messages can go to any, all, or none of:

The selection of channels is made by the OUTPUT_DIAG and OUTPUT_ERR properties from the InputOptions object. (See also: the table of InputOptions for this class and the "CLASS VARIABLES" section for the specific constants to use.)

Message Types

Each message type is shown in the table below along with the method used to generate it. The remaining two columns are explained following the table.

Message type Method Switch
warning warnPrint WARNINGS_ON
error errPrint always output
general print className_DIAG
object creation create CREATE_DIAG or className_DIAG
method trace enter and leave TRACE_DIAG or className_DIAG
class version printVersion VERSION_DIAG or className_DIAG
server environment -- ENV_DIAG

Messages will print only when one of the switches shown is active in the system diagnostic level mask. Note that several messages have more than one switch; those messages will print when either switch is active. Thus, one has the option of seeing, for example, "create" messages for all classes by activating the CREATE_DIAG switch, or of seeing all messages for one class by activating its class switch. The selection of active diagnostic switches is controlled by the DIAG_LEVEL property as explained below.

Diagnostic Selection

The key to seeing just what you want to see in the diagnostic output is the diagnostic selection mask. First, in the configuration file (or from the command-line) specify an InputOptions property for DIAG_LEVEL. Each bit of DIAG_LEVEL is an on/off switch. Therefore, it is best to use a hexadecimal, rather than decimal, representation where it is clear which bits are active. Example:

  DIAG_LEVEL = 0x04000fff

Next, define the diagnostic levels for the predefined Diagnostic switches. Example:

  VERSION_DIAG    = 0x40000000
  CREATE_DIAG     = 0x20000000
  TRACE_DIAG      = 0x10000000

Then, define the diagnostic levels for any library classes you are using. These will be named className_DIAG. Of course, you only need to do this if you care about seeing diagnostics for them. Any classes you do not explicitly define will get a default level of 1. Therefore, it is best not to use the 1 bit for anything else, as you will then get a lot of "noise". Example:

  INPUTOPTIONS_DIAG     = 0x08000000 // for InputOptions class
  DIAGNOSTIC_DIAG       = 0x04000000 // for Diagnostic class
  URLCONNECTIONMGR_DIAG = 0x00800000 // for UrlConnectionMgr class

Finally, define the diagnostic levels for any of your classes you have instrumented. As shown above, the diagnostic level properties are named with all capitals and a _DIAG suffix. So, if you have a class named SomeClass its corresponding diagnostic level in the configuration file will be SOMECLASS_DIAG. Generally, each level should be a single bit, but this is not mandated. You could, for example, overlap bits to create a shorthand for seeing a group of certain diagnostics.

If you have more than one Diagnostic object in your module (created with one of the variant constructors), you need to define a diagnostic level for each one using the form className_variation__DIAG. So if you created one with a variant "A" in module SomeClass, then you'll also define SOMECLASS_A_DIAG.

InputOptions properties used by this class

InputOptions properties used by this class
Property Type Default Specifies...
OUTPUT_DIAG int OUTPUT_DIAG_LOGFILE output channels for regular (non-error and non-warning) messages
OUTPUT_ERR int OUTPUT_DIAG_LOGFILE and OUTPUT_DIAG_STDERR output channels for error and warning messages
DIAG_LEVEL int 0 active diag levels for regular messages
WARNINGS_ON boolean true display or suppress warning messages
TRACE_INDENT String 2 spaces characters to indent/outdent at enter or leave calls
LOG_DIR String log directory in which to create log files
LOG_DIAG_NAME String errors base name of the error (and warning) log file
LOG_ERR_NAME String diagnostics base name of the diagnostic (non-error, non-warning) log file
CREATE_DIAG int 1 diag used to show all object creations
TRACE_DIAG int 1 diag used to show all trace messages
VERSION_DIAG int 1 diag used to show all class versions
ENV_DIAG int 1 diag used to show all system environment variables

Initialization Buffering

In order to provide the most robust and flexible diagnostic facility, the Diagnostic class was designed so that objects may be created and used before the class initialization -- and even the object initialization(!) -- has been performed. The initialization is typically performed by passing an InputOptions object to init (see below). But you may not have the arguments for these methods available without running some other code first. So until the initialization is done, the Diagnostic module quietly collects all messages in a queue, retaining all parameters of a message so that the diagnostic filters can be processed later.

The initialization process sets a variety of parameters from the system configuration, including specifying the diagnostic mask, the diagnostic levels for each module, and so forth. It also finishes initializing each Diagnostic object that has been created since the program started. Once initialization has completed, the message queue is processed, sending each message to the appropriate channel for the appropriate levels (or to the bit bucket if the message is not selected). The initialization buffering is then disabled; any subsequent Diagnostic method calls are passed through immediately. (Note that the secondary buffering controlled by setWebChannelBuffer is completely independent; it may or may not buffer depending on your setting.)

In the interests of reasonable behavior, this initialization buffering has some additional flexibility. First, if you do not call init, and a library module prints a diagnostic warning or error message, reasonable behavior dictates that the message should appear on STDERR, as described in the next section. So by the time your program ends, if you have not called init, any collected error/warning messages will be output to STDERR automatically. Second, if there is a lot of diagnostic traffic, it would not be nice to collect megabytes of messages which are never used. So after 100 messages have been collected, init is automatically invoked in the "casual user" mode, displays any collected errors/warnings, empties the buffer, and thus any subsequent errors/warnings are displayed immediately.

Using Diagnostics Without a Configuration File

Normal program sequence suggests that init be called, passing it an InputOptions object, before creating any Diagnostic objects, since configuration file settings are used by Diagnostic objects. But the casual user of my libraries, and perhaps of your libraries, will create objects which do create Diagnostic objects without any notion of a configuration file or of using InputOptions. That's okay; it's fine if init is never called, or is called with an InputOptions object which uses command-line parameters but no configuration file.

If a configuration file is not used, the following properties are adjusted for more convenient use:

OUTPUT_DIAG is initialized to OUTPUT_DIAG_STDOUT

OUTPUT_ERR is initialized to OUTPUT_DIAG_STDERR

That is, log file output is disabled, and if there are any errors or warnings to be printed along the way, they will simply be output to STDERR, rather than quietly go into a log file which the user/developer is not even aware of. Other diagnostic messages may or may not be displayed, depending upon your invocation of init.

Working With InputOptions Objects

To get started with creating your own InputOptions object, define a level for each Diagnostic object you're interested in, and set the diagnostic mask (DIAG_LEVEL) to that level. In the example, "2" is used. Any level will do as long as it is not the default level for unassigned diagnostics (the value 1). For a class named SomeClass, you would need only this:

        my $diagOutputOn = [ "SOMECLASS_DIAG=2", "DIAG_LEVEL=2" ];
        my $settings = Data::InputOptions->new($diagOutputOn);
        Diagnostic->init($settings);

Note that if that is all you wish to do, it can be done more simply with

        Diagnostic->init("SomeClass");

But let's explore further. Which output channels are selected? That is, what are the settings of the OUTPUT_DIAG and OUTPUT_ERR properties? Recall that normally the former would be just to the log file, while the latter would be STDERR plus the log file. But, as described in the discussion above of running without a configuration file, these will be automatically adjusted to point only to STDOUT and STDERR, respectively. Hence, you get to see your output just as if you'd used print anything and print STDERR anything... statements.

To tailor where the output goes, let's add to the InputOptions object. Here we show regular and error output explicitly set (note that for clarity I have left out package names on the variables in the Diagnostic namespace).

        my $diagOutputOn = [
                "OUTPUT_DIAG=".$OUTPUT_DIAG_STDOUT,
                "OUTPUT_ERR=".($OUTPUT_DIAG_STDERR|$OUTPUT_DIAG_LOGFILE),
                "SOMECLASS_DIAG=2",
                "VERSION_DIAG=4",
                "DIAG_LEVEL=6"
        ];

Several points to note:

We have included a line for VERSION_DIAG above, which specifies that the version of each instrumented and loaded class will be shown as a diagnostic message.

The DIAG_LEVEL is a bit-wise combination of the xxx_DIAG bit flags.

The OUTPUT_DIAG and OUTPUT_ERR properties are bitwise combinations of the valid output channel values.

Web Channel Buffering

Diagnostic output to the STDERR channel and to the log file channel is sent to these destinations as encountered. The STDOUT channel, however, may either be used for command line processing or for CGI output for a web server. Diagnostic therefore provides web channel buffering which you must enable if you are generating CGI output. Otherwise, you may have diagnostic output even before your HTTP headers, which will generate a server error. Almost as bad, you might get diagnostic output interspersed with your regular generated output. Use the setWebChannelBuffer method with a true value to enable it. From that point on, all output destined for the web channel will be queued until such time you explicitly ask for it via the output method. This allows you to insert the diagnostic output wherever you'd like in your generated web page. The output method provides some convenience features which depend on the input you feed it; see the method description for more detail. Once you call this method, the message queue is emptied, and will then start collecting subsequent Diagnostic output, if any, from scratch.

CLASS VARIABLES

VERSION

Current version of this class.

OUTPUT_DIAG_STDOUT

A bit switch directing output to STDOUT formatted as plain text. This is a possible value for the OUTPUT_DIAG and OUTPUT_ERR properties. Included in the default OUTPUT_DIAG mask if a configuration file is not used.

OUTPUT_DIAG_STDERR

A bit switch directing output to STDERR as plain text. This is a possible value for the OUTPUT_DIAG and OUTPUT_ERR properties. Included in the default OUTPUT_ERR mask.

OUTPUT_DIAG_WEBPAGE

A bit switch directing output to STDOUT formatted as HTML. This is a possible value for the OUTPUT_DIAG and OUTPUT_ERR properties.

OUTPUT_DIAG_LOGFILE

A bit switch directing output to a logfile as plain text. This is a possible value for the OUTPUT_DIAG and OUTPUT_ERR properties. Included in the default OUTPUT_DIAG mask and OUTPUT_ERR mask if a configuration file is used.

CONSTRUCTOR

new

PACKAGE->new()

PACKAGE->new(variation)

Creates a Diagnostic object. With no argument, uses the standard level for the specified class, i.e. className_DIAG. With an argument, uses a variant of the standard level for the specified class, i.e. className_variation_DIAG. In either case, the level is retrieved from the InputOptions property list which was either specified via the init call or built internally. If a property for this class is not defined, a default value of 1 is used.

Parameters:

variation - optional; string; a label variation for the class diagnostic.

Returns:

a newly created object

METHODS

init

PKG->init()

PKG->init(1)

PKG->init(className, variant-array-ref)

PKG->init(className, ...)

PKG->init(InputOptions)

This class method should be called during your program's initialization to initialize the Diagnostic class. For casual use, at least use the no-argument form of this method; otherwise, errors and warnings may be delayed until your program finishes execution. See the "Description" for further details.

The key to using Diagnostic objects is this init method. It was designed to allow a variety of parameter choices to meet varying needs.

You may easily enable diagnostics for all classes, for a specific list of classes, for specific variations within a single class, or via an InputOptions object, you may fine-tune for exactly what you need. These are the possible invocations:

If you don't provide an InputOptions object, as in the last case above, init constructs one internally. That is, it creates a structure which emulates a configuration file and passes this to InputOptions::new. This structure is simply a list of strings representing configuration properties.

Parameters:

className - string representing the name of a class

variant-array-ref - reference to an array of strings, each representing a Diagnostic variation as passed in to the Diagnostic constructor.

InputOptions - object of class Data::InputOptions

reset

PACKAGE->reset()

Resets diagnostics to initial conditions, allowing init() to be called again. Note that this should only be called before an init() or after an exit().

setPendingLimit

PACKAGE->setPendingLimit(limit)

Changes the pending limit of messages before the Diagnostic system is auto-initialized. The default value is 100. If the number of messages already buffered is larger than this new pending limit, the Diagnostic system is immediately initialized.

Parameters:

limit - integer; limit of messages buffered before automatically initializing Diagnostic class.

getClassName

OBJ->getClassName()

Returns the name of the owning class.

Returns:

string; the name of the owning class

getDiagName

OBJ->getDiagName()

Returns the name of the diagnostic for the class which created it. The name has the form className_DIAG or className_variation_DIAG, depending on the constructor used.

Returns:

string; the name of the owning class diagnostic property

getWarnCount

PACKAGE->getWarnCount()

Returns number of warnings observed. This is the number of warnings which occurred, whether or not warnings are displayed.

Returns:

int; number of warnings observed

getErrCount

PACKAGE->getErrCount()

Return number of errors observed.

Returns:

number of errors observed

getWebPageEnabled

PACKAGE->getWebPageEnabled()

Returns boolean indicating whether either the standard or the error channels have specified the web page channel for output from the configuration settings. This may be used, for example, to conditionally provide a header and footer for diagnostic output in a generated web page. Note that this will not indicate whether any diagnostic output is actually generated; it simply indicates that output, if generated, will be sent to the web page channel.

Returns:

Boolean indicating whether the web page channel has been activated.

setWebChannelBuffer

PACKAGE->setWebChannelBuffer(boolValue)

Activates or deactivates the web channel buffer. This allows you to control the output on the web channel, so you may insert the diagnostic output in your generated web page wherever you wish using the output method. Note that this needs to be called before the init method. See the "Description" for further details.

Parameters:

boolValue - boolean; selects on or off state.

output

PACKAGE->output()

PACKAGE->output(output)

Retrieves the collected web channel output when web channel buffering is enabled. When using web channel output, you may choose to have it buffered or not. When not buffered, output occurs to the channel when it is generated. But that may not be desirable if, for example, you have not set up your HTTP headers. So when you do enable web channel buffering, this method is the way you access that stored output. There are two methods to retrieve the data; the no-argument signature simply returns it as a string for you to place where you please. For convenience, you may alternatively pass in your generated web page; this method will insert the diagnostic text into it, returning the updated generated web page. The diagnostic text is inserted at the spot where a place holder is found in your text (the string "<DIAG_OUTPUT>"). If no place holder is found, and the text is HTML, then the diagnostic text is inserted just before the <b>/body</b> tag. If it is not HTML, then the diagnostic text is just tacked onto the end of your output.

Parameters:

webPage - optional; string; directs the method to attach the diagnostic text to this string as specified above, and return the revised text.

Returns:

Diagnostic text, or revised output including diagnostic text, as described above.

flush

OBJ->flush()

Flush all active log streams.

exit

OBJ->exit()

Cleanup routine to close all active log streams.

isActive

OBJ->isActive()

Indicates whether the Diagnostic is selected by the current diagnostic level. That is, the Diagnostic was created to respond to a particular diagnostic switch. The global DIAG_LEVEL property specifies all the switches which are active for this program invocation. If this Diagnostic's level is one of the active switches, true is returned.

Returns:

boolean indicating whether Diagnostic is selected

printVersion

PACKAGE->printVersion(className, showAlways)

A class method, this prints the version number of the specified class. This method is invoked automatically by the Diagnostic class itself so one does not normally need to call it.

Parameters:

className - string; name of calling class

showAlways - boolean; displays version unconditionally if true; otherwise displays it only once per className, regardless of how many times called with the same className.

create

OBJ->create()

OBJ->create(supplementalMsg)

PACKAGE->create(level)

PACKAGE->create(level, supplementalMsg)

Prints a message indicating creation of an object of the owning class. This method will output a message not only for the diagnostic level of the owning class but also for the CREATE_DIAG diagnostic level. Thus, one has the option of seeing all create messages for all classes by switching on the CREATE_DIAG diagnostic level, or of seeing all messages for one (or more) particular class by switching on its diagnostic level.

If a supplementalMsg parameter is supplied, it will be tacked on to the standard message.

This method is also available as a class method for convenience. If used, though, you must supply the level since there's no object in which to look it up.

Parameters:

level - diagnostic level at which to output messages

supplementalMsg - optional; string; a supplemental message to tack on to the standard message

enter

OBJ->enter()

OBJ->enter(supplementalMsg)

PACKAGE->enter(level)

PACKAGE->enter(level, supplementalMsg)

Prints a message indicating entering a method of the owning class. This method will output a message not only for the diagnostic level of the owning class but also for the TRACE_DIAG diagnostic level. Thus, one has the option of seeing all enter/leave messages for all classes by switching on the TRACE_DIAG diagnostic level, or of seeing all messages for one (or more) particular class by switching on its diagnostic level.

A side effect of this method is that the indentation of subsequent messages will be increased to indicate nested method calls. Calls to enter and leave should be balanced to properly show indentation.

If a supplementalMsg parameter is supplied, it will be tacked on to the standard message.

This method is also available as a class method for convenience. If used, though, you must supply the level since there's no object in which to look it up.

Parameters:

level - diagnostic level at which to output messages

supplementalMsg - optional; string; a supplemental message to tack on to the standard message

See Also:

leave method

leave

OBJ->leave()

OBJ->leave(supplementalMsg)

PACKAGE->leave(level)

PACKAGE->leave(level, supplementalMsg)

Prints a message indicating leaving a method of the owning class. This method will output a message not only for the diagnostic level of the owning class but also for the TRACE_DIAG diagnostic level. Thus, one has the option of seeing all enter/leave messages for all classes by switching on the TRACE_DIAG diagnostic level, or of seeing all messages for one (or more) particular class by switching on its diagnostic level.

A side effect of this method is that the indentation of subsequent messages will be decreased to indicate nested method calls. Calls to enter and leave should be balanced to properly show indentation.

If a supplementalMsg parameter is supplied, it will be tacked on to the standard message.

This method is also available as a class method for convenience. If used, though, you must supply the level since there's no object in which to look it up.

Parameters:

level - diagnostic level at which to output messages

supplementalMsg - optional; string; a supplemental message to tack on to the standard message

See Also:

enter method

print

OBJ->print(msg)

PACKAGE->print(level, msg)

Output an arbitrary message at the current diagnostic level. If this object's diagnostic level is active (per the DIAG_LEVEL property) the message will be output to the currently selected output channels.

The msg may be either a string or an arbitrary data structure or reference. If it's an object and the object has a toString method, the output of that method will be printed (a la Java). If it's a hash reference, the hash will be output in a concise format for stderr and stdout, or as a formatted table in HTML via a Data::DumperAbbrev object. (Note that you may adjust the column names for this HTML table via the setColumnNames method.)

This method is also available as a class method for convenience. If used, though, you must supply the level since there's no object in which to look it up.

Parameters:

level - diagnostic level at which to output messages

msg - message to print

warnPrint

OBJ->warnPrint(msg)

PACKAGE->warnPrint(msg)

Output a warning message. If warnings are enabled (via the WARNINGS_ON property), the message will be output to the currently selected output channels.

This method is available as a class or instance method.

Parameters:

msg - message to print

errPrint

OBJ->errPrint(msg)

PACKAGE->errPrint(msg)

Output an error message. The message will be output unconditionally to the currently selected output channels.

This method is available as a class or instance method.

Parameters:

msg - message to print

setColumnNames

OBJ->setColumnNames(colNames)

Provides control over the columns displayed in a tabular display of a hash of hashes when passed to the print method. By default, a hash will be printed as a two-column table, keys in the first column, values in the second. (That is, it will be treated as a hash of values rather than a hash of hashes.) With a hash of hashes, you specify the sub-keys (the keys to the child hashes) which you wish to use as columns. The first column will still be the key; but subsequent columns may be any or all of the sub-keys that you specify here.

The colNames argument is a hash reference itself, where the keys are the names of the columns you wish to display. If you don't need any particular order, the hash values to colNames should each be undef; then the second and subsequent columns will be sorted alphabetically. Otherwise, supply a column number for each column you wish to be in a particular spot, starting with 1. (Again, the first column, column zero, is always the parent key.)

See also setTableName.

Parameters:

colNames - reference to hash specifying all column names to display as keys, and positions of the columns as values (or undef if don't care about position).

setTableName

OBJ->setTableName(name)

Provides control over the displayed title of a hash when passed to the print method. By default, a hash will be printed with no title. When set by this method, the title will span the table as the first row.

See also setColumnNames.

Parameters:

name - string; title for displayed hash

STANDALONE TESTING

You can work with the Diagnostic class in isolation, to get a feel for what it does, using the inner class Data::Diagnostic::Test. Invoke the class as a main program, calling the function main from the command-line as in:

        perl -mData::Diagnostic -e "Data::Diagnostic::Test::main(I<args>)"

The argument choices are:

  main(?LIST) -- displays recommended test sequence
  main(name-test)  -- displays only diagnostics for Diagnostic::Test class
  main(name-diag)  -- displays only diagnostics for Diagnostic class
  main(name-two-classes)  -- displays Diagnostic and Test class diagnostics
  main(name-mult-first)  -- multiple diagnostics in one class; init called first
  main(name-mult-last)  -- multiple diagnostics in one class; init called last
  main(exceptions) -- displays just warnings and errors
  main(no-warnings) -- displays just errors, no warnings
  main(no-errors-with-cmd) -- suppresses errors/warnings, uses cmdline & config
  main(no-cmdline) -- suppress cmdline diags from config file
  main(html) -- displays output as html
  main(html-buffer) -- displays output as html, buffered till called
  main(env) -- displays environment tables
  main(env-html) -- displays environment tables as html
  main(env-html-buffer) -- displays environment tables as html buffered
  main(all) -- displays diagnostics for all classes
  main(version) -- displays version diagnostics for all classes
  main(dup) -- duplicate diagnostic created
  main(this) -- displays diagnostics for this class using InputOptions
  main(no-init) -- no initialization; so displays warnings/errors upon exit
  main(auto-init) -- auto-init; many-message triggers output of warnings/errors
  main(auto-init-adjusted) -- auto-init due to pending limit adjusted
  main(extra-init) -- auto-init followed by manual init--oops!
  main(variant) -- use diag before initializing
  main(mult-default) -- multiple diags, showing just default one
  main(mult-extra) -- multiple diags, showing just extra one
  main(mult-both) -- multiple diags, showing both
  main(mult-abbr) -- multiple diag variants for one class
  main("a=x","b=y",...) -- uses the specified command-line settings
  main("filename","a=x","b=y",...)
    -- reads config file, and overrides with the command-line settings

(Note that if you use a configuration file, to actually see any output you must at least turn on the bit for STDERR with OUTPUT_DIAG=2.)

BUGS

Run through pod2html, this page has a couple validation errors against XTHML 1.0.

AUTHOR

Michael Sorens

VERSION

$Revision: 8 $ $Date: 2006-12-19 21:13:43 -0800 (Tue, 19 Dec 2006) $

SINCE

CleanCode 0.9

SEE ALSO

Data::InputOptions, Log::Writer

POD ERRORS

Hey! The above document had some coding errors, which are explained below:

Around line 670:

=back doesn't take any parameters, but you said =back -- end of CLASS VARIABLES section

Around line 885:

=back doesn't take any parameters, but you said =back -- end of CONSTRUCTOR section

Around line 1899:

=back doesn't take any parameters, but you said =back -- end of METHOD section


CleanCode Perl Libraries Copyright © 2001-2013 Michael Sorens - Revised 2013.06.30 Get CleanCode at SourceForge.net. Fast, secure and Free Open Source software downloads