[Mimedefang] MD, logging, and a little bit about the multiplexor

Clayton, Nik [IT] nik.clayton at citigroup.com
Mon Sep 30 06:44:01 EDT 2002


Hi all,

Here's an MD feature request for discussion.  Everything here is IMHO, of
course.

Instead of using the Syslog module for logging, MD should use something 
with a bit more flexibility -- e.g., Log::Channel 

    http://search.cpan.org/author/JMAY/Log-Channel-0.6/Channel.pm

Syslog.pm has its advantages -- namely, it's shipped with Perl and it's
very simple to use.

However, if you want to log information from within an MD filter, you're
then left with whatever MD supplied for the logging identity, log options,
and facility in the openlog() call.

This is not good:

   * You've got to grovel through the MD source code to determine how
     these things are set.

   * There's no guarantee that future versions of MD will call openlog()
     with the same parameters.

   * There's no way to log within your filter with a different identity,
     options, or facility, without first calling closelog(), then 
     openlog() with new options, then closelog() again, then openlog()
     with the old options.  This is tricky:

     a) You don't know what the original options where without looking
        through the MD source code.

     b) Any MD supplied function that your filter calls (action_*(), for
        example) may decide to log something, so you need to do this dance
        before every MD function call.

These can be worked around.  For example, the mimedefang-filter file can
have C<use Log::Channel;> at the top, and do its own logging that way, or 
it can C<system('/usr/bin/logger', '-p', 'mail.info', 'string to log');>
which is simple, but expensive (because it's a fork()/exec() each time).

Much better (IMHO) to have MD do something like this:

    use Log::Channel;
    use Log::Dispatch::Syslog;

    ...

    # Create a new Log::Channel for use by MimeDefang
    my $MD_LOG_CHANNEL = new Log::Channel('mimedefang');

    # Set this channel to log using syslog
    Log::Channel::dispatch('mimedefang', 
                           new Log::Dispatch::Syslog(name      =>
'mimedefang',
                                                     min_level => 'info',
                                                     ident     =>
'mimedefang'));

    # Create a tiny md_log() function, that just logs the message using
    # $MD_LOG_CHANNEL
    sub md_log { $MD_LOG_CHANNEL->(message => $_[0]); }

    ...

    # Elsewhere in MimeDefang
    md_log('something we want to log');

In mimedefang-filter() I can then write something like this, if I want 
to use MD's log:

    ...
    syslog('Something I want to log the same way MD logs things');
    ...

and if I want more control over the logging that comes from my filter I can
instead do something like this in /etc/mail/mimedefang-filter

    my $filter_log_channel;

    sub filter_begin {
        # Set up the log channel
        $filter_log_channel = new Log::Channel('filter');
        Log::Channel::dispatch('filter',
                               new Log::Dispatch::Syslog(...);

        # Rest of filter_begin()
        ...
    }

    sub filter_log { $filter_log_channel->(message => $_[0]); }

    # somewhere else in the filter

    sub foo {
        ...
        md_log('I want to log this in the same way that MD logs stuff');
        ...
        filter_log('I want to log this with my filter's custom log');
        ...
    }        

And about the multiplexor. . . filter_begin() is called at the beginning
of processing each message, which is fine.  However, if you use the 
multiplexor, that means that filter_begin() is going to be called multiple
times.  For stuff that only needs initialising once (e.g., log channels
in the previous example) it would be great if there was a filter_init()
(or some such) that was guaranteed to be called exactly once, and at a
defined point in the MD start up process.

Thoughts?

N (off to go and have another word with the lawyers, to see if I can
   release the code that does the above).

PS:  In the above, Log::Channel is used as an example only.  There are
     a plethora of different logging modules on CPAN -- Log4Perl might be
     another good (albeit heavyweight) choice.
-- 
1        1         2         3         4         5         6         7    7
         0         0         0         0         0         0         0    5
  -- The 75 column-ometer
                                             Contributing to the heat death
Global Messaging, 120 Cheapside, x83331      of the universe since 1973.



More information about the MIMEDefang mailing list