lwt

Promises, concurrency, and parallelized I/O
IN THIS PACKAGE
Module Lwt_log
include module type of Lwt_log_core with type level = Lwt_log_core.level and type logger = Lwt_log_core.logger and type section = Lwt_log_core.section and type template = Lwt_log_core.template and module Section = Lwt_log_core.Section

This module provides functions to deal with logging. It support:

  • logging to multiple destination at the same time
  • filtering logs per destination

Types

type level = Lwt_log_core.level =
| Debug(*

Debugging message. They can be automatically removed by the syntax extension.

*)
| Info(*

Informational message. Suitable to be displayed when the program is in verbose mode.

*)
| Notice(*

Same as Info, but is displayed by default.

*)
| Warning(*

Something strange happend

*)
| Error(*

An error message, which should not means the end of the program.

*)
| Fatal(*

A fatal error happened, in most cases the program will end after a fatal error.

*)

Type of log levels. A level determines the importance of a message

type logger = Lwt_log_core.logger

Type of a logger. A logger is responsible for dispatching messages and storing them somewhere.

type section = Lwt_log_core.section

Each logging message has a section. Sections can be used to structure your logs. For example you can choose different loggers according to the section.

Each section carries a level, and messages with a lower log level than than the section level will be dropped.

Section levels are initialised using the contents of the LWT_LOG environment variable, which must contain one or more rules of the form pattern -> level separated by ";". Where pattern is a string that may contain *.

For example, if LWT_LOG contains:

access -> warning;
foo[*] -> error

then the level of the section "access" is Warning and the level of any section matching "foo[*]" is Error.

If the pattern is omited in a rule then the pattern "*" is used instead, so LWT_LOG may just contain "debug" for instance.

By default, the following rule apply : "* -> notice"

val string_of_level : level -> string
val level_of_string : string -> level option
val load_rules : ?fail_on_error:bool -> string -> unit

Reset the rules set when parsing the LWT_LOG environment variable using this string.

  • parameter fail_on_error

    defines if the function will raise Failure if it encounters a malformed rule

  • raises Failure

    if an invalid rule is found and fail_on_error is true

    load_rules parses the rules string and validates the rules before loading them. If fail_on_error is true, invalid rules will cause this function to raise Failure and leave existing rules unchanged. If fail_on_error is false (this is the default), it tries to load as many rules as possible and ignore invalid ones. If the rules string itself cannot be parsed, existing rules are always left unchanged.

    Example:

    Lwt_log_core.load_rules ~fail_on_error:true "* -> nosuchlevel" (* Raises Failure *)
    Lwt_log_core.load_rules "* -> info"
val add_rule : string -> level -> unit

add_rule pattern level adds a rule for sections logging levels. The rule is added before all other rules. It takes effect immediately and affects all sections for which the level has not been set explicitly with Section.set_level. pattern may contains *. For example:

Lwt_log_core.add_rule "lwt*" Lwt_log_core.Info
val append_rule : string -> level -> unit

append_rule pattern level adds the given rule after all other rules. For example to set the default fallback rule:

Lwt_log_core.append_rule "*" Lwt_log_core.Info
val reset_rules : unit -> unit

removes all rules.

Logging functions

val log : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> level:level -> string -> unit Lwt.t

log ?section ?logger ~level message logs a message.

section defaults to Section.main. If logger is not specified, then the default one is used instead (see default).

If exn is provided, then its string representation (= Printexc.to_string exn) will be append to the message, and if possible the backtrace will also be logged.

location contains the location of the logging directive, it is of the form (file_name, line, column).

