## ## OSSP fsl - Faking/Flexible Syslog Library ## Copyright (c) 2002-2005 Ralf S. Engelschall ## Copyright (c) 2002-2005 The OSSP Project ## Copyright (c) 2002-2005 Cable & Wireless ## ## This file is part of OSSP fsl, a syslog(3) API faking library which ## can be found at http://www.ossp.org/pkg/lib/fsl/. ## ## Permission to use, copy, modify, and distribute this software for ## any purpose with or without fee is hereby granted, provided that ## the above copyright notice and this permission notice appear in all ## copies. ## ## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ## SUCH DAMAGE. ## ## fsl.pod: OSSP fsl manual page ## =pod =head1 NAME B - Faking/Flexible Syslog Library =head1 VERSION OSSP fsl FSL_VERSION_STR =head1 SYNOPSIS LDFLAGS=`B` LIBS=`B` ./configure [...] =head1 DESCRIPTION B offers the syslog(3) API otherwise provided by the Standard C Library (F). Instead of writing to the syslogd(8) process, it uses the powerful B logging capabilities. It is a drop-in link-time replacement which enables any syslog(3) consumer to take advantage of B by just linking this library in before F. The program is intended to apply B functionality to existing syslog(3) based third-party programs without the requirement to change the source code of the program. =head1 OPERATION If an application calls openlog(3) it passes an identification string (I) and a logging facility (I) along. B reads all configuration files matching "ICIC<*>" and parses them using B. Sections are identified by "CICIC<;>" directives. The I argument is an B (Perl-compatible) regular expression that is matched against a string concatenated from "I/I" given to the openlog(3) call. The I (single) argument is an B channel tree specification, usually quoted with B flexible quotes (to make it a single B argument) like "C". The I may contain "C<$1>", ..., "C<$9>" variables which are filled in from the I regular expression parts enclosed in round brackets. The "C<$0>" variable captures the wholly match and "C<$$>" diverts to a single escaped "C<$>". An B channel tree is build from all I on each matching "C" directives and all found trees are merged together with a top "C" channel to form a single channel tree. Further calls to syslog(3) will then inject log messages into this channel tree. =head1 OSSP L2: CHANNEL TREE SPECIFICATION B builds its working configuration using a global environment object and channels which are interconnected to form a channel tree. The environment object holds general internal information and maintains the registration of formatters. The channels are used to process the logging message and use formatters to transform it. The root channel of the tree and each intermediate channel might have one or more children below it, passing the processed message down the tree. The leafs of the tree are constructed by channels specifically designed for outputting the message. Every logging message is injected into a channel, most likely the uppermost one, and traverses down the tree where channels with multiple children duplicate the message. B allows a developer to build this tree programmatically. In addition, B also supports building up the channel tree using a text based "channel tree specification" language. This declarative language offers maximum flexibility as a program can read a specification created by a system administrator and pass it to B verbatim without even knowing anything about existing channels. If this approach is used, a newly designed channel can be used by an existing program by just linking in the latest B version. The main program remains unmodified. An B channel tree specification is defined by the following context-free grammar: B ::= B B ::= I | B | B '->' B | B '->' '{' B '}' B ::= B | B ';' B B ::= B '/' B ':' B | B ':' B | B B ::= B | '(' B ')' B ::= B | B '|' B B ::= 'panic' | 'critical' | 'error' | 'warning' | 'notice' | 'info' | 'trace' | 'debug' B ::= B B B ::= 'buffer' | 'fd' | 'file' | 'filter' | 'irc' | 'noop' | 'null' | 'pipe' | 'prefix' | 'smtp' | 'socket' | 'syslog' | ... B ::= I | '(' ')' | '(' B ')' B ::= B | B ',' B B ::= B '=' B B ::= m/[a-zA-Z][a-zA-Z0-9_-]*/ B ::= single-quoted, double-quoted or unquoted text =head1 OSSP L2: AVAILABLE CHANNELS B provides various channels. The following lists their B prefixed with an 'C' or a 'C' indicating whether it is operating as an output or filter channel. All parameters to B are listed, including the type of each parameter which is either a string (C) or integer (C) and an 'C' or 'C' indicating the parameter is optional or mandatory. Also, the default value for each parameter is listed, if there is one. =head2 Buffering Filter Channel (buffer) The B channel buffers messages poured in from upper channels. It flushes the messages down to the lower channels when the buffered space exceeds the buffer I, when a given time I is reached (0 disables this feature) or when a newly arrived message has a level that matches the I mask. f buffer (INT size o [bytes] =4096 INT interval o [sec] =0 (disabled) INT levelflush o [level] =0 (none) ) =head2 Filedescriptor Output Channel (fd) The B channel passes messages poured in from upper channels to the open file identified by the filedescriptor passed through I. Note that Unix usually allocates C<1> for F and C<2> for F. o fd (INT fd m ) =head2 File Output Channel (file) The B channel opens a file at the given I and passes messages poured in from upper channels to this file. If the file at the given path already exists, additional data is either appended (I=0>) or the existing file is truncated (I=1>). The desired permissions of the logfile can be set through I. If I is set to a number n other than zero the logfile will be closed and reopened before every n'th write operation. In other words, a logfile moved away will receive a maximum of n additional messages, then a new file using the old name will be opened without truncation. If I is set to n seconds other than zero a timer is set. For every write operation the time is checked. If n or more seconds have passed by the timer is reset and it is checked whether the logfile was moved or disappeard. In such case the logfile will be closed an reopened before the actual write. In other words, a logfile moved away will receive messages no longer than the timer is set to, then a new file using the old name will be opened without truncation. These options make external log file rotation easy at a controllable price of performance. It is possible to combine I and I. Note that the append option is obsolete and might be removed in the future. Use the trunc option with inverse logic instead. o file (STR path m INT append o [0=no|1=yes] =1 INT trunc o [0=no|1=yes] =0 INT jitter o [count] =0 (disabled) INT monitor o [sec] =0 (disabled) INT perm o [octal] =0644 ) =head2 Filtering Channel (filter) The B channel filters messages poured in from upper channels. A regular expression is applied against the incoming message and the normal operation is that only matching messages are passed down the tree. Setting I reverses the matching decision. Comparisons are case sensitive unless I is set. f filter (STR regex m [PCRE] INT negate o [0=normal,1=negate] =0 INT nocase o [0=case,1=nocase] =0 ) =head2 Internet Relay Chat Output Channel (irc) The B channel opens a connection to a given IRC channel and passes messages poured in from upper channels to this IRC channel. If configured, the message posted to IRC channel contains the I for easy identification of the sending host. o irc (STR progname o [string] STR localhost o [hostname|address] =nodename or "localhost" STR localuser o [string] =name or "uid#"num STR nickname o [string] =localuser STR username o [string] =localuser"@"localhost STR realname o [string] =username STR channel o [string] ="#l2" INT join o [01] =1 use JOIN/PART STR host m [hostname|address] STR port o [tcpport] =6667 INT timeout o [sec] =30 ) =head2 No Operation Filtering Channel (noop) The B channel can be used to divert incoming messages to multiple channel paths down the tree. Otherwise is does not do anything put passing the messages along. It has no configuration parameters at all. f noop () =head2 No Operation Output Channel (null) The B channel discards any incoming messages and creates no output at all. It has no configuration parameters. o null () =head2 Command Pipe Output Channel (pipe) The B channel executes a given command and pipes messages poured in from upper channels to the commands F. The command can be executed directly or run by "C". The lifetime of the connection can be adjusted by setting I to either "C" for a continuous pipe-through with command restart after termination or "C" for one-shot where the connection is dropped when the command terminates. o pipe (STR execmode m [direct|shell] STR runtime m [cont|one] STR path m [dir/file] ) =head2 Prefixing Filtering Channel (prefix) The B channel prefixes messages poured in from upper channels. The I format string may contain formatting variables prefixed with a 'C<%>'. These are expanded using the internal B formatters L loglevel N nodename P pid then expansion continues to use application specific formatters where B offers D dump S string m errno and finally remaining variables are expanded by strftime(3). f prefix (STR prefix m [string] STR timezone o [local|utc] =local ) =head2 Simple Mail Transfer Protocol Output Channel (smtp) The B channel forwards messages poured in from upper channels to remote hosts using the Simple Mail Transfer Protocol (SMTP). It is possible to specify the local address to bind to which is useful for multi-homed hosts. o smtp (STR progname o [string] STR localhost o [hostname|address] =nodename or "localhost" STR localuser o [string] =name or "uid#"num STR from o [string] =localuser"@"localhost STR rcpt m [string] STR subject o [string] ="[L2] ..." STR host m [hostname|address] STR port o [tcpport] ="smtp" INT timeout o [sec] =30 ) =head2 Raw Socket Output Channel (socket) The B channel forwards messages poured in from upper channels to daemons on remote hosts using raw UDP communication or TCP connections. o socket (STR proto o [udp|tcp] =tcp STR host m [hostname|address] STR port m [udpport|tcpport] INT timeout o [sec] =30 ) =head2 Syslog Remote Output Channel (syslog) The B channel forwards messages poured in from upper channels either to the local syslog(3) library or passes it directly via UDP communication to a remote (or even local) syslogd(8). It is possible to specify the local address to bind to which is useful for multi-homed hosts. o syslog (STR target o [local|remote] =local STR remotehost o [hostname|address] INT remoteport o [udpport] =514 STR localhost o [hostname|address] =nodename or localhost STR facility o [facility] ="user" STR ident m [string] INT logpid o [0=no,1=yes] =1 ); WARNING: Because B is a syslog(3) redirector it must not use the I=C feature of B. It would point back to itself and end up in a infinite run-time loop! However, it's safe to use I=C with I being set to the local host. =head1 OSSP L2: EXAMPLES =head2 Example 1: simple stderr logging A very simple I just writing everything to F (filedescriptor 2): fd(fd=2) =head2 Example 2: simple logfile writing A very simple I just writing notices and more important messages to a logfile with each message prepended with a classical timestamp prefix: notice: prefix(prefix="[%b %d %H:%M:%S]") -> file(path="/var/log/foo") =head2 Example 3: complex logging A very complex I logging example follows. Figuring out the details is left as an exercise to the reader ;) noop -> { (info): filter( regex="foo" ) -> syslog( remotehost="localhost", ident="l2" ); info: prefix( prefix="[%b %d %H:%M:%S] <%L> [%P]" ) -> { debug/error: buffer( size=65536 ) -> file( path="a" ); (trace|debug)/(trace): buffer( size=65536 ) -> file( path="b", perm=0660 ) }; prefix() -> { warning: filter( negate=1, regex="foo" ) -> irc( host=irc.example.com, timeout=3 ); error: filter( nocase=1, regex="foo" ) -> smtp( host=mail.example.com, rcpt=cfo@example.com ); panic: smtp( host=mail.example.com, rcpt=ceo@example.com, subject="Attention: Company at risk!" ) } }; =head1 EXAMPLE # map syslog(3) API priorities to OSSP l2 levels # Notes: - syslog(3) has no corresponding priority for OSSP l2 "trace" # - OSSP l2 has no corresponding level for syslog(3) "emerg" map emerg panic; map alert panic; map crit critical; map err error; map warning warning; map notice notice; map info info; map debug debug; # equivalent of the usual INN syslog.conf(5) entries: # news.crit @l_prefix@/var/inn/log/news.crit # news.err @l_prefix@/var/inn/log/news.err # news.notice @l_prefix@/var/inn/log/news.notice ident (.+)/news q{ prefix( prefix="%b %d %H:%M:%S %N $1[%P]: ", timezone=local ) -> { critical: file( path="@l_prefix@/var/inn/log/news.crit", perm=0644 ); error: file( path="@l_prefix@/var/inn/log/news.err", perm=0644 ); notice: file( path="@l_prefix@/var/inn/log/news.notice", perm=0644 ) } } # default logging default (.+)/.+ q{ debug: prefix( prefix="%b %d %H:%M:%S <%L> $1[%P]: ", timezone=local ) -> file( path="@l_prefix@/var/fsl/default.log", perm=0644 ) }; =head1 CONFIGURE Operation. =over 4 =item C<--with-fsl-cfgdir> The value has to point to an existing directory where configuration files named "IC<*>" (see below) exist. The default value is "C<@FSL_CFGDIR@>". =item C<--with-fsl-prefix> The value has to be a valid partial Unix filename. The default value is "C<@FSL_PREFIX@>". =back Deployment. =over 4 =item C<--with-fsl-debuglogcode> The value must be empty or something where empty omits and anything else includes debugging code. When debugging is not used the whole debugging code is replaced with a simple no-operation stub function. The default value is "C<@FSL_DEBUGLOGCODE@>". =item C<--with-fsl-debuglogfile> The value has to point to a file where logging information is being dumped into. The directory has to exist, the file must be creatable/writable. The file is opened, written in append mode and closed for every debug log message. In case of problems the debug log messages will be silently discarded. The default value is "C<@FSL_DEBUGLOGFILE@>". =item C<--with-fsl-debuglogmask> The value has to point to a symlink. The content of this symlink is the name of a loglevel or a logmask. Possible values are panic, critical, error, warning, notice, info, trace, debug; A single word is interpreted as a log level and all messages with that or a more important level will be logged. If a comma is found in the symlink content a logmask is build by or'ing together the values behind all words. The same is true when the entire value is inside round brackets, which makes this part of the format compatible to l2spec and allows a single word to be a mask rather than a level. If for any reasons the symlink does not exist, is not readable, has a syntactically wrong value or any other problems the debug log messages will be silently discarded. The default value is "C<@FSL_DEBUGLOGMASK@>". =item C<--with-fsl-debuglogstop> The value is the maximum size of the logfile in bytes. If this size is reached or exceeded before the message is written logging stops and debug log messages will be silently discarded. The default value is "C<@FSL_DEBUGLOGSTOP@>". =back For convenience reasons, what(1) or a "strings binarywithfsl | grep '@(#)'" will provide information about debugging code being omitted or included and, in the latter case, which logfile and logmask are being used. =head1 FILES =over 4 =item F<@FSL_CFGDIR@/@FSL_PREFIX@*> B reads configuration sections located in these files. =back =head1 SEE ALSO =over 4 =item syslog(2) The B API which B replaces under link-time. =item B, l2(3), http://www.ossp.org/pkg/lib/l2/ The underlying library providing the flexible logging functionality (see I above). =item B, cfg(3), http://www.ossp.org/pkg/lib/cfg/ The underlying library providing the parsing of the B configuration files (see F above). =item B, pcre(3), http://www.ossp.org/pkg/lib/pcre/ The underlying library providing the matching of program identifiers on B C configuration directives (see I above). =item B, openpkg(7), http://www.openpkg.org/ The project which prompted the development of B and which is also the primary application domain of it. =back =head1 ONLINE RESOURCES =over 4 =item http://www.ossp.org/pkg/lib/fsl/ =item http://cvs.ossp.org/pkg/lib/fsl/ =item ftp://ftp.ossp.org/pkg/lib/fsl/ =back =head1 HISTORY B was implemented in July 2002 by I and I under contract with I . It was originally intended for use in the B project as a replacement for its old B library. It was prompted by the necessity to log to multiple files in the B F package and to write messages of particular log levels to different files in the B F package. The resulting work was generously contributed as Open Source Software to the B project by I for further development and maintainance. =head1 AUTHORS =over 4 =item Thomas Lotterer =item Ralf S. Engelschall =back =cut