<commit_before>(**
 * Copyright (c) 2015, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the "hack" directory of this source tree.
 *
 *)

let timestamp_string () =
  let open Unix in
  let tm = localtime (time ()) in
  let ms = int_of_float (gettimeofday () *. 1000.) mod 1000 in
  let year = tm.tm_year + 1900 in
  Printf.sprintf "[%d-%02d-%02d %02d:%02d:%02d.%03d]"
    year (tm.tm_mon + 1) tm.tm_mday tm.tm_hour tm.tm_min tm.tm_sec ms

(* We might want to log to both stderr and a file. Shelling out to tee isn't cross-platform.
 * We could dup2 stderr to a pipe and have a child process write to both original stderr and the
 * file, but that's kind of overkill. This is good enough *)
let dupe_log: (string * out_channel) option ref = ref None
let set_log filename fd =
  dupe_log := Some (filename, fd)
let get_log_name () = Option.map !dupe_log ~f:fst

let print_with_newline ?exn fmt =
  let print_raw ?exn s =
    let exn_str = Option.value_map exn ~default:"" ~f:(fun exn ->
      let bt = String_utils.indent 8 @@ String.trim @@ (Exception.get_backtrace_string exn) in
      let bt = if bt = "" then "" else ("\n    Backtrace:\n" ^ bt) in
      Printf.sprintf "\n    Exception: %s%s" (Exception.get_ctor_string exn) bt
    ) in
    let time = timestamp_string () in
    begin match !dupe_log with
    | None -> ()
    | Some (_, dupe_log_oc) -> Printf.fprintf dupe_log_oc "%s %s%s\n%!" time s exn_str end;
    Printf.eprintf "%s %s%s\n%!" time s exn_str
  in
  Printf.ksprintf (print_raw ?exn) fmt

let print_duration name t =
  let t2 = Unix.gettimeofday () in
  print_with_newline "%s: %f" name (t2 -. t);
  t2

let exc ?(prefix: string = "") ~(stack: string) (e: exn) : unit =
  print_with_newline "%s%s\n%s" prefix (Printexc.to_string e) stack

module Level : sig
  type t =
    | Off
    | Fatal
    | Error
    | Warn
    | Info
    | Debug
  val min_level : unit -> t
  val set_min_level : t -> unit
  val passes_min_level: t -> bool
  val log : t -> ?exn:Exception.t -> ('a, unit, string, string, string, unit) format6 -> 'a
  val log_duration : t -> string -> float -> float
end = struct<commit_msg>[hack] Typing_log should flush what it logs<commit_after>(**
 * Copyright (c) 2015, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the "hack" directory of this source tree.
 *
 *)

let timestamp_string () =
  let open Unix in
  let tm = localtime (time ()) in
  let ms = int_of_float (gettimeofday () *. 1000.) mod 1000 in
  let year = tm.tm_year + 1900 in
  Printf.sprintf "[%d-%02d-%02d %02d:%02d:%02d.%03d]"
    year (tm.tm_mon + 1) tm.tm_mday tm.tm_hour tm.tm_min tm.tm_sec ms

(* We might want to log to both stderr and a file. Shelling out to tee isn't cross-platform.
 * We could dup2 stderr to a pipe and have a child process write to both original stderr and the
 * file, but that's kind of overkill. This is good enough *)
let dupe_log: (string * out_channel) option ref = ref None
let set_log filename fd =
  dupe_log := Some (filename, fd)
let get_log_name () = Option.map !dupe_log ~f:fst

let print_with_newline ?exn fmt =
  let print_raw ?exn s =
    let exn_str = Option.value_map exn ~default:"" ~f:(fun exn ->
      let bt = String_utils.indent 8 @@ String.trim @@ (Exception.get_backtrace_string exn) in
      let bt = if bt = "" then "" else ("\n    Backtrace:\n" ^ bt) in
      Printf.sprintf "\n    Exception: %s%s" (Exception.get_ctor_string exn) bt
    ) in
    let time = timestamp_string () in
    begin match !dupe_log with
    | None -> ()
    | Some (_, dupe_log_oc) -> Printf.fprintf dupe_log_oc "%s %s%s\n%!" time s exn_str
    end;
    Printf.eprintf "%s %s%s\n%!" time s exn_str
  in
  Printf.ksprintf (print_raw ?exn) fmt

let print_duration name t =
  let t2 = Unix.gettimeofday () in
  print_with_newline "%s: %f" name (t2 -. t);
  t2

let exc ?(prefix: string = "") ~(stack: string) (e: exn) : unit =
  print_with_newline "%s%s\n%s" prefix (Printexc.to_string e) stack

module Level : sig
  type t =
    | Off
    | Fatal
    | Error
    | Warn
    | Info
    | Debug
  val min_level : unit -> t
  val set_min_level : t -> unit
  val passes_min_level: t -> bool
  val log : t -> ?exn:Exception.t -> ('a, unit, string, string, string, unit) format6 -> 'a
  val log_duration : t -> string -> float -> float
end = struct
{'fraction_non_alphanumeric': 0.12218214607754734, 'fraction_numerical': 0.015779981965734897, 'mean_word_length': 3.074380165289256, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7022523', 'n_tokens_mistral': 1669, 'n_tokens_neox': 1611, 'n_words': 559}