terminal user interface to jujutsu. Focused on speed and clarity
9
fork

Configure Feed

Select the types of activity you want to include in your feed.

try to make logging work on macos and windows

+148 -61
+148 -61
jj_tui/lib/logging.ml
··· 1 1 (** A version of the logging module that adds timestamps to the logs *) 2 + 2 3 module Log = struct 3 4 let timestamp_tag = 4 5 let now () = Unix.gettimeofday () |> Unix.localtime in ··· 31 32 let app ?src fn = Logs.app ?src (timestamp_wrap fn) 32 33 end 33 34 34 - module Internal =struct 35 - let reporter ppf = 36 - let report src level ~over k msgf = 37 - let k _ = over (); k () in 38 - let with_stamp h tags k ppf fmt = 39 - let stamp = match tags with 40 - | None -> None 41 - | Some tags -> Logs.Tag.find Log.timestamp_tag tags 35 + module Internal = struct 36 + let reporter ppf = 37 + let report src level ~over k msgf = 38 + let k _ = 39 + over (); 40 + k () 41 + in 42 + let with_stamp h tags k ppf fmt = 43 + let stamp = 44 + match tags with 45 + | None -> 46 + None 47 + | Some tags -> 48 + Logs.Tag.find Log.timestamp_tag tags 49 + in 50 + let dt = Format.pp_print_option (Logs.Tag.printer Log.timestamp_tag) in 51 + Format.kfprintf 52 + k 53 + ppf 54 + ("%a[%a] @[" ^^ fmt ^^ "@]@.") 55 + Logs.pp_header 56 + (level, h) 57 + dt 58 + stamp 42 59 in 43 - let dt = Format.pp_print_option (Logs.Tag.printer Log.timestamp_tag) in 44 - Format.kfprintf k ppf ("%a[%a] @["^^fmt^^"@]@.") 45 - Logs.pp_header (level, h) dt stamp 60 + msgf @@ fun ?header ?tags fmt -> with_stamp header tags k ppf fmt 46 61 in 47 - msgf @@ fun ?header ?tags fmt -> with_stamp header tags k ppf fmt 48 - in 49 - { Logs.report = report } 50 - (** Removes old log files, keeping only the 20 most recent *) 51 - let cleanup_logs () = 52 - let state_home = Unix.getenv "XDG_STATE_HOME" in 53 - let jj_tui_dir = Filename.concat state_home "jj_tui" in 54 - let log_files = Sys.readdir jj_tui_dir 55 - |> Array.to_list 56 - |> List.filter (fun file -> Filename.check_suffix file ".log") 57 - |> List.sort (fun a b -> String.compare b a) in 58 - if List.length log_files > 20 then 59 - List.iteri (fun i file -> 60 - if i >= 20 then 61 - let file_path = Filename.concat jj_tui_dir file in 62 - Unix.unlink file_path 63 - ) log_files 64 - ;; 65 - let init_logging () = 66 - (*creates or opens the log file*) 67 - let get_log_file_channel () = 62 + { Logs.report } 63 + ;; 64 + 65 + (** Removes old log files, keeping only the 20 most recent *) 66 + let cleanup_logs () = 68 67 let state_home = Unix.getenv "XDG_STATE_HOME" in 69 68 let jj_tui_dir = Filename.concat state_home "jj_tui" in 70 - (try Unix.mkdir jj_tui_dir 0o755 with Unix.Unix_error (Unix.EEXIST, _, _) -> ()); 71 - let timestamp = Unix.time () |> Unix.localtime in 72 - let timestamp_str = Printf.sprintf "%04d%02d%02d_%02d%02d%02d" 73 - (timestamp.tm_year + 1900) (timestamp.tm_mon + 1) timestamp.tm_mday 74 - timestamp.tm_hour timestamp.tm_min timestamp.tm_sec in 75 - let log_file = Filename.concat jj_tui_dir (Printf.sprintf "log_%s.log" timestamp_str) in 76 - let log_channel = open_out_gen [ Open_append; Open_creat ] 0o644 log_file in 77 - log_channel 78 - in 79 - (*Make a mutex for logging to prevent concurrency and threading issues *) 80 - let logging_mutex = Picos_std_sync.Mutex.create () in 81 - Logs.set_reporter_mutex 82 - ~lock:(fun () -> Picos_std_sync.Mutex.lock logging_mutex) 83 - ~unlock:(fun () -> Picos_std_sync.Mutex.unlock logging_mutex); 84 - (* log our logs into the log file*) 85 - let log_chan = get_log_file_channel () in 86 - let log_formatter = Format.formatter_of_out_channel log_chan in 87 - let reporter = reporter log_formatter in 88 - Logs.set_level (Some Debug); 89 - Logs.set_reporter reporter; 90 - (*make sure everything is working*) 91 - [%log info "Logging initialized"]; 92 - cleanup_logs (); 93 - [%log debug "Old logs cleaned up"] 94 - ;; 69 + let log_files = 70 + Sys.readdir jj_tui_dir 71 + |> Array.to_list 72 + |> List.filter (fun file -> Filename.check_suffix file ".log") 73 + |> List.sort (fun a b -> String.compare b a) 74 + in 75 + if List.length log_files > 20 76 + then 77 + List.iteri 78 + (fun i file -> 79 + if i >= 20 80 + then ( 81 + let file_path = Filename.concat jj_tui_dir file in 82 + Unix.unlink file_path)) 83 + log_files 84 + ;; 85 + 86 + let normalise_os raw = 87 + match String.lowercase_ascii raw with "darwin" | "osx" -> "macos" | s -> s 88 + ;; 89 + 90 + let poll_os () = 91 + let raw = 92 + match Sys.os_type with 93 + | "Unix" -> 94 + (try 95 + let uname_in, _ = Unix.open_process_args "uname" [| "uname"; "-s" |] in 96 + let str = uname_in |> In_channel.input_all in 97 + Some (str |> String.lowercase_ascii |> String.trim) 98 + with 99 + | _ -> 100 + None) 101 + | s -> 102 + Some (s |> String.lowercase_ascii |> String.trim) 103 + in 104 + match raw with None | Some "" -> None | Some s -> Some (normalise_os s) 105 + ;; 106 + 107 + (*tries to get the logging dir for macos and linux*) 108 + let get_log_dir () = 109 + let os = poll_os () in 110 + let state_home = 111 + try 112 + match os with 113 + | Some "linux" -> 114 + Some (Unix.getenv "XDG_STATE_HOME") 115 + | Some "macos" -> 116 + Some "~/Library/Logs" 117 + | Some "windows" -> 118 + Some "~/AppData/Local" 119 + | _ -> 120 + None 121 + with 122 + | _ -> 123 + None 124 + in 125 + let state_home = 126 + Option.bind state_home (fun x -> if Sys.is_directory x then Some x else None) 127 + in 128 + match state_home with 129 + | None -> 130 + (try 131 + Unix.mkdir "~/.jj_tui" 0o755; 132 + Some "~/.jj_tui" 133 + with 134 + | Unix.Unix_error (Unix.EEXIST, _, _) -> 135 + None) 136 + | a -> 137 + a 138 + ;; 95 139 140 + let init_logging () = 141 + (*creates or opens the log file*) 142 + let get_log_file_channel () = 143 + get_log_dir () 144 + |> Option.map @@ fun state_home -> 145 + let jj_tui_dir = Filename.concat state_home "jj_tui" in 146 + (try Unix.mkdir jj_tui_dir 0o755 with Unix.Unix_error (Unix.EEXIST, _, _) -> ()); 147 + let timestamp = Unix.time () |> Unix.localtime in 148 + let timestamp_str = 149 + Printf.sprintf 150 + "%04d%02d%02d_%02d%02d%02d" 151 + (timestamp.tm_year + 1900) 152 + (timestamp.tm_mon + 1) 153 + timestamp.tm_mday 154 + timestamp.tm_hour 155 + timestamp.tm_min 156 + timestamp.tm_sec 157 + in 158 + let log_file = 159 + Filename.concat jj_tui_dir (Printf.sprintf "log_%s.log" timestamp_str) 160 + in 161 + let log_channel = open_out_gen [ Open_append; Open_creat ] 0o644 log_file in 162 + log_channel 163 + in 164 + (* log our logs into the log file*) 165 + let log_chan = get_log_file_channel () in 166 + match log_chan with 167 + | Some log_chan -> 168 + (*Make a mutex for logging to prevent concurrency and threading issues *) 169 + let logging_mutex = Picos_std_sync.Mutex.create () in 170 + Logs.set_reporter_mutex 171 + ~lock:(fun () -> Picos_std_sync.Mutex.lock logging_mutex) 172 + ~unlock:(fun () -> Picos_std_sync.Mutex.unlock logging_mutex); 173 + let log_formatter = Format.formatter_of_out_channel log_chan in 174 + let reporter = reporter log_formatter in 175 + Logs.set_level (Some Debug); 176 + Logs.set_reporter reporter; 177 + (*make sure everything is working*) 178 + [%log info "Logging initialized"]; 179 + cleanup_logs (); 180 + [%log debug "Old logs cleaned up"] 181 + | None -> 182 + () 183 + ;; 96 184 end 97 - (** 98 - Initialize the logging system 99 - *) 100 - let init_logging= Internal.init_logging 185 + 186 + (** Initialize the logging system *) 187 + let init_logging = Internal.init_logging