scsh-hackers
[Top] [All Lists]

[Scsh-hackers] New syslog API proposal

To: scsh-hackers@lists.sourceforge.net
Subject: [Scsh-hackers] New syslog API proposal
From: shivers@cc.gatech.edu
Date: Sun, 11 Feb 2001 12:59:02 -0500
List-id: Discussion among the implementors <scsh-hackers.lists.sourceforge.net>
Reply-to: shivers@cc.gatech.edu
Sender: scsh-hackers-admin@lists.sourceforge.net
I have a new proposal for a syslog facility. The underlying premise is
that explicit opening and closing of syslog channels (connections) 
should be deprecated, since providing multiple channels typically requires
multiplexing them onto a single connection. Just create & use them, letting
the run-time system figure out how to manage them. This means that we no longer
have to have facilities for opening-a-connection/doing-some-work/closing-
the-connection in a fashion that protects the connection-close across
non-local exits, which simplifies things a fair amount. E.g., I can punt
the analogs to (CALL-WITH-INPUT-FILE filename proc) and 
(WITH-INPUT-FROM-FILE filename thunk).

The API follows. After we converge, I will post to the scsh and scheme
newsgroups for discussion, but we would not have to wait for that to proceed.
    -Olin

** Basic operations on syslog channels
======================================
A syslog channel is a value that describes a particular connection to the
syslog system. Scsh permits multiple such channels, each describing a
different client of the logging service. This can be particularly useful
in a multithreaded context, where different threads may be executing 
completely distinct applications.

The following procedures allow one to create, examine, recognise, compare and
hash syslog channels.

(syslog-channel [name class option]) -> syslog-channel

    A syslog channel is characterised by three values that describe
    the client facility using the logging service: the facility NAME,
    the facility CLASS, and any connection OPTIONS.

    - NAME is either a string, or false, meaning no name string is associated
      with the channel. It is intended to name the facility performing the
      logging, and is typically the name of the process' program (in a
      one-application-per-process setting).

      Additionally, the NAME parameter may be one of
        syslog-channel  This channel's name
        #t              The current channel's name
      If no NAME parameter is provided, it defaults to #F.

    - CLASS is a value specifying the general class of the facility performing
      the logging. The range of possible classes are the values of these
      named constants:
          syslog-class/authorisation    Security/authorization messages 
(private)
        * syslog-class/cron             Clock daemon (cron and at)
          syslog-class/daemon           Other system daemons
          syslog-class/kernel           Kernel messages
          syslog-class/local0           Reserved for local use
          syslog-class/local1           Reserved for local use
          syslog-class/local2           Reserved for local use
          syslog-class/local3           Reserved for local use
          syslog-class/local4           Reserved for local use
          syslog-class/local5           Reserved for local use
          syslog-class/local6           Reserved for local use
          syslog-class/local7           Reserved for local use
          syslog-class/lpr              Line-printer subsystem
          syslog-class/mail             Mail subsystem
        * syslog-class/news             USENET news subsystem
        * syslog-class/syslog           For msgs generated internally by syslog
          syslog-class/user             Generic user-level messages (default)
        * sysloc-class/uucp             UUCP subsystem
      The unstarred constants comprise a portable set. The starred facility
      classes are common facility classes that are not provided on all Unix
      systems; if such a facility class is not available on the particular 
      system, the named constant is bound to #F. Other facility classes
      may be provided by a particular Unix system as well.

      The default facility class is SYSLOG-CLASS/USER.

      Additionally, the CLASS parameter may be one of
        syslog-channel  This channel's class
        #t              The current channel's class

      [Some work needs to be done to pick out the standard BSD/Linux/Solaris
      facility classes, i.e. the starred entries above. This is the same game
      played with tty-driver flags -- see section 3.12.1 of the manual.]

    - OPTION is the bitwise-or of the following options:
        syslog-option/console-on-error
        syslog-option/pid
        syslog-option/echo-on-stderr
      Other options may be available on a particular Unix implementation.

      Additionally, the OPTION parameter may be one of
        syslog-channel  This channel's options
        #t              The current channel's options

    Creating a syslog channel does not open a connection to the syslog
    service; the actual connections are made on-demand. (See below.) Note that
    the NDELAY option is not provided by scsh; this effect can be obtained
    with FORCE-SYSLOG-CHANNEL if desired.

    Design note: Allowing syslog-channels as parameters makes it easy to
    "clone" a channel, overriding specific attributes where desired.

    Implementation note: the syslog system is provided using standard C
    interfaces that do not permit nul-byte or multi-byte characters for the
    facility name. So things are somewhat iffy for Schemes that provide
    super-Latin-1 character types. Such an implementation might employ an
    alternate interface to the system logger, or might be forced to filter
    these characters out of the name. Similarly, nul characters are currently
    filtered out of the facility name, as C is unable to deal with them.

(syslog-channel:class syslog-channel) -> int
(syslog-channel:name  syslog-channel) -> string or false
(syslog-channel:options  syslog-channel) -> int
    These functions export the three attributes of a syslog channel.

    Design note: syslog channels are pure -- they cannot be side-effected.

(syslog-channel? x) -> boolean
(syslog-channel= syslog-channel1 syslog-channel2) -> boolean
(syslog-channel-hash syslog-channel [bound])
    Basic type predicate, equality and hash support for syslog channels.

    Syslog channels are distinct from other values in the system.

    Two channels are equal if their three attributes are all equal.

    The function used to hash syslog channels is implementation specific.
    BOUND is an exact non-negative integer, defaulting to zero.
    If it is positive, the hash function returns an integer in the range
    [0,BOUND); if it is zero, the hash function returns an integer
    in a large, implementation-chosen range, e.g. the range of non-negative
    integers that can be represented in a single machine word.

