# Alog

- README

- CHANGELOG

- Download

## 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.

### 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.

### 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.*).
       if Policy_DB.Accept_Src (Identifier => "Example.Source1",
                                Level      => Debug)
       then
          Log.Log_Message (Source => "Example.Source1",
                           Level  => Debug,
                           Msg    => "This is a testmessage");
       end if;

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

       --  No source specified, will not be logged because of the default 'Info'
       --  loglevel.
       if Policy_DB.Accept_Src (Level => Debug) then
          Log.Log_Message (Level => Debug,
                           Msg   => "This will not be logged");
       end if;
    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-2014 Reto Buerki
    Copyright (C) 2008-2014 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.