LoxBerry::Log::new (logging constructor)

$logobject = LoxBerry::Log::new(named parameters);


Creates a log object to do LoxBerry-specific logging to a logfile or to the standard output (stderr, stdout). The LoxBerry logging module uses the user-defined loglevel from the plugin management, therefore no plugin-own setting and own loglevel-filtering is required.

Constructor

This article is the specification of LoxBerry's log object-class. For starting examples, see the article Usage of the logging module.

The constructor of the log object takes several named parameters to adjust the logging behaviour. Some parameters are dependent to other parameters.

Info for LoxBerry-Core developers: Some parameters have fallback settings if used in a plugin, but are mandatory if used in widgets or other LoxBerry-Core components.

Named parameters

Named parameters are delivered in the form LoxBerry::Log::new( parameter ⇒ "value", parameter ⇒ "value", …). For numbers, the quotes are not required. Perl does not recognize Booleans (True, False), they need to be 1 or 0.


Parameter OptionalDefault Function
name This is the "logical" name (better think of a group) of your logfile. This is not the filename. You may use a name like "webinterface" and "daemon" to group multiple logfiles of your plugin.

The name is optional only if you use the nofile parameter (to not write any logfile)
package x $lbpplugindirThe package defines, where this log belongs to. In a plugin, the log always belongs to the plugin, therefore the $lbpplugindir variable is used automatically. For Core developers, or if LoxBerry cannot determine your plugin directory, the constructor will fail with an error "A package must be defined."
logdir x $lbplogdir The logdir parameter defines, in which directory the logfile should be created. In a plugin, the directory is defaulted to the plugin log directory $lbplogdir.

If the logdir parameter is used, the filename of the log is generated (see filename explanation).

The logdir and filename parameters are mutually exclusive: If the logdir parameter is used, the filename is automatically generated. If - otherwise - the filename parameter is used, the logdir parameter is completely ignored.
filename x (generated) The filename parameter defines the absolute path and filename to the logfile. It is not combined with the logdir parameter.

Without filename parameter, the filename is created out of <timestamp>_<package>_<name>.log, so every call of the constructor creates a new logfile.

With filename, the full file path needs to be specified. Use the filename parameter, if you want to have a fixed filename everytime.

The logdir and filename parameters are mutually exclusive: If the logdir parameter is used, the filename is automatically generated. If - otherwise - the filename parameter is used, the logdir parameter is completely ignored.
append x 0 0 → The logfile will be overwritten

1 → If the file already exists, the log will be appended

The append parameter only makes sense when using the filename parameter.
Where the logging should take place
stderr x 0 1 → Enables to output to STDERR
stdout x 0 1 → Enables to output to STDOUT
nofile x 0 0 → A logfile to disk is written

1 → Writing to disk is disabled, no filehandle is created or opened.
Every parameter stands for itself - they are not exclusive. Therefore, you can combine stderr ⇒ 1 and nofile ⇒1 to only get logging output to STDERR (this can be very handy during development). Or you can enable stderr ⇒ 1 together with stdout ⇒ 1. Or you can only set stderr ⇒ 1 to get a logfile and the output to STDERR.
Special parameters
loglevel x user-defined You should not set the loglevel in your code. LoxBerry::Log determines the loglevel from the plugin management userinterface, where every user can set the desired loglevel. LoxBerry::Log will automatically filter your log events by the user-defined loglevel.

