317 lines
12 KiB
OCaml
317 lines
12 KiB
OCaml
(* Lightweight thread library for Objective Caml
|
|
* http://www.ocsigen.org/lwt
|
|
* Interface Lwt_log
|
|
* Copyright (C) 2002 Shawn Wagner <raevnos@pennmush.org>
|
|
* 2009 Jérémie Dimino <jeremie@dimino.org>
|
|
*
|
|
* This program 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, with linking exceptions;
|
|
* either version 2.1 of the License, or (at your option) any later
|
|
* version. See COPYING file for details.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
* 02111-1307, USA.
|
|
*)
|
|
|
|
(** Logging facility *)
|
|
|
|
(** This module provides functions to deal with logging.
|
|
It support:
|
|
|
|
- logging to the syslog daemon
|
|
- logging to a channel (stderr, stdout, ...)
|
|
- logging to a file
|
|
- logging to multiple destination at the same time
|
|
*)
|
|
|
|
(** {6 Types} *)
|
|
|
|
(** Type of log levels. A level determines the importance of a
|
|
message *)
|
|
type 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 logger
|
|
(** Type of a logger. A logger is responsible for dispatching messages
|
|
and storing them somewhere.
|
|
|
|
Lwt provides loggers sending log messages to a file, syslog,
|
|
... but you can also create you own logger. *)
|
|
|
|
type 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 [LWT_LOG] environment
|
|
variable, which must contains 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 contains ["debug"] for
|
|
instance.
|
|
|
|
If [LWT_LOG] is not defined then the rule ["* -> notice"] is
|
|
used instead. *)
|
|
|
|
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 immediatly and affect all sections for which the level
|
|
has not been set explicitly with {!Section.set_level}. [pattern]
|
|
may contains [*]. For example:
|
|
|
|
{[
|
|
Lwt_log.add_rule "lwt*" Lwt_log.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.append_rule "*" Lwt_log.Info
|
|
]}
|
|
*)
|
|
|
|
(** {6 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) format4 -> 'a
|
|
(** [log_f] is the same as [log] except that it takes a format
|
|
string *)
|
|
|
|
(** 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) 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) 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) 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) 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) 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) format4 -> 'a
|
|
|
|
(** Sections *)
|
|
module Section : sig
|
|
type t = section
|
|
|
|
val make : string -> section
|
|
(** [make name] creates a section with the given name. Two calls
|
|
to {!make} with the same name will return the same section
|
|
object. *)
|
|
|
|
val name : section -> string
|
|
(** [name section] returns the name of [section]. *)
|
|
|
|
val main : section
|
|
(** The main section. It is the section used by default when no
|
|
one is provided. *)
|
|
|
|
val level : section -> level
|
|
(** [level section] returns the logging level of [section]. *)
|
|
|
|
val set_level : section -> level -> unit
|
|
(** [set_level section] sets the logging level of the given
|
|
section. Modifications of rules using {!add_rule} won't affect
|
|
the level of this section after this operation. *)
|
|
|
|
val reset_level : section -> unit
|
|
(** [reset_level section] resets the level of [section] to its
|
|
default value, i.e. to the value obtained by applying
|
|
rules. *)
|
|
end
|
|
|
|
(** {6 Log templates} *)
|
|
|
|
type template = string
|
|
(** A template is for generating log messages.
|
|
|
|
It is a string which may contains variables of the form
|
|
[$(var)], where [var] is one of:
|
|
|
|
- [date] which will be replaced with the current date
|
|
- [milliseconds] which will be replaced by the fractionnal part
|
|
of the current unix time
|
|
- [name] which will be replaced by the program name
|
|
- [pid] which will be replaced by the pid of the program
|
|
- [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)"]
|
|
- ["$(date) $(name)[$(pid)]: $(message)"]
|
|
- ["$(date).$(milliseconds) $(name)[$(pid)]: $(message)"]
|
|
- ["$(date): $(loc-file): $(loc-line): $(loc-column): $(message)"]
|
|
*)
|
|
|
|
val render : buffer : Buffer.t -> template : template -> section : section -> level : level -> message : string -> unit
|
|
(** [render ~buffer ~template ~section ~level ~message] instantiate
|
|
all variables of [template], and store the result in
|
|
[buffer]. The location is obtained from threads local
|
|
storage. *)
|
|
|
|
val location_key : (string * int * int) Lwt.key
|
|
(** The key for storing current location. *)
|
|
|
|
(** {6 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.
|
|
|
|
@param 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.
|
|
@param close is used to close the logger. *)
|
|
|
|
val close : logger -> unit Lwt.t
|
|
(** Close the given logger *)
|
|
|
|
val default : logger ref
|
|
(** The default logger. It is used as default when no one is
|
|
specified. Initially, it sends messages to the standard output
|
|
for error messages. *)
|
|
|
|
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.dispatch
|
|
(fun section level ->
|
|
match Lwt_log.Section.name section, level with
|
|
| "access", _ -> access_logger
|
|
| _, Lwt_log.Error -> error_logger)
|
|
]}
|
|
*)
|
|
|
|
(** {6 Predefined loggers} *)
|
|
|
|
val null : logger
|
|
(** Logger which drops everything *)
|
|
|
|
(** Syslog facility. Look at the SYSLOG(3) man page for a description
|
|
of syslog facilities *)
|
|
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 ]
|
|
|
|
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.
|
|
|
|
@param paths is a list of path to try for the syslogd socket. It
|
|
default to [\["/dev/log"; "/var/run/log"\]].
|
|
@param 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
|
|
|
|
@param mode defaults to [`Append]
|
|
@param 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.
|
|
|
|
@param template defaults to ["$(name): $(section): $(message)"] *)
|