diff --git a/META.js_of_ocaml.template b/META.js_of_ocaml.template index 2b2ba824d5..86e5b0901c 100644 --- a/META.js_of_ocaml.template +++ b/META.js_of_ocaml.template @@ -24,6 +24,10 @@ package "graphics" ( requires = "js_of_ocaml-lwt.graphics" ) +package "log" ( + requires = "js_of_ocaml-lwt.logger" +) + package "ocamlbuild" ( requires = "js_of_ocaml-ocamlbuild" ) diff --git a/doc/Makefile b/doc/Makefile index 61ba945803..8703c6b13d 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -10,8 +10,8 @@ MLIS+=$(wildcard ${SRC_DIR}ocamlbuild/*.mli) OTHER+=-I ${CMI_DIR}lib -package ocamlbuild -I ${CMI_DIR}ocamlbuild -I ../_build/install/default/lib/js_of_ocaml -I ../_build/install/default/lib/js_of_ocaml/deriving -I ../_build/install/default/lib/js_of_ocaml-tyxml ifeq "${WITH_LWT}" "YES" -OTHER += -package lwt -I ${CMI_DIR}lib/lwt -MLIS+=$(wildcard ${SRC_DIR}lib/lwt/*.mli) +OTHER += -package lwt -I ${CMI_DIR}lib/lwt -I ${CMI_DIR}lib/lwt/log +MLIS+=$(wildcard ${SRC_DIR}lib/lwt/*.mli) $(wildcard ${SRC_DIR}lib/lwt/log/*.mli) ifeq "${WITH_GRAPHICS}" "YES" OTHER+=-package graphics -I ${CMI_DIR}lib/lwt/graphics MLIS+=$(wildcard ${SRC_DIR}lib/lwt/graphics/*.mli) diff --git a/doc/api/index b/doc/api/index index 576bba98f8..dea55726e9 100644 --- a/doc/api/index +++ b/doc/api/index @@ -38,6 +38,12 @@ Lwt_js_events Lwt_js } +{2 Lwt logger - API Reference} + +{!modules: +Lwt_log_js +} + {2 Graphics - API Reference} {!modules: diff --git a/lib/lwt/log/jbuild b/lib/lwt/log/jbuild new file mode 100644 index 0000000000..a23e2926bc --- /dev/null +++ b/lib/lwt/log/jbuild @@ -0,0 +1,8 @@ +(jbuild_version 1) +(library + ((name lwt_log_js) + (public_name js_of_ocaml-lwt.logger) + (synopsis "Lwt logger for js_of_ocaml.") + (optional) + (libraries (js_of_ocaml lwt lwt.log)) + (preprocess (pps (js_of_ocaml-ppx))))) diff --git a/lib/lwt/log/lwt_log_js.ml b/lib/lwt/log/lwt_log_js.ml new file mode 100644 index 0000000000..b66803f48a --- /dev/null +++ b/lib/lwt/log/lwt_log_js.ml @@ -0,0 +1,99 @@ +(* Js_of_ocaml library + * http://www.ocsigen.org/js_of_ocaml/ + * Copyright (C) 2014 Hugo Heuzard + * + * 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 exception; + * either version 2.1 of the License, or (at your option) any later version. + * + * 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. + *) + +include Lwt_log_core +open Js_of_ocaml +let js_val = Lwt.new_key () + +let console = make + ~close:(fun _ -> Lwt.return_unit) + ~output:(fun section level logs -> + let str = + (Js.string + (Printf.sprintf "[%s] %s" (Section.name section) (String.concat "\n" logs))) + in + (match level,Lwt.get js_val with + | Debug,None -> Firebug.console##debug str + | Debug,Some v -> Firebug.console##debug_2 str v + + | Info,None + | Notice,None -> Firebug.console##info str + | Info,Some v + | Notice,Some v -> Firebug.console##info_2 str v + + | Warning,None -> Firebug.console##warn str + | Warning,Some v -> Firebug.console##warn_2 str v + + | Error,None + | Fatal,None -> Firebug.console##error str + | Error,Some v + | Fatal,Some v -> Firebug.console##error_2 str v + ); + Lwt.return_unit + ) + +let log ?inspect ?exn ?section ?location ?logger ~level message = + let inspect = match inspect with None -> None | Some v -> Some (Obj.repr v) in + Lwt.with_value js_val inspect (fun () -> + log ?exn ?section ?location ?logger ~level message + ) +let log_f ?inspect ?exn ?section ?location ?logger ~level format = + Printf.ksprintf (log ?inspect ?exn ?section ?location ?logger ~level) format + +let ign_log ?inspect ?exn ?section ?location ?logger ~level message = + try + ignore (log ?inspect ?exn ?section ?location ?logger ~level message) + with _ -> + () + +let ign_log_f ?inspect ?exn ?section ?location ?logger ~level format = + Printf.ksprintf (ign_log ?inspect ?exn ?section ?location ?logger ~level) format + +let debug ?inspect ?exn ?section ?location ?logger msg = log ?inspect ?exn ?section ?location ?logger ~level:Debug msg +let debug_f ?inspect ?exn ?section ?location ?logger fmt = Printf.ksprintf (debug ?inspect ?exn ?section ?location ?logger) fmt +let info ?inspect ?exn ?section ?location ?logger msg = log ?inspect ?exn ?section ?location ?logger ~level:Info msg +let info_f ?inspect ?exn ?section ?location ?logger fmt = Printf.ksprintf (info ?inspect ?exn ?section ?location ?logger) fmt +let notice ?inspect ?exn ?section ?location ?logger msg = log ?inspect ?exn ?section ?location ?logger ~level:Notice msg +let notice_f ?inspect ?exn ?section ?location ?logger fmt = Printf.ksprintf (notice ?inspect ?exn ?section ?location ?logger) fmt +let warning ?inspect ?exn ?section ?location ?logger msg = log ?inspect ?exn ?section ?location ?logger ~level:Warning msg +let warning_f ?inspect ?exn ?section ?location ?logger fmt = Printf.ksprintf (warning ?inspect ?exn ?section ?location ?logger) fmt +let error ?inspect ?exn ?section ?location ?logger msg = log ?inspect ?exn ?section ?location ?logger ~level:Error msg +let error_f ?inspect ?exn ?section ?location ?logger fmt = Printf.ksprintf (error ?inspect ?exn ?section ?location ?logger) fmt +let fatal ?inspect ?exn ?section ?location ?logger msg = log ?inspect ?exn ?section ?location ?logger ~level:Fatal msg +let fatal_f ?inspect ?exn ?section ?location ?logger fmt = Printf.ksprintf (fatal ?inspect ?exn ?section ?location ?logger) fmt + +let ign_debug ?inspect ?exn ?section ?location ?logger msg = ign_log ?inspect ?exn ?section ?location ?logger ~level:Debug msg +let ign_debug_f ?inspect ?exn ?section ?location ?logger fmt = Printf.ksprintf (ign_debug ?inspect ?exn ?section ?location ?logger) fmt +let ign_info ?inspect ?exn ?section ?location ?logger msg = ign_log ?inspect ?exn ?section ?location ?logger ~level:Info msg +let ign_info_f ?inspect ?exn ?section ?location ?logger fmt = Printf.ksprintf (ign_info ?inspect ?exn ?section ?location ?logger) fmt +let ign_notice ?inspect ?exn ?section ?location ?logger msg = ign_log ?inspect ?exn ?section ?location ?logger ~level:Notice msg +let ign_notice_f ?inspect ?exn ?section ?location ?logger fmt = Printf.ksprintf (ign_notice ?inspect ?exn ?section ?location ?logger) fmt +let ign_warning ?inspect ?exn ?section ?location ?logger msg = ign_log ?inspect ?exn ?section ?location ?logger ~level:Warning msg +let ign_warning_f ?inspect ?exn ?section ?location ?logger fmt = Printf.ksprintf (ign_warning ?inspect ?exn ?section ?location ?logger) fmt +let ign_error ?inspect ?exn ?section ?location ?logger msg = ign_log ?inspect ?exn ?section ?location ?logger ~level:Error msg +let ign_error_f ?inspect ?exn ?section ?location ?logger fmt = Printf.ksprintf (ign_error ?inspect ?exn ?section ?location ?logger) fmt +let ign_fatal ?inspect ?exn ?section ?location ?logger msg = ign_log ?inspect ?exn ?section ?location ?logger ~level:Fatal msg +let ign_fatal_f ?inspect ?exn ?section ?location ?logger fmt = Printf.ksprintf (ign_fatal ?inspect ?exn ?section ?location ?logger) fmt + + +(*let raise_error ?inspect ?exn ?section ?location ?logger msg = + Lwt.ignore_result (log ?inspect ?exn ?section ?location ?logger ~level:Error msg); + failwith msg *) +(*let raise_error_f ?inspect ?exn ?section ?location ?logger fmt = + Printf.ksprintf (raise_error ?inspect ?exn ?section ?location ?logger) fmt *) diff --git a/lib/lwt/log/lwt_log_js.mli b/lib/lwt/log/lwt_log_js.mli new file mode 100644 index 0000000000..d6d65a118e --- /dev/null +++ b/lib/lwt/log/lwt_log_js.mli @@ -0,0 +1,98 @@ +(* Js_of_ocaml library + * http://www.ocsigen.org/js_of_ocaml/ + * Copyright (C) 2014 Hugo Heuzard + * + * 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 exception; + * either version 2.1 of the License, or (at your option) any later version. + * + * 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. + *) + + +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 + +(** Lwt logger for js_of_ocaml *) + +(** {2 Predefined logger} *) + +val console : Lwt_log.logger +(** Logger that use the javascript console object. *) + + +(** {2 Logging functions} *) + +val log : ?inspect : 'v -> ?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. + + If [inspect] is provided, it will be append to the message. + + [location] contains the location of the logging directive, it is + of the form [(file_name, line, column)]. *) + +val log_f : ?inspect : 'v -> ?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 *) + +val ign_log : ?inspect : 'v -> ?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 : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> level : level -> ('a, unit, string, unit) 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 : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> string -> unit Lwt.t +val debug_f : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> ('a, unit, string, unit Lwt.t) format4 -> 'a +val ign_debug : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> string -> unit +val ign_debug_f : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> ('a, unit, string, unit) format4 -> 'a + +val info : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> string -> unit Lwt.t +val info_f : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> ('a, unit, string, unit Lwt.t) format4 -> 'a +val ign_info : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> string -> unit +val ign_info_f : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> ('a, unit, string, unit) format4 -> 'a + +val notice : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> string -> unit Lwt.t +val notice_f : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> ('a, unit, string, unit Lwt.t) format4 -> 'a +val ign_notice : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> string -> unit +val ign_notice_f : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> ('a, unit, string, unit) format4 -> 'a + +val warning : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> string -> unit Lwt.t +val warning_f : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> ('a, unit, string, unit Lwt.t) format4 -> 'a +val ign_warning : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> string -> unit +val ign_warning_f : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> ('a, unit, string, unit) format4 -> 'a + +val error : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> string -> unit Lwt.t +val error_f : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> ('a, unit, string, unit Lwt.t) format4 -> 'a +val ign_error : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> string -> unit +val ign_error_f : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> ('a, unit, string, unit) format4 -> 'a + +val fatal : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> string -> unit Lwt.t +val fatal_f : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> ('a, unit, string, unit Lwt.t) format4 -> 'a +val ign_fatal : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> string -> unit +val ign_fatal_f : ?inspect : 'v -> ?exn : exn -> ?section : section -> ?location : (string * int * int) -> ?logger : logger -> ('a, unit, string, unit) format4 -> 'a