Supply a straight-forward means of tracing program flow through the APS library for debugging and logging purposes. In particular, to support the selective display of helpful information as supplied by compiled macros in library functions, and to categorise and group this information according to message class (type/meaning) and channel (unit representing a functional block). The contents of these messages are entirely at the discretion of the programming team.
This component must be able to...
APS currently defines a TRACE pre-processor macro in apsinternal.h to output freeform printf-formatted text via stdout. The mechanism does not attempt to format the text or to supply additional information (such as function and line location), nor does it distinguish between different classes of messages. It is also not possible to selectively choose which messages are to be displayed.
WINE provides a simple interface for debugging the source on a per-module basis. While most source files designate which channel is to be used by default, it is also possible for one to direct messages to multiple different channels. Clearly this greatly simplifies the task of breaking up the code into manageable debugging segments.
WINE subdivides each channel into four independently-controlled message classes:
WINE defines a plurality of independent message channels. While the channels do not represent different output pathways, they do provide independent controls over which messages are to be output and which are to be ignored. The set of selected channels and classes is generally represented by the key [class]{+-}channel[,...] which must be passed to the -debug-msg argument at run-time. For instance, all Postscript printer driver related messages are grouped under the heading of psdrv. This allows a user to monitor that channel without being bombarded by literally millions of other unrelated messages. Moreover, it is possible to monitor only particular classes of messages such as "err" or "fixme" using the special "all" meta-channel.
e.g. +all,trace-somemodule : enable all messages, except trace class in somemodule
Output is preformatted by the interface such that each message contains:
Although not perfect, the WINE idea appears to be a good starting point for our new design. It main flaw is that the messages which are produced are difficult to read at a glance. They also fail to provide sufficient context information in many cases thereby requiring the user to "grep" and examine the source code in order to further diagnose the problem.
Pursuant to discussions among the APS Development Team with the original design criteria, the following design is proposed as being adequate. It is designed to be both flexible and extensible while remaining lightweight.
Five classes of message have been defined. It is not permitted to use a class for other than it was intended.
The following channels are defined for the moment following the same design concept as in WINE. This list should be updated as new ones are added or old ones are split. Each channel name is followed by a list of default source file associations:
The output format will be managed exclusively by the library to ensure clarity and conformance to the following guidelines.
All messages will be formatted such that...
In addition, user messages should follow the following style guide...
e.g.:
123456789012345678901234567890234567890123456789012345678901234567890123456789 ====== LPR ERROR = LprSetConfigFlags (lprtransport.c:729) =============== Could not make necessary changes to filter configurations due to filesystem error. Returning APS_ACCESS_DENIED. ====== LPR TRACE = ReallyReallyReallyReallyLongNam(lprtransport.c:729) == This message will contain a hard linebreak as its author did not take term inal with into account and the code does not (presently) bother to word-wr ap in a pretty fashion. ====== PRINTCAP MSG = doSomeThing (readwriteprintcap.c:1234) =============== Was unable to create "/etc/printcap" file, returning an error.
Default active channels may be specified when configuring and affect all subsequent compilations. The --enable-debug-trace parameter consists of two parts separated by a colon. If not specified, the default is: msg,warn,error,fixme:all+error+fixme.
The first part of the --enable-debug-trace parameter (before the colon) specifies message classes which are to be enabled. All others will be compiled out. This may be useful for improving performance or before release to market. Classes must be specified using the key [all|default][class[,...]].
The second part specifies which channels are to be enabled by default at run-time. The specification of channels is similar to that of WINE, but reversed: their order matches that of the tokens in debug messages that are produced. Channel specification key: [default][channel{+-}[class][{+-}[class][...]][,...]]. Channels and classes may also be identified here using the "all" keyword.
e.g.:
./configure --enable-debug-trace=msg,warn,error,fixme:all+error+fixme
./configure --enable-debug-trace=default:default
default settings
./configure --enable-debug-trace=all:lpr+all-fixme
enables all lpr messages except those which are fixme's
enables all classes
./configure --enable-debug-trace=default:all+error+fixme,attr-all,lpr+trace
fixme,error,warn,trace
enables all errors and fixme's, except those in attr, and enables lpr
trace messages [and errors and fixme's]
enables classes fixme, error, warn, msg
It is possible to override the default set of enabled channels by defining the environment variable "APSTRACE" in the application's context. The contents of this variable override those of the --default-trace parameter. The variable may be empty, but if it does not exist the configured defaults are preserved.
It is not possible, without recompilation, to enable classes which have been disabled by the --enable-debug-trace configuration parameter.
e.g.:
$ echo "Enabling all debug message channels for lprtransport and related
components"
$ export APSTRACE="lpr+all,transport+all,utils+all"
$ myApplication
$ echo "Disabling all debug message channels"
$ export APSTRACE=""
$ myApplication
The supplied interface is heavily inspired from the WINE sources. The macros have been renamed to avoid name clashing and confusion between the APS and WINE teams due to the apparent functional similarities.
Definitions:
channel : unquoted literal all-lowercase channel identifier
fmt : printf-style format string
... : variable arguments for printf formatting
These macros select and declare channels...
N.B All channels must be declared in a source file before they can be used.
These macros operate on the default channel...
These macros operate on the specified channel (unquoted literal)... Specifying "default" (w/o quotes) causes the action to occur on the default channel.
e.g.:
#include <stdlib.h> #include "apsinternal.h" #include "aps.h" DEBUG_CHANNEL_DEFAULT(attrprov) DEBUG_CHANNEL(attr) int myFunction(const char *name, int value) { TRACE("got name=\"%s\", value=%d", name, value); if (MSG_ON) { /* do some extra work to put out a nice-looking message */ MSG("Object \"%s\" will be removed in %d seconds", getExpiryTimeRemaining(name)); } TRACE("returning TRUE"); return TRUE; } int mySpecialFunction(int foobar) { TRACE_ON_(attr)("got foobar=%d", foobar); FIXME_ON_(attr)("unimplemented"); return 0; }
Corel Corporation
Linux Printing (APS) Development Team
April 2000.