package easy_logging

  1. Overview
  2. Docs


Easy logging

Logging infrastructure inspired by the Python logging module. The aim of this module is to provide a quick and easy to use logging infrastructure.

It has the following features :

  • one line logger creation
  • log messages printf style, or provide string or string lazy_t message
  • loggers for tree architecture for easy level configuration
  • handlers associated to each logger will filter, format and treat the message independantly
  • use the infrastructure with your own handlers with the MakeLogging functor.
  • use tags to add contextual information to log messages
Basic example
open Easy_logging
logger = Logging.make_logger "my_logger" (Some Debug) [Cli Debug]
logger#info "log_message" 

will output to the stdout a message of the form

1.306  my_logger    Info    log_message

Table of contents

  1. Overall description (see also Easy_logging)
  2. Defaults

    1. Handlers (see also Easy_logging__Handlers)
    2. Loggers (see also Easy_logging.Logging.logger )
    3. The Logging module (see also Easy_logging.Logging)
  3. The MakeLogging functor (see also Easy_logging__Make_logging.MakeLogging )
  4. More examples
  5. Index of modules

Overall description

The logging infrastructure is based on four concepts:

loggers, handlers, log items and logging tree.

A call to logger will create a log item, which it will pass to its handlers. Each handler will treats the item (e.g. transform it to a string, and then outputs to stdout or to a file).

                                    | handler 1 |
               _______________      |-----------|
              |     logger    | ==> |   ( * )   |
              |---------------|     |___________|
(message) ==> | -> log item   |      ___________
              [_______________| ==> | handler 2 |
                                    |   ...     |

Logging tree

Loggers are stored in a tree structure, with the following properties :

  • messages handled by a logger (after level filtering) are passed to its ancestor's handlers (this can be overriden with the set_propagate method).
  • if not set, the level of a logger is that of its closest ancestor whose level is set (or NoLevel if there is no such ancestor)
                       A (Info, Cli Debug)
                     /    \
                  A.B      A.C
                 /            \
            A.B.D (Warning)    A.C.E (Debug, (File "f", Debug),

For example, with the above logging tree

  • logs made to A, A.B or A.C of level Info or more are written to the stdout.
  • logs made to A.B.D of level Warning or above are written the stdout.
  • logs made to A.C.E are only written to the file "f"


To each logger and log message are associated a level, which will be used to filter the messages going through the logging infrastructure.

The predefined levels are, in increasing order of precedence :

  1. Debug : used for debugging.
  2. Trace : used between info and debug
  3. Info : used to trace program execution.
  4. Warning : used for warnings.
  5. Error : used for errors.
  6. Flash : used for one-shot debugging: displays an easy to spot message.
  7. NoLevel : used to filter out all messages.

Log items

A log item has type

type log_item = {
    level : level;          (* the level of the log item *)
    logger_name : string;   (* the name of the logger to which the log call was passed *)
    msg : string;           (* the actual log message *)
    tags : string list      (* a list of tags *)



Three handler creation helper function are provided. They instantiate handlers with a level of their own to filter messages :

  • Cli handler: outputs colored messages to stdout.

    let h = Default_handlers.make (Cli Debug) 
  • CliErr handler: outputs colored messages to stderr.

    let h = Default_handlers.make (CliErr Debug) 
  • File handler : outputs messages to a given file.

    let h = Default_handlers.make (File ("filename", Debug)) 

Note that file handlers will write to files in the logs folder in the current path, creating it if it doesn't exist.

See more at Easy_logging.Handlers


See complete class documentation at Easy_logging.Logging.logger


A logger object can be created directly (in which case it will not be part of the logging tree)

let logger1 = new Logging.logger "my_logger1" 

or through helper functions of the The Logging module module.


A logger object has three methods for each of the log levels:

  • one that takes a formatting string and parameters (printf like)

    logger1#debug "Myvar : %s" (to_string myvar); 
  • one that takes a string lazy_t

    logger1#ldebug (lazy (heavy_calculation ())); 
  • one that takes a string

    logger1#sdebug (to_string myvar);

The Logging module

The Easy_logging.Logging module is that application of MakeLogging over Handlers. It provides two functions :

  • val make_logger :
    ?propagate:bool -> string -> log_level -> Default_handlers.desc list 

    Instantiates a logger with some paramters, and adds it to the logging tree.

  • val get_logger : string -> logger 

    Returns a registered logger, or creates a new one if it doesn't exist.

The MakeLogging functor

The MakeLogging functor takes a Easy_logging__.Easy_logging_types.HandlersT typed module, and creates a Logging module.


When declaring your Handlers module, do not coerce it the type HandlersT, because then its internal types t and desc won't be accessible.


See the examples page for more examples.

Index of modules

  1. Easy_logging__Colorize
  2. Easy_logging
  3. Easy_logging__Formatters
  4. Easy_logging__Handlers
  5. Easy_logging__Logging_infra
  6. Easy_logging__Logging_types
  7. Easy_logging__Make_logging

Innovation. Community. Security.