Overview

Alog is a stackable logging framework for Ada. It aims to be straight forward to use and easily extendable. It provides support for various logger types, log facilities, loglevel policies and message transformations.

Framework Architecture

Logger

Logger instances are used to manage an arbitrary number of log facilities and message transformations. Various logger types exist which are suitable for different scenarios:

Logger

This is the basic Alog logger type. This logger is easy to use and good enough for most situations. However, it does not provide thread safety.

Tasked Logger

The Alog tasked logger encapsulates a basic logger instance inside a server task to provide safe concurrent logging. Since calls to this logger are potentially blocking operations, it cannot be used from within a protected action.

Active Logger

The Alog active logger provides task safe concurrent logging from any context.

Facility

Another basic entity in the Alog framework is called a Facility. Facilities are log destinations and used to log messages to different backends, e.g. a file or a database. Currently, the framework provides the following log facilities:

File_Descriptor

Writes log messages to file or console.

Syslog

Writes log messages to syslog.

SMTP

Sends log messages by mail.

PGSQL

Writes log messages to a PostgreSQL database.

XMPP (experimental)

Sends log messages to a jabber account.

Transformation

Transformations are used to modify a log message before it is passed on to a facility. The following message transformations are available:

Casing (toUpper / toLower)

Convert a log message to upper/lower case.

Policy

Alog supports source and destination filtering by means of loglevel policies. Refer to the example section for information on how to setup such policies.

Examples

The examples presented in this section will give an introduction on how to use the Alog framework in your own project.

Logger

The following example uses a basic logger instance to log messages to standard output. Furthermore, a file based facility is attached which writes log messages to a file.

with Alog.Logger;
with Alog.Facilities.File_Descriptor;

use Alog;

--  Alog logger example.
procedure Logger_Example1 is
   --  Initialize logger instance with default file descriptor facility
   --  (logs to stdout).
   Log : Logger.Instance (Init => True);
begin
   --  Write a message with loglevel 'Info' to stdout.
   Log.Log_Message
     (Level => Info,
      Msg   => "This is a testmessage from Alog logger");

   Attach_FD_Facility :
   declare
      FD : constant Facilities.File_Descriptor.Handle :=
        new Facilities.File_Descriptor.Instance;
   begin
      FD.Set_Logfile (Path => "/tmp/alog.log");
      Log.Attach_Facility (Facility => Facilities.Handle (FD));

      --  Log a message to file and stdout.
      Log.Log_Message (Source => "Example",
                       Level  => Warning,
                       Msg    => "Another testmessage");
   end Attach_FD_Facility;
end Logger_Example1;

The logger will take care about cleaning up all the attached facilities when it goes out of scope. However, you can do this explicitly by calling Logger.Clear as well.

Facility

The following code sets up a file descriptor based facility to log messages to a file. If the file already exists, it will be overwritten.

with Alog.Log_Request;
with Alog.Facilities.File_Descriptor;

use Alog;

--  Alog file descriptor facility example.
procedure Facility_Example1 is
   Facility : Facilities.File_Descriptor.Instance;
begin
   --  Enable writing of loglevels.
   Facility.Toggle_Write_Loglevel (State => True);

   --  Use '/tmp/alog.log' as logfile, overwrite existing file.
   Facility.Set_Logfile (Path   => "/tmp/alog.log",
                         Append => False);

   --  Let the facility process a log request with loglevel 'Warning'.
   Facility.Process
     (Request => Log_Request.Create
        (Level   => Warning,
         Message => "This is a testmessage from Alog FD facility"));

   --  Teardown the facility.
   Facility.Teardown;
end Facility_Example1;

Policy

The first policy example uses the policy database of Alog to specify source specific loglevels. It shows how logging policies can be used to filter log messages depending on their source.

with Alog.Policy_DB;
with Alog.Logger;

use Alog;

--  Alog source loglevel policy example.
procedure Policy_Example1 is
   Log : Logger.Instance (Init => True);
begin
   --  Set default loglevel to 'Info'.
   Policy_DB.Set_Default_Loglevel (Level => Info);
   --  Set source specific loglevel for all 'Example' sources to 'Debug'.
   Policy_DB.Set_Loglevel (Identifier => "Example.*",
                           Level      => Debug);

   --  This message will be logged because it matches a source specific
   --  loglevel (Example.*).
   Log.Log_Message (Source => "Example.Source1",
                    Level  => Debug,
                    Msg    => "This is a testmessage");

   --  This message will not be logged because of the configured default 'Info'
   --  loglevel. There's no configured source loglevel for 'Source2'.
   Log.Log_Message (Source => "Source2",
                    Level  => Debug,
                    Msg    => "This will not be logged");

   --  No source specified, will not be logged because of the default 'Info'
   --  loglevel.
   Log.Log_Message (Level => Debug,
                    Msg   => "This will not be logged");
end Policy_Example1;

The second policy example demonstrates the usage of destination filtering. Only log messages with loglevel Error or higher are written to the application error logfile. It shows how logging policies can be used to filter log messages depending on the destination (facility name).

with Alog.Policy_DB;
with Alog.Logger;
with Alog.Facilities.File_Descriptor;

use Alog;

--  Alog destination loglevel policy example.
procedure Policy_Example2 is
   Log    : Logger.Instance (Init => True);
   Errors : constant Facilities.File_Descriptor.Handle :=
     new Facilities.File_Descriptor.Instance;
begin
   --  Write all error messages to '/tmp/errors.log'.
   Errors.Set_Logfile (Path => "/tmp/errors.log");
   Errors.Set_Name (Name => "Application_Errors");
   Errors.Toggle_Write_Loglevel (State => True);

   --  Set loglevel policy to 'Error' for destination 'Application_Errors'.
   Policy_DB.Set_Loglevel (Identifier => "Application_Errors",
                           Level      => Error);

   Log.Attach_Facility (Facility => Facilities.Handle (Errors));

   --  This message will appear on stdout, but not in the error logfile.
   Log.Log_Message (Level  => Info,
                    Msg    => "This is not an error");
   --  This message will also be written to the error logfile.
   Log.Log_Message (Level  => Error,
                    Msg    => "This is an error");
end Policy_Example2;

Browse the source

  • You can browse the Alog source code with gitweb here.

Licence

Copyright (C) 2008-2011 Reto Buerki
Copyright (C) 2008-2011 Adrian-Ken Rueegsegger

Alog is free software; you can redistribute it and/or modify it under the terms
of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2.1 of the License, or (at your option) any later
version.