Up

module Log

: sig

A library for general logging.

Although this module is fully Async-safe it exposes almost no Deferreds. This is partially a design choice to minimize the impact of logging in code, and partially the result of organic design (i.e. older versions of this interface did the same thing).

A (limited) Blocking module is supplied to accommodate the portion of a program that runs outside of Async.

#
module Level : sig
#
type t = [
| `Debug
| `Info
| `Error
]

Describes both the level of a log and the level of a message sent to a log. There is an ordering to levels (`Debug < `Info < `Error), and a log set to a level will never display messages at a lower log level.

include Core.Std.Stringable with type t := t
#
val arg : t Core.Std.Command.Spec.Arg_type.t
#
val t_of_sexp : Sexplib.Sexp.t -> t
#
val __t_of_sexp__ : Sexplib.Sexp.t -> t
#
val sexp_of_t : t -> Sexplib.Sexp.t
end
#
module Message : sig
#
type t
#
val time : t -> Core.Std.Time.t
#
val message : t -> string
#
val raw_message : t -> [
| `String of string
| `Sexp of Core.Std.Sexp.t
]
#
val level : t -> Level.t option
#
val tags : t -> (string * string) list
#
val add_tags : t -> (string * string) list -> t
#
module Stable : sig
#
module V0 : sig
include sig
#
type __pa_nonrec_0 = t
#
type t = __pa_nonrec_0
end
with type __pa_nonrec_0 := t
#
val t_of_sexp : Sexplib.Sexp.t -> t
#
val sexp_of_t : t -> Sexplib.Sexp.t
#
val bin_t : t Core.Std.Bin_prot.Type_class.t
#
val bin_read_t : t Core.Std.Bin_prot.Read.reader
#
val __bin_read_t__ : (int -> t) Core.Std.Bin_prot.Read.reader
#
val bin_reader_t : t Core.Std.Bin_prot.Type_class.reader
#
val bin_size_t : t Core.Std.Bin_prot.Size.sizer
#
val bin_write_t : t Core.Std.Bin_prot.Write.writer
#
val bin_writer_t : t Core.Std.Bin_prot.Type_class.writer
end
#
module V2 : sig
include sig
#
type __pa_nonrec_1 = t
#
type t = __pa_nonrec_1
end
with type __pa_nonrec_1 := t
#
val t_of_sexp : Sexplib.Sexp.t -> t
#
val sexp_of_t : t -> Sexplib.Sexp.t
#
val bin_t : t Core.Std.Bin_prot.Type_class.t
#
val bin_read_t : t Core.Std.Bin_prot.Read.reader
#
val __bin_read_t__ : (int -> t) Core.Std.Bin_prot.Read.reader
#
val bin_reader_t : t Core.Std.Bin_prot.Type_class.reader
#
val bin_size_t : t Core.Std.Bin_prot.Size.sizer
#
val bin_write_t : t Core.Std.Bin_prot.Write.writer
#
val bin_writer_t : t Core.Std.Bin_prot.Type_class.writer
end
end
#
val sexp_of_t : t -> Sexplib.Sexp.t
end
#
module Rotation : sig
#
type t

description of boundaries for file rotation.

If all fields are None the file will never be rotated. Any field set to Some will cause rotation to happen when that boundary is crossed. Multiple boundaries may be set. Log rotation always causes incrementing rotation conditions (e.g. size) to reset.

