|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T l
Length: 14000 (0x36b0) Types: TextFile Names: »logging.tex«
└─⟦3d0c2be1b⟧ Bits:30001254 ISODE-5.0 Tape └─⟦eba4602b1⟧ »./isode-5.0.tar.Z« └─⟦d3ac74d73⟧ └─⟦this⟧ »isode-5.0/doc/manual/logging.tex«
% run this through LaTeX with the appropriate wrapper \f \chapter {The ISODE Logging Facility}\label{logging} Although not a database mechanisms, per se, the ISODE logging facility is used to manipulate general logs: used by both the ISODE and programs which use the ISODE. \subsection {Data-Structures} There is one primary data-structure, the \verb"LLog": \begin{quote}\index{LLog}\small\begin{verbatim} typedef struct ll_struct { char *ll_file; char *ll_hdr; char *ll_dhdr; int ll_events; #define LLOG_NONE 0 #define LLOG_FATAL 0x01 #define LLOG_EXCEPTIONS 0x02 #define LLOG_NOTICE 0x04 #define LLOG_PDUS 0x08 #define LLOG_TRACE 0x10 #define LLOG_DEBUG 0x20 #define LLOG_ALL 0xff #define LLOG_MASK \ "\020\01FATAL\02EXCEPTIONS\03NOTICE\04PDUS\05TRACE\06DEBUG" int ll_syslog; int ll_msize; int ll_stat; #define LLOGNIL 0x00 #define LLOGCLS 0x01 #define LLOGCRT 0x02 #define LLOGZER 0x04 #define LLOGERR 0x08 #define LLOGTTY 0x10 #define LLOGHDR 0x20 #define LLOGDHR 0x40 int ll_fd; } LLog; \end{verbatim}\end{quote} The elements of this structure are: \begin{describe} \item[\verb"ll\_file":] the name of the file to use for the log, unless an absolute pathname (e.g., \file{/usr/tmp/logfile}) or an anchored pathname (e.g., \file{./logfile}), the name is interpreted relative to the the \verb"logpath" directory in the ISODE tailoring file (see Chapter~\ref{isotailor}); \item[\verb"ll\_hdr":] the logging header which is usually set by one of the utility routines described below; \item[\verb"ll\_hdr"/\verb"ll\_dhdr":] the so-called dynamic header; \item[\verb"ll\_events"/\verb"ll\_syslog":] a bitmask describing the logging events which are interesting to this log, any combination of: \[\begin{tabular}{|l|l|} \hline \multicolumn{1}{|c|}{\bf Value}& \multicolumn{1}{c|}{\bf Meaning}\\ \hline \tt LLOG\_FATAL& fatal errors\\ \tt LLOG\_EXCEPTIONS& exceptional events\\ \tt LLOG\_NOTICE& informational notices\\ \tt LLOG\_PDUS& PDU printing\\ \tt LLOG\_TRACE& program tracing\\ \tt LLOG\_DEBUG& full debugging\\ \hline \end{tabular}\] In addition, the values \verb"LLOG_NONE" by itself refers to no events and \verb"LLOG_ALL" refers to all events being of interest. For those systems with a \man syslog(3) routine, the \verb"ll_syslog" element indicates if the event should be given to \man syslog(8) as well; \item[\verb"ll\_msize":] the maximum size of the log, in units of Kbytes (a non-positive number indicates no limit); \item[\verb"ll\_stat":] assorted switches, any combination of: \[\begin{tabular}{|l|l|} \hline \multicolumn{1}{|c|}{\bf Value}& \multicolumn{1}{c|}{\bf Meaning}\\ \hline \tt LOGCLS& keep log closed, except when writing\\ \tt LOGCRT& create log if ncessary\\ \tt LOGZER& truncate log when limits reached\\ \tt LOGERR& log closed due to (soft) error\\ \tt LOGTTY& also log to stderr\\ \tt LOGHDR& static header allocated\\ \tt LOGDHR& dynamic header allcoated\\ \hline \end{tabular}\] \item[\verb"ll\_fd":] the file-descriptor corresponding to the log. \end{describe} \f \section {Accessing the Log} Typically, logs are not opened or closed directly~---~when an entry is made to a log, the log is opened (if necessary), the entry is written, and (usually) the log is then closed. To open a log associated with a \verb"LLog" structure, the routine \verb"ll_open" is used: \begin{quote}\index{ll\_open}\small\begin{verbatim} int ll_open (lp) LLog *lp; \end{verbatim}\end{quote} The parameter to this routine is: \begin{describe} \item[\verb"lp":] a pointer to a \verb"LLog" structure. \end{describe} The \verb"ll_open" routine will open the log, creating the corresponding file (if necessary). Logs are created mode \verb"0666". If the name of the file to use for the log is ``\verb"-"'', then the \verb"LLOGTTY" option is enabled and no file is actually opened. When determining the actual name of the file to use, a ``\verb"%d"'' in the name will be replaced by the process-id of the program opening the log. On failure, the manifest constant \verb"NOTOK" is returned. Otherwise, the log is opened (and left open, regardless of the presence of the \verb"LLOGCLS" option), and the manifest constant \verb"OK" is returned. To close a log, the routine \verb"ll_close" is used: \begin{quote}\index{ll\_close}\small\begin{verbatim} int ll_close (lp) LLog *lp; \end{verbatim}\end{quote} The parameter to this routine is: \begin{describe} \item[\verb"lp":] a pointer to a \verb"LLog" structure. \end{describe} This routine returns the manifest constant \verb"OK" on success (even if the log was already closed), or \verb"NOTOK" otherwise. \subsection {Timestamps} One of the characteristics of a log is that it contains an informational timestamp for each entry. This timestamp contains the date and time of the log and also two ``header'' strings, a static header and a dynamic header. Normally, these strings are constructed from the name of the program or subsystem using the log. The routine \verb"ll_hdinit" is used to initialize the static header: \begin{quote}\index{ll\_hdinit}\small\begin{verbatim} void ll_hdinit (lp, prefix) LLog *lp; char *prefix; \end{verbatim}\end{quote} The parameters to this routine are: \begin{describe} \item[\verb"lp":] a pointer to a \verb"LLog" structure; and, \item[\verb"prefix":] the name of the program or subsystem using the log. \end{describe} This routine will form a header consisting of the program name, the process-id, and the user-name. The routine \verb"ll_dbinit" is similar, but also enables debugging features: \begin{quote}\index{ll\_dbinit}\small\begin{verbatim} void ll_dbinit (lp, prefix) LLog *lp; char *prefix; \end{verbatim}\end{quote} The parameters to this routine are: \begin{describe} \item[\verb"lp":] a pointer to a \verb"LLog" structure; and, \item[\verb"prefix":] the name of the program or subsystem using the log. \end{describe} This routine will form a header identical to the one formed by \verb"ll_hdinit". It will then set the name of the file associated with the log to be relative to the current working directory. Finally, it turns on all event logging and logging to the user's terminal. \subsection {Making Log Entries} At the lowest level, the \verb"ll_log" routine is used to append an entry to a log: \begin{quote}\index{ll\_log}\small\begin{verbatim} int ll_log (lp, event, what, fmt, args ...) LLog *lp; int event; char *what, *fmt; \end{verbatim} \end{quote} The parameters to this routine are: \begin{describe} \item[\verb"lp":] a pointer to a \verb"LLog" structure; \item[\verb"event":] the event type being logged (e.g., \verb"LLOG_NOTICE"); \item[\verb"what":] some text associated with a system call error (use the manifest constant \verb"NULLCP" if the entry is not associated with an error in a system call); and, \item[\verb"fmt"/\verb"args":] an argument list to \man printf(3s). \end{describe} The entry is only made if the log is enabled (in the \verb"ll_events" field of the \verb"LLog" structure) for the event listed as a parameter to \verb"ll_log". If there was a problem in writing to the log, \verb"ll_log" returns the manifest constant \verb"NOTOK". Otherwise, \verb"OK" is returned. The \verb"ll_log" routine is actually a simple wrapper around the \verb"_ll_log" routine: \begin{quote}\index{\_ll\_log}\small\begin{verbatim} int _ll_log (lp, event, ap) LLog *lp; int event; va_list ap; \end{verbatim} \end{quote} The parameters to this routine are: \begin{describe} \item[\verb"lp":] a pointer to a \verb"LLog" structure; \item[\verb"event":] the event type being logged; and, \item[\verb"ap":] an argument pointer to a variable-length argument list as described in \man varargs(3). \end{describe} It may be necessary to have multi-line log entries. In this case, the first line of the entry should be made with \verb"ll_log". The remaining lines should be made with the \verb"ll_printf" routine: \begin{quote}\index{ll\_printf}\small\begin{verbatim} int ll_printf (lp, fmt, args ...) LLog *lp; char *fmt; \end{verbatim} \end{quote} The parameters to this routine are: \begin{describe} \item[\verb"lp":] a pointer to a \verb"LLog" structure; and, \item[\verb"fmt"/\verb"args ...":] an argument list to \man printf(3s). \end{describe} As with \verb"ll_log", this routine returns either \verb"OK" on success or \verb"NOTOK" on error. Unlink \verb"ll_log" however, \verb"ll_printf" will ignore the setting of the \verb"LLOGCLS" option). As such, when the last line of a multi-line entry has been made, the routine \verb"ll_sync" should always be called to synchronize the log: \begin{quote}\index{ll\_sync}\small\begin{verbatim} int ll_sync (lp) LLog *lp; \end{verbatim} \end{quote} The parameter to this routine is: \begin{describe} \item[\verb"lp":] a pointer to a \verb"LLog" structure. \end{describe} \subsection {More About Making Log Entries} Although the \verb"ll_log" routine has a basic functionality, programmers often prefer a slightly simpler interface. A few macros have been defined for this purpose. The \verb"SLOG" macro is the most commonly used: \begin{quote}\index{SLOG}\small\begin{verbatim} SLOG (lp, event, what, args) \end{verbatim}\end{quote} The parameters to this macro are: \begin{describe} \item[\verb"lp":] a pointer to a \verb"LLog" structure; \item[\verb"event":] the event type being logged; \item[\verb"what":] some text associated with a system call error (use the manifest constant \verb"NULLCP" if the entry is not associated with an error in a system call); and, \item[\verb"args":] a parenthesized argument list for \man printf(3s). \end{describe} The \verb"SLOG" macro compares the event enabled for a log to the event being logged to see if \verb"ll_log" should be called. Since, the need for a \verb"what" parameter is not common in many applications, the \verb"LLOG" macro has been supplied. It is essentially the \verb"SLOG" macro but with a value of \verb"NULLCP" supplied for the \verb"what" parameter of \verb"ll_log": \begin{quote}\index{LLOG}\small\begin{verbatim} LLOG (lp, what, args) \end{verbatim}\end{quote} Further, even though logging is contingent on an event type being enabled, a programmer may still wish that calls to logging package still be conditionally compiled. The \verb"DLOG" macro has been supplied for this purpose. If the pre-processor symbol \verb"DEBUG" is defined, then \verb"DLOG" is equivalent to \verb"LLOG" otherwise it compiles no code whatsoever: \begin{quote}\index{DLOG}\small\begin{verbatim} DLOG (lp, what, args) \end{verbatim}\end{quote} Finally, it may be useful to log PDUs (protocol data units), again under conditional compilation. The \verb"PLOG" macro takes the address of a pretty-printer function generated by \man pepy(1) (see Section~\ref{pepy:pretty} on page~\pageref{pepy:pretty} in \volfour/) along with a presentation element (as described in Chapter~\ref{libpsap} in \volone/) and a brief textual title, and directs the pretty-printer to output to the log: \begin{quote}\index{PLOG}\small\begin{verbatim} PLOG (lp, fnx, pe, text, rw) \end{verbatim}\end{quote} The \verb"rw" parameter is an integer saying wheter the PDU was read from the network (non-zero) or written to the network (zero-valued). As with the \verb"DLOG" macro, if the \verb"DDEBUG" symbol is not defined, then no code is generated. \subsection {Miscellaneous Routines} In order to support some of the more esoteric log capabilities, there are a few utility routines. The routine \verb"ll_preset" evaluates a \man printf(3s) argument list and returns a pointer to static buffer containing the result: \begin{quote}\index{ll\_preset}\small\begin{verbatim} char *ll_preset (fmt, args ...) char *fmt; \end{verbatim} \end{quote} The routine \verb"ll_check" determines if a log has exceeded its size, and if so, if a correction can be made: \begin{quote}\index{ll\_check}\small\begin{verbatim} int ll_check (lp) LLog *lp; \end{verbatim} \end{quote} This routine returns \verb"OK" if the log is within its bounds. \f \section {Use of Logging in Programs} From the perspective of applications programmers, there are three kinds of styles for using the logging package, depending on the kind of program being written. In all three cases, \verb"LLog" structures are usually declared statically in the main module of a program and a pointer to the structure is made available for general use: \begin{quote}\small\begin{verbatim} static LLog _pgm_log = { "myname.log", NULLCP, NULLCP, LLOG_FATAL | LLOG_EXCEPTIONS | LLOG_NOTICE, -1, LLOGCLS | LLOGCRT | LLOGZER, NOTOK }; LLog *pgm_log = &_pgm_log; \end{verbatim}\end{quote} Where the \verb"myname" in ``\verb"myname.log"'' is replaced with the name of the program. Note that in all cases, in order to ensure consistent logging it is {\bf critical\/} that the call to \verb"isodetailor" be the first call made to {\em any \/} of the ISODE routines. For static responders, two routines are called in the initialization code: \begin{quote}\small\begin{verbatim} isodetailor (argv[0], 0); ll_hdinit (pgm_log, argv[0]); \end{verbatim}\end{quote} Later on, after argument parsing, if a debug option is enabled, then \begin{quote}\small\begin{verbatim} ll_dbinit (pgm_log, argv[0]); \end{verbatim}\end{quote} is called. For dynamic responders, a similiar code sequence is used: \begin{quote}\small\begin{verbatim} isodetailor (argv[0], 0); if (debug = isatty (fileno (stderr))) ll_hdinit (pgm_log, argv[0]); else ll_dbinit (pgm_log, argv[0]); \end{verbatim}\end{quote} For user-interfaces, the code is simply: \begin{quote}\small\begin{verbatim} isodetailor (argv[0], 1); ll_hdinit (pgm_log, argv[0]); \end{verbatim}\end{quote} which will ask the tailoing system to read both the standard tailoring file and a user-specific tailoring file and then to initialize the program log.