** Forcing channels to open and close
=====================================
These operations are not strictly necessary to normal use of the syslog
facility, and are, in fact, deprecated for normal use.

(force-syslog-connection syslog-channel) -> unspecified
    If the channel is not currently connected to the syslog service,
    connect it. This is *not* required in order to log messages
    with the channel -- logging routines such as SYSLOG-WRITE will
    make connections on-demand when given an unconnected syslog channel. 
    This routine simply forces the connection to be made at an earlier 
    point in time.

    Implementation note: Most underlying implementations of the syslog
    facility will only allow one syslog connection at a time, requiring the
    scsh run-time system to multiplex different syslog-channels onto this
    single connection on-demand. Hence forcing a syslog channel to be
    connected in one thread could be undone a millisecond later by a syslog
    operation on a different channel in another thread.

(close-syslog-channel syslog-channel) -> boolean
    Close the channel; return true if the channel was previously open,
    and false if it had already been closed.

    Attempting to force or write to a closed channel will raise an error.

    Syslog channels are also closed when they are garbage collected.

    Implementation note: closing a channel does not necessarily break
    the connection to the syslog daemon, since there may be other open
    channels in the system, multiplexed onto the same underlying socket.

** The dynamicaly-scoped current syslog channel
===============================================
The scsh run-time systems maintains a "current syslog channel" which
is the default channel used for logging messages. The binding of the
current channel is maintained with dynamic scope, and can be manipulated
with the following forms. Note that this allows threads both to share a single
binding, or isolate themselves from other threads, as desired.

The top-level dynamic scope of the scsh run-time system binds the current
syslog channel to a value with default facility class, no options, and
a facility name taken from the name of the Unix process.

(with-current-syslog-channel* syslog-channel thunk)    -> value(s) of thunk
(with-current-syslog-channel  syslog-channel body ...) -> value(s) of body
    Bind the current syslog channel to SYSLOG-CHANNEL and 
    call the thunk / execute the body forms in that dynamic scope.

(set-current-syslog-channel! syslog-channel) -> unspecified
    Change the current syslog channel in the current dynamic scope.
    The side-effect is only performed on the binding of the current
    syslog channel that is visible in the current dynamic scope.
    The binding remains unaltered in other scopes.

(current-syslog-channel) -> syslog-channel
    Return the current syslog channel.

** Logging messages with syslog channels
========================================

(syslog-write level msg [syslog-channel]) -> unspecified
    Log string MSG with severity LEVEL to SYSLOG-CHANNEL, which
    defaults to the current channel.

    The severity level is one of the following named constants:
        syslog-level/emergency  System is unusable
        syslog-level/alert      Action must be taken immediately
        syslog-level/critical   Critical condition
        syslog-level/error      Error condition
        syslog-level/warning    Warning condition
        syslog-level/notice     Normal, but significant, condition
        syslog-level/info       Informational message
        syslog-level/debug      Debug-level message

    Implementation note: the syslog facility is provided using standard C
    interfaces that do not permit nul-byte or multi-byte characters. So things
    are somewhat iffy for Schemes that provide super-Latin-1 character types.
    Such an implementation might employ an alternate interface to the
    system logger, or might be forced to filter these characters out of the
    message. Similarly, nul characters are currently filtered out of the
    message, as C is unable to deal with them.

    [Do we need to select & name standard but non-portable Linux/Solaris/BSD
    severity levels, a la facility classes above?]

(syslog-format level syslog-channel format-string arg ...) -> unspecified
    As in SYSLOG-WRITE, but the message is produced in the manner
    of the FORMAT procedure, using the given format-string and arguments.
    Passing #t for the SYSLOG-CHANNEL parameter will use the current
    syslog channel.

    [I dislike FORMAT, and intend to design a replacement, extensible little
    language for doing I/O one day. Should I enshrine FORMAT in this API?]

-------------------------------------------------------------------------------
How it works:

Making a syslog channel simply allocates a record with the three indicated
attributes, and an OPEN? bit which is cleared when the channel is closed.

The run-time maintains a private bit of state, the channel currently installed
via the C syslog(3). When a SYSLOG-WRITE is done, the channel to which we are
writing is compared to this installed channel (using SYSLOG-CHANNEL=, not
EQ?). If they differ, we use the C openlog(3) routine to install the new
channel as the currently-installed one and proceed.

We keep a "weak set" of the allocated, open channels. Closing a channel
removes it from this set; if the set is empty we call the C closelog(3)
routine. This weak set is also checked after each GC.

Should also have a low-level, sub-thread-system facility for getting at the C
openlog(3) and closelog(3) routines, procedures named with % prefixes.

SYSLOG-WRITE must scan the message string to escape %'s and remove nul chars,
since %'s are interpreted by syslog(3) as printf codes, and nul chars will
mess it up.

-------------------------------------------------------------------------------
Random notes:

Open issues are marked in the above API with [...]'s.

syslog design alternatives
- no channel values, full spec on each call
  No state, no dynamic scope hoo-hah, completely functional.
  But options are problem. No good.

- encode as regular ports, use regular I/O funs like WRITE-STRING & FORMAT.
  Must buffer data & split at newline boundaries. How to handle two distinct
  writes, where the first is distinct from the second, but doesn't end in
  newline?
  + Require the newline (best)
  + Add an "end-of-msg" proc. (sux)
  This approach means you must bind the severity level to the port when
  you make the port; different severity levels require different ports.
  Awkward.

Note that with the current design you *can't specify* the facility class at
write time; it is fixed when the channel is created. But channel creation is
very cheap, and, actually, something one does rarely, so no problem.


<Prev in Thread] Current Thread [Next in Thread>