http://qs1969.pair.com?node_id=114485
Category: Miscellaneous
Author/Contact Info Michael Joyce, coolmichael
Description: This module uses the DBI and DBD::CSV to handle all the file locking necessary for a simple logging facility.

I needed something like this for some of my CGI scripts. Appending to a table was a problem, as the file would sometimes loose some. I couldn't get flock to work, wanted to try writing object oriented perl.

Sample useage:

my $log=Logger->new("logfile", "/home/michael/logs"); open FILE, "myfile" or { $log->logger("something bad happened: $!"); die; }
I found it useful to have two log files open at the same time, one for fatal errors and one for warnings generated by bad input, or other non-fatal (recoverable) problems.

Please comment.

#!perl -w

# Log.pm -- a simple logger which uses DBI and DBD::CSV to
# handle all the file locking. All log entries are kept in
# a text file, to make reading it much easier than if they
# had been put into a real database.
# copyright September 23, 2001 by Michael S. Joyce
# michaeljoyce@telus.net
# This code may be used and distributed under the same terms
# as Perl.
# TODO:
# add an option to make database connections
# happen with each call to logger(), instead of
# maintaining the connection for the lifetime of
# the program

use DBI;
use strict;

package Logger;

use vars qw($tbldefault $dbdefault);

# default name for the log file
$tbldefault="errlog";

# default directory for the log files
$dbdefault='E:\\\\log';

# check to see if a log file exists,
# and create it if it doesn't.
sub tblexists {
  my $dbh = shift;
  my $tblname = shift;

# $dbh->tables() is a new method in DBI version 1.09
  unless (scalar grep {$_ eq $tblname} $dbh->tables())
  {
    my $crtstr=<<ENDQ;
      CREATE TABLE $tblname(
        date      CHAR(24),
        filename  CHAR(24),
        lineno    CHAR(8),
        message   VARCHAR(256)
       )
ENDQ
    $dbh->do($crtstr) or die "creating table: $!\n$dbh->errstr";
  }
}

# initialize the logger
# put a statement handle and database handle
# into self, as well as other potentially useful information
sub initialize {
  my $self = shift;
  
  $self->{'tblname'}=shift || $tbldefault;
  $self->{'dbname'}=shift || $dbdefault;
  $self->{'constr'}="DBI:CSV:f_dir=$self->{'dbname'}";

  my $dbh = DBI->connect($self->{'constr'})
    or die "No Database Connection Made: $!\n $DBI::errstr\n";
  $self->{'dbhandle'}=$dbh;

  tblexists($dbh, $self->{'tblname'});

  my $instr="INSERT INTO $self->{'tblname'} VALUES (?,?,?,?)";
  my $sth=$dbh->prepare($instr);
  $self->{'sthandle'}=$sth;
}

# simple constructor
# most of the work is done in initialize()
sub new {
  my $class = shift;
  my $self = {};
  bless $self, $class;
  $self->initialize(@_);
  return $self;
}

# member function to log a message
sub logger {
  my $self = shift;
  my $sth = $self->{'sthandle'};
  my $time=localtime();
  my $message = shift;

  my ($package, $filename, $line) = caller;
  
  $sth->execute($time, $filename, "line $line", $message);
}

# Destructor to cleanup database connections
sub DESTROY {
  my $self = shift;
  my $dbh = $self->{'dbhandle'};
  $dbh->disconnect();
}

1;
Replies are listed 'Best First'.
Re: Perl module to handle simple logging
by RhetTbull (Curate) on Sep 25, 2001 at 17:50 UTC
    This isn't a comment about your code and might be considered a nitpick but I think it's important none-the-less. You include a copyright statement with your code "# copyright September 23, 2001 by Michael S. Joyce " which is certainly OK but you don't tell us what we can and can't do with the code. E.g. is it ok to use in my own code? I know that by posting it here it can be reasonably assumed that the code is freely available to do whatever I want with but that wouldn't hold up in court and as a result I wouldn't be allowed to use this snippet in production code. This raises the bigger question about who owns the code posted here. I would assume that all authors retain the copyright but perhaps the Monastery does? Some snippets and code submissions do include a disclaimer or copyright notice but most do not. Would it be prudent to add a feature that would include a default copyright statement with code (unless the author provided a different one?) (I would assume the default would be the same license as perl itself). Maybe it could even be a user option..."include link to this copyright statement with all my code"?
      Would be nice to have this level of protection, but I think this could make short snippets of code a lot more unweildy if we're putting a full copyright in?
        After some discussion of this issue a while back my response was to simply include the following statement on my homenode.

        Unless otherwise noted, all code authored by myself ("RhetTbull") on perlmonks.org is free software which you can redistribute and/or modify under the same terms as Perl itself.

        Yes, it's probably unnecessary but I figure better safe than sorry. See tilly's horror story to see why I'm paranoid.

Re: Perl module to handle simple logging
by perrin (Chancellor) on Sep 25, 2001 at 18:47 UTC
    FYI, there are a number of full-featured logging modules already available on CPAN.