val log_f : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> level:level -> ( 'a, unit, string, unit Lwt.t ) Pervasives.format4 -> 'a

log_f is the same as log except that it takes a format string

val ign_log : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> level:level -> string -> unit

Same as log but ignore the resulting thread.

val ign_log_f : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> level:level -> ( 'a, unit, string, unit ) Pervasives.format4 -> 'a

Same as log_f but ignore the resulting thread.

The following functions are the same as log except that their name determines which level is used.

For example info msg is the same as log ~level:Info msg.

val debug : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> string -> unit Lwt.t
val debug_f : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> ( 'a, unit, string, unit Lwt.t ) Pervasives.format4 -> 'a
val ign_debug : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> string -> unit
val ign_debug_f : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> ( 'a, unit, string, unit ) Pervasives.format4 -> 'a
val info : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> string -> unit Lwt.t
val info_f : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> ( 'a, unit, string, unit Lwt.t ) Pervasives.format4 -> 'a
val ign_info : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> string -> unit
val ign_info_f : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> ( 'a, unit, string, unit ) Pervasives.format4 -> 'a
val notice : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> string -> unit Lwt.t
val notice_f : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> ( 'a, unit, string, unit Lwt.t ) Pervasives.format4 -> 'a
val ign_notice : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> string -> unit
val ign_notice_f : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> ( 'a, unit, string, unit ) Pervasives.format4 -> 'a
val warning : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> string -> unit Lwt.t
val warning_f : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> ( 'a, unit, string, unit Lwt.t ) Pervasives.format4 -> 'a
val ign_warning : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> string -> unit
val ign_warning_f : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> ( 'a, unit, string, unit ) Pervasives.format4 -> 'a
val error : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> string -> unit Lwt.t
val error_f : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> ( 'a, unit, string, unit Lwt.t ) Pervasives.format4 -> 'a
val ign_error : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> string -> unit
val ign_error_f : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> ( 'a, unit, string, unit ) Pervasives.format4 -> 'a
val fatal : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> string -> unit Lwt.t
val fatal_f : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> ( 'a, unit, string, unit Lwt.t ) Pervasives.format4 -> 'a
val ign_fatal : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> string -> unit
val ign_fatal_f : ?exn:exn -> ?section:section -> ?location:(string * int * int) -> ?logger:logger -> ( 'a, unit, string, unit ) Pervasives.format4 -> 'a
module Section = Lwt_log_core.Section

Sections

Log templates

type template = Lwt_log_core.template

A template is for generating log messages.

It is a string which may contains variables of the form $(var), where var is one of:

  • message which will be replaced by the message emited
  • level which will be replaced by a string representation of the level
  • section which will be replaced by the name of the message's section
  • loc-file which will be replaced by the file name of the calling logging function
  • loc-line which will be replaced by the line number of the calling logging function
  • loc-column which will be replaced by the column number of the calling logging function

For example:

  • "$(name): $(message)"
  • "$(name): $(loc-file): $(loc-line): $(loc-column): $(message)"
val location_key : (string * int * int) Lwt.key

The key for storing current location.

Loggers

exception Logger_closed

Exception raised when trying to use a closed logger

val make : output:( section -> level -> string list -> unit Lwt.t ) -> close:( unit -> unit Lwt.t ) -> logger

make ~output ~close creates a new logger.

  • parameter output

    is used to write logs. It is a function which receive a section, a level and a list lines that must be logged together.

  • parameter close

    is used to close the logger.

val close : logger -> unit Lwt.t

Close the given logger

val default : logger Pervasives.ref

The default logger. It is used as default when no one is specified. If Lwt_core is linked (in the package lwt.unix) the default logger sends all messages to standard error. Otherwise the default logger is null.

val broadcast : logger list -> logger

broadcast loggers is a logger which send messages to all the given loggers.

Note: closing a broadcast logger does not close its components.

val dispatch : ( section -> level -> logger ) -> logger

dispatch f is a logger which dispatch logging instructions to different logger according to their level and/or section.

Here is an example:

let access_logger = Lwt_log.file "access.log"
and error_logger = Lwt_log.file "error.log" in

Lwt_log_core.dispatch
  (fun section level ->
    match Lwt_log_core.Section.name section, level with
      | "access", _ -> access_logger
      | _, Lwt_log_core.Error -> error_logger)

Predefined loggers

val null : logger

Logger which drops everything

val render : buffer:Buffer.t -> template:template -> section:section -> level:level -> message:string -> unit

Same as Lwt_log_core.render, except that the template may also contain the following variables:

  • date, which will be replaced with the current local date and time,
  • milliseconds, which will be replaced by the fractional part of the current Unix time, to millisecond accuracy.

For example:

  • "$(date) $(name)[$(pid)]: $(message)"
  • "$(date).$(milliseconds) $(name)[$(pid)]: $(message)"
  • "$(date): $(loc-file): $(loc-line): $(loc-column): $(message)"
type syslog_facility = [
| `Auth
| `Authpriv
| `Cron
| `Daemon
| `FTP
| `Kernel
| `Local0
| `Local1
| `Local2
| `Local3
| `Local4
| `Local5
| `Local6
| `Local7
| `LPR
| `Mail
| `News
| `Syslog
| `User
| `UUCP
| `NTP
| `Security
| `Console
]

Syslog facility. Look at the SYSLOG(3) man page for a description of syslog facilities

val syslog : ?template:template -> ?paths:string list -> facility:syslog_facility -> unit -> logger

syslog ?template ?paths ~facility () creates an logger which send message to the system logger.

  • parameter paths

    is a list of path to try for the syslogd socket. It default to ["/dev/log"; "/var/run/log"].

  • parameter template

    defaults to "$(date) $(name)[$(pid)]: $(section): $(message)"

val file : ?template:template -> ?mode:[ `Truncate | `Append ] -> ?perm:Unix.file_perm -> file_name:string -> unit -> logger Lwt.t

desf_file ?template ?mode ?perm ~file_name () creates an logger which will write messages to file_name.

  • if mode = `Truncate then the file is truncated and previous contents will be lost.
  • if mode = `Append, new messages will be appended at the end of the file
  • parameter mode

    defaults to `Append

  • parameter template

    defaults to "$(date): $(section): $(message)"

val channel : ?template:template -> close_mode:[ `Close | `Keep ] -> channel:Lwt_io.output_channel -> unit -> logger

channel ?template ~close_mode ~channel () creates a logger from a channel.

If close_mode = `Close then channel is closed when the logger is closed, otherwise it is left open.

  • parameter template

    defaults to "$(name): $(section): $(message)"