Skip to content

Commit

Permalink
Add synchronous APIs to monitor logger
Browse files Browse the repository at this point in the history
Summary:
When the monitor logs using `FlowServerMonitorLogger`, each log
command asynchronously writes the message to the log and or stderr. It
is good that it is asynchronous, so that the monitor doesn't go
unresponsive while it logs.

However, when we're debugging it's really useful to have synchronous
logging. If Lwt is acting strangely, I want to be able to using logging
to figure out what happens when.

Some lwt APIs use `_s` to indiciate synchronous APIs. So I've done that
here!

Reviewed By: samwgoldman

Differential Revision: D7464042

fbshipit-source-id: 39419da1aebf68f86e9ec5cba21a8d277186e1e8
  • Loading branch information
gabelevi authored and facebook-github-bot committed Apr 3, 2018
1 parent 16334d4 commit b55ba90
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 24 deletions.
1 change: 1 addition & 0 deletions ocp_build_flow.ocp.fb
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,7 @@ begin library "flow-monitor-logger"
end
requires = [
"flow-common-lwt"
"hh-utils-core"
"lwt"
"lwt.log"
"lwt.unix"
Expand Down
12 changes: 1 addition & 11 deletions src/monitor/flowServerMonitor.ml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,6 @@ let spf = Printf.sprintf

module Logger = FlowServerMonitorLogger

(* We're using lwt's logger instead of Hh_logger, so let's map Hh_logger levels to lwt levels *)
let lwt_level_of_hh_logger_level = function
| Hh_logger.Level.Off -> Lwt_log_core.Fatal
| Hh_logger.Level.Fatal -> Lwt_log_core.Fatal
| Hh_logger.Level.Error -> Lwt_log_core.Error
| Hh_logger.Level.Warn -> Lwt_log_core.Warning
| Hh_logger.Level.Info -> Lwt_log_core.Info
| Hh_logger.Level.Debug -> Lwt_log_core.Debug

(* We want to send a "Starting" message immediately and a "Ready" message when the Flow server is
* ready for the first time. This function sends the "Starting" message immediately and sets up a
* callback for when the server is ready *)
Expand Down Expand Up @@ -128,8 +119,7 @@ let internal_start ~is_daemon ?waiting_fd monitor_options =
FlowExitStatus.(exit ~msg Unknown_error)
);

Logger.init_logger
?log_fd (Hh_logger.Level.min_level () |> lwt_level_of_hh_logger_level);
Logger.init_logger log_fd;
Logger.info "argv=%s" (argv |> Array.to_list |> String.concat " ");

(* If there is a waiting fd, start up a thread that will message it *)
Expand Down
36 changes: 27 additions & 9 deletions src/monitor/logger/flowServerMonitorLogger.ml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@

type 'a logger_fn =
?exn : exn ->
?section : Lwt_log_core.section ->
?location : (string * int * int) ->
?logger:Lwt_log_core.logger ->
('a, unit, string, unit) format4 ->
'a

Expand Down Expand Up @@ -58,13 +55,24 @@ end)

let initialized = ref false

(* We're using lwt's logger instead of Hh_logger, so let's map Hh_logger levels to lwt levels *)
let lwt_level_of_hh_logger_level = function
| Hh_logger.Level.Off -> Lwt_log_core.Fatal
| Hh_logger.Level.Fatal -> Lwt_log_core.Fatal
| Hh_logger.Level.Error -> Lwt_log_core.Error
| Hh_logger.Level.Warn -> Lwt_log_core.Warning
| Hh_logger.Level.Info -> Lwt_log_core.Info
| Hh_logger.Level.Debug -> Lwt_log_core.Debug

(* Creates a default logger and sets the minimum logger level. The logger will log every message
* that passes the minimum level to stderr. If log_fd is provided, each message will be logged
* to it as well *)
let init_logger ?log_fd min_level =
let init_logger log_fd =
if !initialized then failwith "Cannot initialized FlowServerMonitorLogger more than once";
initialized := true;

let min_level = Hh_logger.Level.min_level () |> lwt_level_of_hh_logger_level in

let template = "$(date).$(milliseconds) [$(level)] $(message)" in

let log_fd = Option.map log_fd ~f:Lwt_unix.of_unix_file_descr in
Expand Down Expand Up @@ -94,8 +102,18 @@ let init_logger ?log_fd min_level =
(* Set the min level *)
Lwt_log_core.add_rule "*" min_level

let fatal = Lwt_log_core.ign_fatal_f
let error = Lwt_log_core.ign_error_f
let warn = Lwt_log_core.ign_warning_f
let info = Lwt_log_core.ign_info_f
let debug = Lwt_log_core.ign_debug_f
(* Async logging APIs. These are the APIs you should generally use. Since they're async, they
* won't make the monitor unresponsive while they're logging *)
let fatal ?exn fmt = Lwt_log_core.ign_fatal_f ?exn fmt
let error ?exn fmt = Lwt_log_core.ign_error_f ?exn fmt
let warn ?exn fmt = Lwt_log_core.ign_warning_f ?exn fmt
let info ?exn fmt = Lwt_log_core.ign_info_f ?exn fmt
let debug ?exn fmt = Lwt_log_core.ign_debug_f ?exn fmt

(* Synchronous versions just delegate to Hh_logger. These are mainly used for debugging, when you
* want a logging call to write to the log RIGHT NOW. *)
let fatal_s = Hh_logger.fatal
let error_s = Hh_logger.error
let warn_s = Hh_logger.warn
let info_s = Hh_logger.info
let debug_s = Hh_logger.debug
13 changes: 9 additions & 4 deletions src/monitor/logger/flowServerMonitorLogger.mli
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,23 @@
* LICENSE file in the root directory of this source tree.
*)

val init_logger: ?log_fd:Unix.file_descr -> Lwt_log_core.level -> unit
val init_logger: Unix.file_descr option -> unit

type 'a logger_fn =
?exn : exn ->
?section : Lwt_log_core.section ->
?location : (string * int * int) ->
?logger:Lwt_log_core.logger ->
('a, unit, string, unit) format4 ->
'a

(* Async APIs *)
val fatal: 'a logger_fn
val error: 'a logger_fn
val warn: 'a logger_fn
val info: 'a logger_fn
val debug: 'a logger_fn

(* Sync APIs *)
val fatal_s: 'a logger_fn
val error_s: 'a logger_fn
val warn_s: 'a logger_fn
val info_s: 'a logger_fn
val debug_s: 'a logger_fn

0 comments on commit b55ba90

Please sign in to comment.