Easy_logging 0.2

Hello,
feeling that there was some lack of logging librairies for OCaml (apart from the Logs module, which was a bit too complicated to use for me), I wrote a (hopefully) both easy to use and yet powerful logging library, taking inspiration from the excellent Python logging package.

Some defaults are provided that allow logging to the stdout and/or files, but it is also possible to redefine you own handlers.

Sources and Documentation are provided.

Any comment or suggestion would be appreciated.

5 Likes

I believe support for printf-style strings for creating log messages would be useful. Formatting strings even when they are not used because of the log priority can introduce a performance concern, though.

Hello lindig,
I think I will eventually add support for format strings, but for now you can use the logging methods that take a lazy string as an input, for example

 logging#ldebug ( lazy (Printf.sprintf "%s" mystring))

see lazy logging methods.

2 Likes

How does this compare to Async’s Log module, which is generally used as follows:

Log.Global.info "Message %d" count
Log.Global.warn_s [%message "Issue connecting to db" (db : string)]

Hello mc10,
I have never used Async, so I didn’t know about that module. It seems quite close to what I had in mind, and provides most of what easy_logging does, and much more.

Instead of instantiating modules (like Log.Global) as so called logging singletons, Easy_logging instantiates logger objects:

open Easy_logging
logger = Logging.make_logger "my_logger" (Some Debug) [Cli Debug];;
logger#info "log_message";; 

This is by design, since logger objects are registered and stored at creation (in a Logging module), to be able to modify the log level all logging singletons at runtime (see Logging module and example).
(Maybe I’ll switch to modules instead of classes as logging singletons, using first-class modules to registration, but for now it’s a bit easier for me to go with objects).

The second difference is that a Logging module can be created by a functor over a module of Handlers (things to write to stdout/files/etc), making it easy to define the handlers according to your needs (although Async’s log defaults seems quite enough).

Anyway Async’s Logging will be a great source of inspiration for me, thanks for pointing it out !

Version 0.4 is out (or should be soon) :

  • printf style logging is now the default
  • simplifed configuration in case of multiple loggers (and closer to the python module) :
    the loggers form a tree (based on their name, dots indicating descendence)
    • log items are passed to the handlers of a logger’s ancestors (so that few handlers need initialisation) (possible to override)
    • loggers inherit the level of their ancestor if not set explicitely
  • an additional package easy_logging_yojson provides initialisation of loggers from the json format (with ppx_deriving_yojson), so that configuration can be fully done outside the code.
3 Likes

Hi,

I am using “easy_logging” in one of my side projects. I noticed the log file is truncated every time I execute the program. I am expecting new log entries appended to the log file till it reaches 65536 KB. Below is the code to create logger and logging. Am i missing something? Thanks.

let get_logger lname fname =
  let open Easy_logging in
  let h_config : Handlers.config =
    {
      file_handlers =
        {
          logs_folder = "logs/";
          truncate = false;
          file_perms = 0o664;
          date_prefix = Some "%Y%m%d_";
          versioning = None;
          suffix = ".log";
        };
    }
  in
  Logging.set_handlers_config h_config;
  Logging.make_logger lname Debug [ RotatingFile (fname, Debug, 65536, 2) ]

let () =
  let logger = get_logger "rdf_parsing" "catalog" in
  try
    logger#info "%s" "Getting settings...";
    (** program logic here **)

    logger#info "Total files [%d]. Start parsing..." (List.length files);
   
  with _ ->
    logger#error "%s"
      ("Error occured while decoding rdf file.\n" ^ Printexc.get_backtrace ())

1 Like

“lack of logging libraries” ?!

I would not say logging is a field where the OCaml open-source
bazaar is lacking. :grinning_face_with_smiling_eyes:

# opam search logging | grep -v blog
# Packages matching: match(*logging*)
# Name              # Installed # Synopsis
bolt                --          Bolt is an OCaml Logging Tool
charrua-core        --          Charrua DHCP core library.
docout              --          Functor to create (text) output functions
dolog               6.0.0       The dumb OCaml logging library
dtools              --          Library providing various helper functions to make daemons
easy_logging        --          Module to log messages. Aimed at being both powerful and easy to use
easy_logging_yojson --          Configuration loader for easy_logging with yojson backend
loga                --          Logging library for OCaml
logger-p5           --          Camlp5 syntax extension for logging
logs                0.7.0       Logging infrastructure for OCaml
logs-async          --          Jane Street Async logging with Logs
logs-ppx            --          PPX to cut down on boilerplate when using Logs
logs-syslog         --          Logs reporter to syslog (UDP/TCP/TLS)
lwt_log             1.1.1       Lwt logging library (deprecated)
ocaml-systemd       --          OCaml module for native access to the systemd facilities
sihl                --          The Sihl web framework
sihl-core           --          The core of the Sihl web framework
taglog              --          Logging library using levels and tags to determine what to log.
tezos-event-logging --          Tezos event logging library
volt                --          Volt is a variant of Bolt OCaml Logging Tool
1 Like