NAME

Log::Transcript - Log data with log line headers to stderr and to a session transcript with option to email the session transcript.


SYNOPSIS

  use Log::Transcript;
       # no default; undefined if not set by user; if not defined,
       # transcript will not be sent
  $Log::Transcript::notify          = $string;
       # defaults to the basename of $0
  $Log::Transcript::program         = $string;
       # defaults to concatenation of:
       #   . username of real uid of running process
       #   . an at sign ('@')
       #   . fully qualified domainname of current host
  $Log::Transcript::from            = $string;

Subroutines for logging

  logecho( LIST );
  logechos( LIST );
  logdie( LIST );
  log_start_message();
  send_session_transcript( force => SCALAR );
  send_session_transcript();

Subroutines affecting state

       # one or more of these parameters may be given
  set_state(
             notify          => $string,
             from            => $string,
             program         => $string,
             send_transcript => SCALAR,
             logheaders      => $string,
             mailhosts       => $string,
           );
  set_send( SCALAR );
  set_send();

Utility subroutines

  $string = log_timestamp();
  $string = loglinehdr();


DESCRIPTION

Log::Transcript is a collection of subroutines designed to log information to stderr and email the information to a set of user-specified email addresses.

This module assists in logging three types of logged data: informational, advisory and urgent. Informational data is logged to stderr. Advisory data is logged to stderr and is also emailed to a set of addresses specified by the caller upon invocation of a subroutine that indicates the caller is ready to have it sent. Urgent data is logged to stderr and immediately emailed to a set of caller-specified addresses. When urgent data is logged, process execution is immediately halted, and the process exists with an error status.

It is intended that a batch mode process using this package redirect its stderr to append to a file, in effect creating a running log file. A process doing so can log as informational data any data of which a record should be kept, but data which is not required to be seen by a person in any timely manner. The process can log as advisory data any data which a person should review in a timely manner, but data that should not stop the normal flow of execution of the process. Finally, the process can log as urgent data any data which must halt execution and which a person must see in a timely manner. No matter what the category logging, the data will become part of the log file (because of the redirection of stderr). The log file is then a permanent record that can be used for debugging, statistics and other data collection, forensics, etc.

Each line logged has a log line header, a string which is prepended to the text logged. Included in this header is "logging metadata": a timestamp, the name of the host, the name of the process supplying the logged text, and the process ID of the process supplying the logged text. Batch mode processes using this module to append log files can be assured that logging metadata will accompany every line of logged text.

These routines were originally written for the following scenario. A cron job invokes a program, say "myprog", and redirects stdout and stderr to append to a file, say "cron.log". Because logging is done with log line headers, the data lines logged by this module resemble lines in a system log. For informational data, myprog will use logecho() to log the data. For advisory data, myprog will use logechos() to log the advisory data, and send_session_transcript() to email all logged data. For urgent data, and to halt process execution, myprog will use logdie(), which will log the urgent data and send all logged data.

If urgent or advisory data is logged and a valid set of email recipients is specified, the entire body of logged data (informational, advisory, and urgent), called the session transcript, is emailed to the recipients in addition to having been written to stderr. So, a cron job that has redirected stdout and stderr to append a "cron.log" file will collect all logged data from every invocation, and cron.log will become a persistent record of all logged events.

It is possible to log advisory and urgent data without emailing the logged data. To do this, the caller simply omits the step of indicating the set of recipient email addresses.

Or, a process could determine whether it was in batch mode (i.e., whether stdin was associated with a tty) and set the notification addresses if in batch mode and omit that step if in interactive mode.


PACKAGE VARIABLES

$Log::Transcript::hostid

The value of $Log::Transcript::hostid will be identified in the session transcript preface as the hostid of the machine sending the transcript.

Default value: the hostid of the current host

$Log::Transcript::hostfqdn

The value of $Log::Transcript::hostfqdn will be identified in the session transcript preface as the fully qualified host name of the machine sending the transcript.

Default value: the fully qualified host name of the current host

$Log::Transcript::from

The value of $Log::Transcript::from will be used as the email address in the From: header in any transcript emailed. This implements a Reply-To functionality of sorts.