LoxBerry-Core developers: As no systemwide loglevel is available, you need to set the loglevel.
autoraise x 1 Auto-Raise will automatically set the loglevel to 6 ("raise"), if any event of severity 2, 1 or 0 (LOGCRIT, LOGALERT, LOGEMERGE) is triggert. LOGCRIT should be used for events that are unrecoverable (your program has to terminate). If you send an LOGCRIT event and auto-raise raises the loglevel, you can send additional logging events with more information about the shutdown reason. After the LOGCRIT, every severity is logged except LOGDEB (except loglevel was already on 7 before).
addtime x 0 1 → A timestamp is added to every logging line triggered by a logging event. This is useful for time measurement.
dbkey x <none> This is a special parameter for handing over logging sessions from script to script. The caller will query the dbkey with $log→dbkey and send this to the second script. The second script uses the dbkey parameter in the constructor to recover the logging session. No other parameters are needed and are recovered from the initial session. Additional parameters like strerr ⇒ 1 will overwrite the saved settings. (available from LoxBerry V1.2.5)
nosession x 0 Sending nosession ⇒ 1 creates no headers and only a single database entry under package+name. It is the feature for "line by line logfiles" with little output. It implicitely enables append ⇒ 1. The logfile ⇒ … parameter is mandatory, as the filename is the key of the log. See example below. (available from LoxBerry V2.0)


Usage

Simple logging

use LoxBerry::Log;
# Creates a logging object with the filename $lbplogdir/<timestamp>_$lbpplugindir_daemon.log (e.g. /opt/loxberry/log/plugins/kodi/20180417_104703_kodi_daemon.log)
my $log = LoxBerry::Log->new ( 
    name => 'daemon', 
);
 
 
# Creates a logging object using the fixed filename $lbplogdir/mylogfile.log, append to existing log
my $log = LoxBerry::Log->new ( 
        name => 'cronjob', 
        filename => "$lbplogdir/mylogfile.log",
        append => 1,
);
 
 
# After init of the log object, start to log
LOGSTART "Update by cron job"; 
LOGOK "Everything ok";
LOGEND "Finished";


Object functions

After the log is initialized, you can access several properties from the log object (column "Readable"), and you also can change several properties ("Changeable"). 