The condition keep is special and does not follow the rules above. When a log is rotated keep is examined and logs that do not fall under its instructions are deleted. This deletion takes place on rotation only, and so may not happen. The meaning of keep options are:

  • `All -- never delete
  • `Newer_than span -- delete files with a timestamp older than Time.sub (Time.now ()) span. This normally means keeping files that contain at least one message logged within span. If span is short enough this option can delete a just rotated file.
  • `At_least i -- keep the i most recent files

Log rotation does not support symlinks, and you're encouraged to avoid them in production applications. Issues with symlinks:

  • You can't tail symlinks without being careful (e.g. you must remember to pass "-F" to `tail`).
  • Symlinks are hard to reason about when the program crashes, especially on startup (i.e., is the symlink pointing me at the right log file?).
  • Atomicity is hard.
  • Symlinks encourage tailing, which is a bad way to communicate information.
  • They complicate archiving processes (the symlink must be skipped).
#
val create : ?messages:int -> ?size:Core.Std.Byte_units.t -> ?time:Core.Std.Time.Ofday.t -> ?zone:Core.Std.Time.Zone.t -> keep:[
| `All
| `Newer_than of Core.Std.Time.Span.t
| `At_least of int
] -> naming_scheme:[
| `Numbered
| `Timestamped
| `Dated
] -> unit -> t
#
val default : ?zone:Core.Std.Time.Zone.t -> unit -> t

Sane log rotation defaults.

Writes dated log files. Files are rotated every time the day changes in the given zone (uses the machine's zone by default). If the dated log file already exists, it's appended to.

Logs are never deleted. Best practice is to have an external mechanism archive old logs for long term storage.

#
val t_of_sexp : Sexplib.Sexp.t -> t
#
val sexp_of_t : t -> Sexplib.Sexp.t
end
#
module Output : sig
#
type machine_readable_format = [
| `Sexp
| `Sexp_hum
| `Bin_prot
]
#
type format = [
| `Text
]
#
type t
#
val create : (Message.t Core.Std.Queue.t -> unit Import.Deferred.t) -> t

create f returns a t, given a function that actually performs the final output work. It is the responsibility of the write function to contain all state, and to clean up after itself when it is garbage collected (which may require a finalizer).

The "stock" output modules support a sexp and bin_prot output format, and other output modules should make efforts to support them as well where it is meaningful/appropriate to do so.

The unit Deferred returned by the function should not be fulfilled until the all of the messages in the given queue are completely handled (e.g. written to disk).

#
val stdout : unit -> t
#
val stderr : unit -> t
#
val writer : format -> Import.Writer.t -> t
#
val file : format -> filename:string -> t
#
val rotating_file : format -> basename:string -> Rotation.t -> t

See [root:Async_extended].Std.Log for syslog and colorized console output.

#
val machine_readable_format_of_sexp : Sexplib.Sexp.t -> machine_readable_format
#
val __machine_readable_format_of_sexp__ : Sexplib.Sexp.t -> machine_readable_format
#
val sexp_of_machine_readable_format : machine_readable_format -> Sexplib.Sexp.t
#
val format_of_sexp : Sexplib.Sexp.t -> format
#
val __format_of_sexp__ : Sexplib.Sexp.t -> format
#
val sexp_of_format : format -> Sexplib.Sexp.t
end
#
module Blocking : sig

Async programs often have a non-Async portion that runs before the scheduler begins to capture command line options, do setup, read configs, etc. This module provides limited global logging functions to be used during that period. Calling these functions after the scheduler has started will raise an exception. They otherwise behave similarly to the logging functions in the Async world.

#
module Output : sig
#
type t
#
val stdout : t
#
val stderr : t

See [root:Async_extended].Std.Log for syslog and colorized console output.

#
val create : (Message.t -> unit) -> t
end
#
val level : unit -> Level.t
#
val set_level : Level.t -> unit
#
val set_output : Output.t -> unit
#
val raw : ?time:Core.Std.Time.t -> ?tags:(string * string) list -> ('a, unit, string, unit) Pervasives.format4 -> 'a

raw printf like logging for raw (no level) messages. Raw messages are still output with a timestamp.

#
val info : ?time:Core.Std.Time.t -> ?tags:(string * string) list -> ('a, unit, string, unit) Pervasives.format4 -> 'a

info printf like logging at the `Info log level

#
val error : ?time:Core.Std.Time.t -> ?tags:(string * string) list -> ('a, unit, string, unit) Pervasives.format4 -> 'a

error printf like logging at the `Info log level

#
val debug : ?time:Core.Std.Time.t -> ?tags:(string * string) list -> ('a, unit, string, unit) Pervasives.format4 -> 'a

error printf like logging at the `Info log level

end
#
type t
#
module type Global_intf = sig

An interface for singleton logs

#
val log : t Core.Std.Lazy.t
#
val level : unit -> Level.t
#
val set_level : Level.t -> unit
#
val set_output : Output.t list -> unit
#
val raw : ?time:Core.Std.Time.t -> ?tags:(string * string) list -> ('a, unit, string, unit) Pervasives.format4 -> 'a

logging functions as the functions that operate on a given log. In this case they operate on a single log global to the module

#
val info : ?time:Core.Std.Time.t -> ?tags:(string * string) list -> ('a, unit, string, unit) Pervasives.format4 -> 'a
#
val error : ?time:Core.Std.Time.t -> ?tags:(string * string) list -> ('a, unit, string, unit) Pervasives.format4 -> 'a
#
val debug : ?time:Core.Std.Time.t -> ?tags:(string * string) list -> ('a, unit, string, unit) Pervasives.format4 -> 'a
#
val flushed : unit -> unit Import.Deferred.t
#
val printf : ?level:Level.t -> ?time:Core.Std.Time.t -> ?tags:(string * string) list -> ('a, unit, string, unit) Pervasives.format4 -> 'a
#
val sexp : ?level:Level.t -> ?time:Core.Std.Time.t -> ?tags:(string * string) list -> 'a -> ('a -> Core.Std.Sexp.t) -> unit
#
val string : ?level:Level.t -> ?time:Core.Std.Time.t -> ?tags:(string * string) list -> string -> unit
#
val message : Message.t -> unit
end
#
module Make_global : functor () -> Global_intf

This functor can be called to generate "singleton" logging modules

#
module Global : Global_intf

Programs that want simplistic single-channel logging can open this module. It provides a global logging facility to a single output type at a single level. More nuanced logging can be had by using the functions that operate on a distinct Log.t type.

#
val set_level : t -> Level.t -> unit

set_level sets the level of the given log. Messages sent at a level less than the current level will not be output.

#
val level : t -> Level.t

level returns the last level passed to set_level, which will be the log level checked as a threshold against the level of the next message sent.

#
val set_output : t -> Output.t list -> unit

set_output changes the output type of the log, which can be useful when daemonizing. The new output type will be applied to all subsequent messages.

#
val close : t -> unit

close closes a log so that further write attempts will raise an error.

#
val flushed : t -> unit Import.Deferred.t

flushed returns a Deferred.t that is fulfilled when the last message delivered to t before the call to flushed is out the door.

#
val create : level:Level.t -> output:Output.t list -> t

create create a new log

#
val raw : ?time:Core.Std.Time.t -> ?tags:(string * string) list -> t -> ('a, unit, string, unit) Pervasives.format4 -> 'a

raw printf like logging for raw (no level) messages. Raw messages are still output with a timestamp.

#
val debug : ?time:Core.Std.Time.t -> ?tags:(string * string) list -> t -> ('a, unit, string, unit) Pervasives.format4 -> 'a

debug printf like logging at the `Debug log level

#
val info : ?time:Core.Std.Time.t -> ?tags:(string * string) list -> t -> ('a, unit, string, unit) Pervasives.format4 -> 'a

info printf like logging at the `Info log level

#
val error : ?time:Core.Std.Time.t -> ?tags:(string * string) list -> t -> ('a, unit, string, unit) Pervasives.format4 -> 'a

error printf like logging at the `Error log level

#
val printf : ?level:Level.t -> ?time:Core.Std.Time.t -> ?tags:(string * string) list -> t -> ('a, unit, string, unit) Pervasives.format4 -> 'a

printf generalized printf style logging

#
val sexp : ?level:Level.t -> ?time:Core.Std.Time.t -> ?tags:(string * string) list -> t -> 'a -> ('a -> Core.Std.Sexp.t) -> unit

sexp logging of values without first converting them to a string. In the case where the log level would discard this message no string conversion will ever be done.

#
val string : ?level:Level.t -> ?time:Core.Std.Time.t -> ?tags:(string * string) list -> t -> string -> unit

string logging of string values

#
module Reader : sig
#
val pipe : [< ] -> string -> Message.t Import.Pipe.Reader.t

pipe format filename returns a pipe of all the messages in the log. Errors encountered when opening or reading the file will be thrown as exceptions into the monitor current at the time pipe is called.

end
#
val sexp_of_t : t -> Sexplib.Sexp.t
end