Default value: USER@[HOST.]DOMAIN, where USER is the username associated with the effective UID that owns the running process, and [HOST.]DOMAIN is the fully qualified [hostname.]domainname of the current host.

$Log::Transcript::logheaders

The value of $Log::Transcript::logheaders determines whether "long" or "short" log line headers are used. Valid values are in { "long", "short" }. Values can be assigned without regard to case sensitivity.

Default value: "long"

$Log::Transcript::mailheaders

The value of this variable is expected to be an ordered, comma-delimited list of mail hosts. An SMTP connection is attempted in order, with each of the members of the list, stopping when a connection is established or the end of the list is reached.

Default value: a sensible default list. To see it, execute:

  perldoc -m Log::Transcript

and search for "$mailhosts".

Recommend changing this only when the default list doesn't result in mail being delivered.

$Log::Transcript::notify

The value of $Log::Transcript::notify will be used as the To: header of the session transcript email.

If this variable is not defined by the caller, no transcript will be mailed. It's value can be set directly, or by calling set_state with the "notify" key and a string that evaluates to a valid email address or comma-delimited set thereof:

  set_state( notify => $string );

Default value: none. It is undefined until given a value by the caller.

$Log::Transcript::program

The value of $Log::Transcript::program is taken to be a string representing the name of the calling program. It will be used in each log line header.

Default value: the basename of $0

$Log::Transcript::send_transcript

The value of $Log::Transcript::send_transcript is taken to be a boolean that determines whether the session transcript is sent. (See THE SESSION TRANSCRIPT section for additional information.)

The value of $Log::Transcript::send_transcript can be set:

Default value: false

@Log::Transcript::session_transcript

This array is the session transcript. That is, it contains all logged data. As the purpose of this package is to manage the transcript, it is recommended that this variable is not directly modified without a sufficient understanding of this package. But it can be modified directly, if needed. Applicable quote from "Advanced Perl Programming":

  Perl doesn't have an infatuation with enforced privacy. It would
  prefer that you stayed out of its living room because you weren't
  invited, not because it has a shotgun.


LOG LINE HEADERS

Log line headers are strings containing logging metadata. They are prepended to each line of logged text. There is a "long" form and a "short" form for these headers. A long log line header includes the following:

  YYYY-mm-dd HH:MM:SS HOSTNAME PROGRAM_NAME[PROCESS_ID]

That is, it has a timestamp, a hostname (up to, but excluding the first dot), a program name (the value of $Log::Transcript::program), and the process ID (pid) of the invoking program.

A short log line header includes only:

  PROGRAM_NAME[PROCESS_ID]

By default, long headers are used.

The shorter form can be selected globally by setting the variable $Log::Transcript::logheaders to the (case-insensitive) string "short". The short form may also be globally selected by calling set_state() with:

  logheaders => "short"

Regardless of the global setting in effect indicating the use of long or short log line headers, either form may be selected on a per call basis by giving --long-hdrs or --short-hdrs as the first argument to logecho(), logechos(), or logdie().


THE SESSION TRANSCRIPT

The session transcript is a record of all data (informational, advisory, and urgent) logged during a program's run. It is populated by calls to logecho(), logechos(), and logdie().

The existence of a transcript does not necessarily mean that it will be emailed. A transcript is emailed only if $Log::Transcript::notify is defined and one of the following is true:

See the discussion on the package variables $Log::Transcript::notify and $Log::Transcript::send_transcript for additional information.


EXAMPLE USE OF A TRANSCRIPT

