NAME

    Log::QnD - Quick and dirty logging system

SYNOPSIS

     use Log::QnD;
    
     # create log entry
     my $qnd = Log::QnD->new('./log-file');
    
     # save stuff into the log entry
     $qnd->{'stage'} = 1;
     $qnd->{'tracks'} = [qw{1 4}];
     $qnd->{'coord'} = {x=>1, z=>42};
    
     # undef the log entry or let it go out of scope
     undef $qnd;
    
     # the log entry looks like this:
     # {"stage":1,"tracks":["1","4"],"time":"Tue May 20 17:13:22 2014","coord":{"x":1,"z":42},"entry_id":"7WHHJ"}
    
     # get a log file object
     $log = Log::QnD::LogFile->new($log_path);
    
     # get first entry from log
     $from_log = $log->read_forward();
    
     # get latest entry from log
     $from_log = $log->read_backward();

DESCRIPTION

    Log::QnD is for creating quickly creating log files without a lot of
    setup. All you have to do is create a Log::QnD object with a file path.
    The returned object is a hashref into which you can save any data you
    want, including data nested in arrays and hashrefs. When the object
    goes out of scope its contents are saved to the log as a JSON string.

    PLEASE NOTE: Until this module reaches version 1.0, I might make some
    non-backwards-compatible changes. See Versions notes for such changes.

INSTALLATION

    Log::QnD can be installed with the usual routine:

     perl Makefile.PL
     make
     make test
     make install

Log::QnD

    A Log::QnD object represents a single log entry in a log file. It is
    created by calling Log::QnD->new() with the path to the log file:

     my $qnd = Log::QnD->new('./log-file');

    That command alone is enough to create the log file if necessary and an
    entry into the log. It is not necessary to explicitly save the log
    entry; it will be saved when the Log::QnD object goes out of scope.

    By default, each log entry has two properties when it is created: the
    time the object was created ('time') and a (probably) unique ID
    ('entry_id'). The structure looks like this:

     {
        'time' => 'Mon May 19 19:22:22 2014',
        'entry_id' => 'JNnwk'
     }

    The 'time' field is the time the log entry was created. The 'entry_id'
    field is just a random five-character string. It is not checked for
    uniqueness, it is just probable that there is no other entry in the log
    with the same ID.

    Each log entry is stored as a single line in the log to make it easy to
    parse. Entries are separated by a blank line to make them more
    human-readable. So the entry above and another entry would be stored
    like this:

     {"time":"Mon May 19 19:22:22 2014","entry_id":"JNnwk"}
    
     {"time":"Mon May 19 19:22:23 2014","entry_id":"kjH0c"}

    You can save other values into the hash, including nested hashes and
    arrays:

     $qnd->{'stage'} = 1;
     $qnd->{'tracks'} = [qw{1 4}];
     $qnd->{'coord'} = {x=>1, z=>42};

    which results in a JSON string like this:

     {"stage":1,"tracks":["1","4"],"time":"Tue May 20 17:13:22 2014","coord":{"x":1,"z":42},"entry_id":"7WHHJ"}

 Log::QnD->new($log_file_path)

    Create a new Log::QnD object. The only param for this method is the
    path to the log file. The log file does not need to actually exist yet;
    if necessary it will be created when the QnD object saves itself.

 $qnd->cancel()

    Cancels the automatic save. By default the $qnd object saves to the log
    when it goes out of scope, undeffing it won't cancel the save.
    $qnd->cancel() causes the object to not save when it goes out of scope.

 $qnd->uncancel()

    Sets the log entry object to automatically save when the object goes
    out of scope. By default the object is set to autosave, so uncancel()
    is only useful if you have cancelled the autosave in some way, such as
    with $qnd->cancel().

 $qnd->save()

    Saves the Log::QnD log entry. By default, this method is called when
    the object goes out of scope. If you've used $qnd->cancel() to cancel
    autosave then you can use $qnd->save() to explicitly save the log
    entry.

 $qnd->log_file()

    Returns a Log::QnD::LogFile object. The log entry object does not hold
    on to the log file object, nor does the log file object "know" about
    the entry object.

 $qnd->catch_stderr()

    Closes the existing STDERR, redirects new STDERR to the stderr element
    in the log entry. STDERR is release when the log object goes out of
    scope.

    Currently it's undefined what should or will happen if too log entries
    both try to catch STDERR. Either don't do that or solve this dilemna
    and submit your ideas back to me.

 $qnd->private()

    $qnd->private() is a method inherited from Class::PublicPrivate
    <http://search.cpan.org/~miko/Class-PublicPrivate/>. This method is
    used to store private properties such as the location of the log file.
    Unless you want to tinker around with the log entry's internals you can
    ignore this method.