Parameter ReadableChangeableReturn value Function
filename x String with absolute filenameYou can query the currently used filename, also if it was generated (so, if you haven't used the filename parameter, but the logdir parameter).

If you need the filename to pipe other log output to the file, you should use the close function.
filehandle x <filehandle> Returns the used filehandle to access the file. This can be used, if your function directly can write to the handle. Never close this filehandle by yourself.
close x String with absolute filenameThis will close the filehandle and return the current filename. Use this function before you pipe "foreign" output from other commands to the logfile.

It is required to close the filehandle before some other tool writes to the file, because the file is locked by LoxBerry::Log. Without closing the file, other commands may fail, or the writing is cached and written, when LoxBerry::Log closes the file after LOGEND.

After you have piped your output to the logfile, use the open method to re-open the filehandle.
open x Re-opens the logfile after the filehandle was closed by close. No parameters are required.
default x Sets the current log object to the default log. The shortcut functions (LOGDEB, LOGOK,…) use this log object.
Where the logging should take place
stderr x x 0/1 Enables or disables stderr output, or queries the current status.
stdout x x 0/1 Enables or disables stdout output, or queries the current status.
nofile x x 0/1 Disables or enables logfile output, or queries the current status.
Special parameters
loglevel x x 0-7 Returns the currently set loglevel, and allows to change the current loglevel.
autoraise x x 0/1 Enable or disable Auto-Raise, and collect the current status.
addtime x x 0/1 Enables or disables writing a timestamp, or queries the current status.
dbkey x <int> Returns the unique number of this logging session for a handover to another script. The dbkey is initialized with the LOGSTART event. Before, the dbkey is undefined. (available from LoxBerry V1.2.5)
Writing to the logfile, e.g. $obj→OK("OK message") 
The writing functions exist both as method on the log object, and as shortcut function.

The method on the object is called with $log→WARN("text"). The shortcut function uses the default object and is directly called with LOGWARN("text").
LOGSTART x LOGSTART("Logfile title"); Submit a string for the title of the logfile, e.g. LOGSTART "Daemon was called". LoxBerry::Log automatically adds several information to the logfile, e.g. the current time, and a special header to signal a new logfile start in the logviewer. → Shortcut function is LOGSTART
LOGTITLE x x Title of the log As LOGSTART defines the log title that is displayed in the loglist, you may change the title during runtime (e.g. because you have more specific information from a config file). The function does not write to the logfile.
LOGEND x LOGEND ("Final message"); Submit a string for the footer of the logfile, e.g. "LOGEND "Processing of daemon finished". LoxBerry::Log uses this information to know that your program did not terminate unexpected. If LOGEND is missing, LoxBerry::Log expects that your program died. → Shortcut function is LOGEND
DEB x Debug message (severity 7) → Shortcut function is LOGDEB
INF x Info message (severity 6) → Shortcut function is LOGINF
OK x OK message (severity 5) → Shortcut function is LOGOK
WARN x Warning message (severity 4) → Shortcut function is LOGWARN
ERR x Error message (severity 3) → Shortcut function is LOGERR
CRIT x Critical message (severity 2) → Shortcut function is LOGCRIT
ALERT x Alter message (severity 1) - Currently you should not use this → Shortcut function is LOGALERT
EMERGE x Emergency message (severity 0) - Currently you should not use this → Shortcut function is LOGEMERGE

Usage

Simple logging

use LoxBerry::Log;
# Creates a logging object
my $log = LoxBerry::Log->new ( 
    name => 'daemon', 
);
 
 
# Query the filename
my $filename = $log->filename;
 
 
# Query the current loglevel
my $loglevel = $log->loglevel;
 
 
# Set loglevel to 7
my $loglevel = $log->loglevel(7);
 
 
# Pipe text to the logfile during operation
my $filename = $log->close;
system("ls -l >> $filename");
$log->open;
 
# Change the logfile title during runtime
LOGTITLE "New logfile title";
$log->logtitle("Another new title");
print "Current title is " . $log->logtitle();
 
# Finish processing because of an unrecoverable error
if ($unrecoverable_error_occured) {
    LOGCRIT "Processing stopped because of an unrecoverable error";
    # Auto-Raise automatically switches to loglevel 6
    LOGERR "Occured error: $error";
    LOGINF "Current state is $state";
    # Finish the log
    LOGEND "Processing terminated";
    exit(1);
}

Tricks using the logging components

LOGEND

The LOGEND call should always be used to tell LoxBerry::Log and the logging database, that your logfile is finished.

The $message on LOGEND is optional. You can simply call LOGEND without parameter.

You can place LOGEND to an END block in your Perl script. The END is a "magic" block that is called from Perl on every script exit. In the END block, you can check if you already have called a LOGEND by simply checking the $log object: LOGEND unreferences your $log object.

END
{
    if ($log) {
        $log->LOGEND;
    }
}

Loglevel in a daemon

The loglevel will be read from the plugin database once at the init of the log object, and then every minute, in the case you do not set the loglevel in the constructor or by $log→loglevel. 

If you don't set the loglevel in your code, it is taken from the loglevel setting the user has done in the Plugin Management (or in Log Manager, or in your plugin, if you offer the control). 

nosession => 1 parameter

Available from LoxBerry V2.0

This feature is disabling the log sessions, and refrains from the logging headers and footers, and new log database entries for each file.

Notices:

  • With nosession => 1, the filename => ... parameter is mandatory (the filename is the key)
  • append => 1 is implicitely set.
  • The first call will create one database entry (to view it in Log Manager). Every further call will update this database entry.
  • The big headers and footers from LOGSTART and LOGEND will not be in the logfile.
  • The LOGSTART and LOGEND requests are still required. The LOGSTART message will be inserted to the log as normal-formatted ok message. LOGEND will update the database state.
  • If the logfile was deleted (e.g. by the logfile maintenance), the first lines in the log still are information about LoxBerry version, Plugin version and loglevel. They only appear once on the top.

Example:

Simple logging

use LoxBerry::Log;
$log = LoxBerry::Log->new (
        name => 'AJAX',
        filename => "$lbplogdir/ajax.log",
        stderr => 1,
        addtime => 1,
        nosession => 1,
    );
LOGSTART "ajax call: checksecpin";
LOGOK "Secure pin was ok";
LOGEND;

Example view in Log Manager and logfile:

Only a single line will exist in Log Manager, independent of the number of calls.

This is the logfile after two calls.