Example of using a transcript:

  #!/usr/bin/perl
  use Log::Transcript;
       # supply program name, notify recipients, and from address
  set_state( notify  => 'developers-list@foo.bar',
             from    => 'developers-list@foo.bar' );
  # alternatively:
  #
  #   $Log::Transcript::notify  = 'developers-list@foo.bar';
  #   $Log::Transcript::from    = 'developers-list@foo.bar';
  log_start_message();
  @filelist = ... ;
       # logecho() does not affect the value of
       # $Log::Transcript::send_transcript
  logecho "got filelist";
  for $file ( @filelist ) {
    if ( $file !~ /$some_regexp/ ) {
           # logechos() sets $Log::Transcript::send_transcript
           # to true 
      logechos "$file doesn't match $some_regexp";
    }
  }
  logecho "sending files";
  for $file ( @filelist ) {
         # logdie causes us to die immediately.  A transcript will be
         # sent if $Log::Transcript::notify is defined
    ... process $file successfully ...
      or logdie "$file: can't send: $!\n";
    logecho "$file sent";
  }
       # $Log::Transcript::notify was defined by the call to
       # set_state(), so this invocation of send_session_transcript()
       # will email a transcript if $Log::Transcript::send_transcript
       # is true.  In this example, that will have happened only if
       # one of the names in the file list didn't match the regexp. 
       # In that case, $Log::Transcript::send_transcript will
       # have been set to true by a call to logechos().  Otherwise, no
       # transcript will be sent.  In any case, the data logged by
       # logecho() will have been logged to stderr (or to wherever
       # you've redirected stderr).  
       #
       # In general if your program does anything to make
       # $Log::Transcript::send_transcript true (except calling
       # logdie() ), you will need a call to send_session_transcript().
  send_session_transcript();


SUBROUTINES

SUBROUTINES FOR LOGGING

logecho()

  logecho( LIST );

logecho() prints its arguments to stderr and appends its arguments to the session transcript.

Its arguments are first concatenated and then split on newlines, to produce text lines to be logged. Each resulting line is prefixed by a log line header and is printed to stderr and also appended to the session transcript.

Note: If you want to override the currently selected log line header format on a per-call basis, use either --short-hdrs or --long-hdrs as the first argument to logecho().

logechos()

  logechos( LIST );

"logechos" is mnemonic for "logecho set". logechos() sets $Log::Transcript::send_transcript to true and then calls logecho() with its arguments.

logdie()

  logdie( LIST );

logdie() sets $Log::Transcript::send_transcript to true, calls logecho() with its arguments, calls send_session_transcript() if $Log::Transcript::notify is defined, and causes the calling program to exit with a value of 255.

log_start_message()

log_start_message() logs the string ">>> started TIMESTAMP", where "TIMESTAMP" is the output of a call to log_timestamp().

send_session_transcript()

  send_session_transcript();
  send_session_transcript( force => SCALAR );

send_session_transcript() is called to send (email) a transcript of all data which has been logged to that point. So it is usually called just before normal termination of the calling program.

If it decides to email the session transcript, it first prepends a preface containing useful information.

send_session_transcript() emails the session transcript if $Log::Transcript::notify is defined and if at least one of the following is true:

A transcript preface identifies the host on which the program was run, the file that was executed, the time the program was invoked, and the real and effective user and group ID's owning the running process.

Typically, you want to call send_session_transcript() after normal processing has completed in your program.

See THE SESSION TRANSCRIPT section for additional information.

SUBROUTINES AFFECTING STATE

set_state()

  set_state( 
             notify          => $string,
             from            => $string,
             program         => $string,
             send_transcript => SCALAR,
             logheaders      => $string,
             mailhosts       => $string,
           );

set_state() sets package variables used by this module.

For each KEY and VALUE specified, VALUE will be used to set the appropriate $Log::Transcript::KEY variable.

At least one KEY and VALUE should be specified.

See section PACKAGE VARIABLES for additional information.

set_send()

  set_send();
  set_send( SCALAR );

set_send() sets the value of $Log::Transcript::send_transcript. If called without arguments or called with a true argument, $Log::Transcript::send_transcript is set to true. If called with a false argument, $Log::Transcript::send_transcript is set to false.

UTILITY SUBROUTINES

Routines used internally that are exported in case they are also useful to the caller.

log_timestamp()

  SCALAR = log_timestamp();

log_timestamp() returns a timestamp of the form:

  YYYY-mm-dd HH:MM:SS

loglinehdr()

  SCALAR = loglinehdr();

If the lowercased value of $Log::Transcript::logheaders equals "long", loglinehdr() returns a string (log line header) of the form:

  YYYY-mm-dd HH:MM:SS HOSTNAME PROGRAM_NAME[PROCESS_ID]

If the lowercased value of $Log::Transcript::logheaders equals "short", loglinehdr() returns a string (log line header) of the form:

  PROGRAM_NAME[PROCESS_ID]


AUTHOR

David Alban