Log::QnD::LogFile

    A Log::QnD::LogFile object represents the log file to which the log
    entry is saved. The LogFile object does the actual work of saving the
    log entry. It also provides a mechanism for retrieving information from
    the log. If you use Log::QnD in its simplest form by just creating
    Log::QnD objects and allowing them to save themselves when they go out
    of scope then you don't need to explicitly use Log::QnD::LogFile.

 Log::QnD::LogFile->new($log_file_path)

    Create a new Log::QnD::LogFile object. The only param for this method
    is the path to the log file.

 $log->write_entry($string)

    This method writes the log entry to the log file. The log file is
    created if it doesn't already exist.

    The only input for this method is the string to write to the log. The
    string should already be in JSON format and should have no newline.
    write_entry() doesn't do anything about formatting the string, it just
    spits it into the log.

 $log->entry_count()

    This method returns the number of entries in the log file. If the log
    file doesn't exist then this method returns undef.

 $log->read_forward(), $log->read_backward()

    read_forward() and read_backward() each return a single entry from the
    log file. The data is already parsed from JSON. So, for example, the
    following line returns an entry from the log:

     $log->read_forward();

    read_forward() starts with the first entry in the log. Each subsequent
    call to read_forward() returns the next log entry.

    read_backward() starts with the last log entry. Each subsequent call to
    read_backward() returns the next entry back.

    After the latest/earliest entry in the log is returned then these
    methods return undef.

    It is important to know that after the first call to read_forward() or
    read_backward() is made the log file object puts a read lock on the log
    file. That means that log entry objects cannot write to the file until
    the read lock is removed. The read lock is removed when the log file
    object is detroyed, when read_backward() returns undef, or when you
    explicitly call $log->end_read.

    If you call one of these methods while the log object is reading
    through using the other method, then the read will reset and the
    end/beginning of the log file.

    option: entry_id

      If you send the 'entry_id' option then the log entry specified by the
      given id will be returned. If no such entry is found then undef is
      returned. For example, the following line returns the log entry for
      'fv8sd', or undef if the entry is not found:

       $log->read_backward(entry_id=>'fv8sd');

    option: count

      The count option indicates how many log entries to return. So, for
      example, the following line retrieves up to five entries, fewer if
      the ending|beginning of the file is reached:

       @entries = $log->read_forward(count=>5)

      If count is 0 then all remaining entries are returned. In array
      context an array is returned. In scalar context an array reference is
      returned. Undef is never returned. Each subsequent call using count
      returns the next batch of count entries.

 $log->end_read()

    end_read() explicitly closes the read handle for the log and releases
    the read lock. end_read() always returns undef.

SEE ALSO

    The following modules provide similar functionality. I like mine best
    (or I wouldn't have written it) but your tastes may differ. Funny how
    the world works like that.

    Log::JSON <http://search.cpan.org/~kablamo/Log-JSON/>

    Log::Message::JSON <http://search.cpan.org/~dozzie/Log-Message-JSON/>

    Mojo::Log::JSON <http://search.cpan.org/dist/Mojo-Log-JSON/>

TERMS AND CONDITIONS

    Copyright (c) 2014 by Miko O'Sullivan. All rights reserved. This
    program is free software; you can redistribute it and/or modify it
    under the same terms as Perl itself. This software comes with no
    warranty of any kind.

AUTHOR

    Miko O'Sullivan miko@idocs.com

TO DO

    Clean up POD

      In particular, I can't figure out how to link to sections in this
      page that have greater-than symbols in their names like
      $qnd->cancel()

VERSIONS

    Version 0.10, May 20, 2014

      Initial release.

    Version 0.11, May 22, 2014

      Fixed problem in test script. Fixed incorrect documentation.

    Version 0.12, May 225, 2014

      Made non-backwards-compatible change from "entry-id" to "entry_id".

      Added 'entry_id' option to $log_file->get_entry().

      Added documentation for $qnd->private() method.

    0.13, May 26, 2014

      Changed $log_file->get_entry() to $log_file->read_backward(). This is
      a non-backwards-compatible change.

      Added $log_file->read_forward().

      Added private method $log_file->read_entry().

    0.14, May 27, 2014

      Fixed test script that was attempting to clear the screen. That bug
      was an artifact from development.

      Added count option to read_forward and read_backward.

    0.15, May 28, 2014

      Tidied up output of log entry so that the entry is followed by a
      newline.

      Added $log->entry_count() method.

    0.16, July 28, 2014

      Added catch_stderr method. Fixed typos in documentation. Clarified
      wording in documentation.

