mirror of
				https://github.com/velopack/velopack.git
				synced 2025-10-25 15:19:22 +00:00 
			
		
		
		
	Remove logging callbacks from C++ / NodeJS
This commit is contained in:
		
							
								
								
									
										4
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @@ -2190,10 +2190,12 @@ dependencies = [ | ||||
|  "async-std", | ||||
|  "bitflags 2.9.0", | ||||
|  "derivative", | ||||
|  "file-rotate", | ||||
|  "glob", | ||||
|  "lazy_static", | ||||
|  "libc", | ||||
|  "log", | ||||
|  "log-panics", | ||||
|  "normpath", | ||||
|  "rand", | ||||
|  "regex", | ||||
| @@ -2202,8 +2204,10 @@ dependencies = [ | ||||
|  "serde_json", | ||||
|  "sha1", | ||||
|  "sha2", | ||||
|  "simplelog", | ||||
|  "tempfile", | ||||
|  "thiserror 2.0.12", | ||||
|  "time 0.3.37", | ||||
|  "ts-rs", | ||||
|  "ureq", | ||||
|  "url", | ||||
|   | ||||
| @@ -23,7 +23,7 @@ edition = "2021" | ||||
| rust-version = "1.75" | ||||
|  | ||||
| [workspace.dependencies] | ||||
| velopack = { path = "src/lib-rust" } | ||||
| velopack = { path = "src/lib-rust", features = ["file-logging"] } | ||||
| log = "0.4" | ||||
| log-derive = "0.4.1" | ||||
| ureq = "3.0" | ||||
|   | ||||
| @@ -116,7 +116,7 @@ pub fn install(pkg: &mut BundleZip, install_to: Option<&PathBuf>, start_args: Op | ||||
|      | ||||
|     info!("Acquiring lock..."); | ||||
|     let paths = create_config_from_root_dir(&root_path); | ||||
|     let locator = VelopackLocator::new(paths, app); | ||||
|     let locator = VelopackLocator::new_with_manifest(paths, app); | ||||
|     let _mutex = locator.try_get_exclusive_lock()?; | ||||
|  | ||||
|     let tx = if dialogs::get_silent() { | ||||
|   | ||||
| @@ -156,7 +156,7 @@ fn try_legacy_migration(root_dir: &PathBuf, manifest: &Manifest) -> Result<Velop | ||||
|     // new shortcuts will be force-created | ||||
|     let mut modified_manifest = manifest.clone(); | ||||
|     modified_manifest.shortcut_locations = String::new(); | ||||
|     let locator = VelopackLocator::new(path_config, modified_manifest); | ||||
|     let locator = VelopackLocator::new_with_manifest(path_config, modified_manifest); | ||||
|     let _mutex = locator.try_get_exclusive_lock()?; | ||||
|  | ||||
|     if !locator.get_current_bin_dir().exists() { | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| pub mod commands; | ||||
| pub mod logging; | ||||
| pub mod shared; | ||||
| #[cfg(target_os = "windows")] | ||||
| pub mod windows; | ||||
| @@ -8,6 +7,5 @@ pub use shared::dialogs; | ||||
|  | ||||
| #[macro_use] | ||||
| extern crate log; | ||||
| extern crate simplelog; | ||||
| #[macro_use] | ||||
| extern crate lazy_static; | ||||
|   | ||||
| @@ -1,58 +0,0 @@ | ||||
| use anyhow::Result; | ||||
| use simplelog::*; | ||||
| use std::path::PathBuf; | ||||
| use time::format_description::{modifier, Component, FormatItem}; | ||||
|  | ||||
| pub fn trace_logger() { | ||||
|     TermLogger::init(LevelFilter::Trace, get_config(None), TerminalMode::Mixed, ColorChoice::Never).unwrap(); | ||||
| } | ||||
|  | ||||
| pub fn setup_logging(process_name: &str, file: Option<&PathBuf>, console: bool, verbose: bool) -> Result<()> { | ||||
|     let mut loggers: Vec<Box<dyn SharedLogger>> = Vec::new(); | ||||
|     let color_choice = ColorChoice::Never; | ||||
|     if console { | ||||
|         let console_level = if verbose { LevelFilter::Debug } else { LevelFilter::Info }; | ||||
|         loggers.push(TermLogger::new(console_level, get_config(None), TerminalMode::Mixed, color_choice)); | ||||
|     } | ||||
|  | ||||
|     if let Some(f) = file { | ||||
|         let file_level = if verbose { LevelFilter::Trace } else { LevelFilter::Info }; | ||||
|         let writer = file_rotate::FileRotate::new( | ||||
|             f.clone(), | ||||
|             file_rotate::suffix::AppendCount::new(1),          // keep 1 old log file | ||||
|             file_rotate::ContentLimit::Bytes(1 * 1024 * 1024), // 1MB max log file size | ||||
|             file_rotate::compression::Compression::None, | ||||
|             None, | ||||
|         ); | ||||
|         loggers.push(WriteLogger::new(file_level, get_config(Some(process_name)), writer)); | ||||
|     } | ||||
|  | ||||
|     CombinedLogger::init(loggers)?; | ||||
|     log_panics::init(); | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| fn get_config(process_name: Option<&str>) -> Config { | ||||
|     let mut c = ConfigBuilder::default(); | ||||
|     let mut prefix = "".to_owned(); | ||||
|     if let Some(pn) = process_name { | ||||
|         prefix = format!("[{}:{}] ", pn, std::process::id()); | ||||
|     } | ||||
|  | ||||
|     let prefix_heaped = Box::leak(prefix.into_boxed_str()); | ||||
|  | ||||
|     let time_format: &'static [FormatItem<'static>] = Box::leak(Box::new([ | ||||
|         FormatItem::Literal(prefix_heaped.as_bytes()), | ||||
|         FormatItem::Literal(b"["), | ||||
|         FormatItem::Component(Component::Hour(modifier::Hour::default())), | ||||
|         FormatItem::Literal(b":"), | ||||
|         FormatItem::Component(Component::Minute(modifier::Minute::default())), | ||||
|         FormatItem::Literal(b":"), | ||||
|         FormatItem::Component(Component::Second(modifier::Second::default())), | ||||
|         FormatItem::Literal(b"]"), | ||||
|     ])); | ||||
|  | ||||
|     c.set_time_format_custom(time_format); | ||||
|     let _ = c.set_time_offset_to_local(); // might fail if local tz can't be determined | ||||
|     c.build() | ||||
| } | ||||
| @@ -79,7 +79,7 @@ fn main_inner() -> Result<()> { | ||||
|  | ||||
|     let verbose = matches.get_flag("verbose"); | ||||
|     let logfile = matches.get_one::<PathBuf>("log"); | ||||
|     logging::setup_logging("setup", logfile, true, verbose)?; | ||||
|     velopack::logging::init_logging("setup", logfile, true, verbose); | ||||
|  | ||||
|     let debug = matches.get_one::<PathBuf>("debug"); | ||||
|     let install_to = matches.get_one::<PathBuf>("installto"); | ||||
|   | ||||
| @@ -1,8 +1,6 @@ | ||||
| #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] | ||||
| #![allow(dead_code)] | ||||
|  | ||||
| mod logging; | ||||
|  | ||||
| #[macro_use] | ||||
| extern crate log; | ||||
|  | ||||
| @@ -21,7 +19,7 @@ fn main() -> ExitCode { | ||||
|         my_dir.join("Velopack.log") | ||||
|     }; | ||||
|  | ||||
|     let _ = logging::setup_logging("stub", Some(&default_log_file), false, false); | ||||
|     let _ = velopack::logging::init_logging("stub", Some(&default_log_file), false, false); | ||||
|  | ||||
|     info!("--"); | ||||
|     info!("Starting Velopack Stub (at {:?})", my_path); | ||||
|   | ||||
| @@ -7,8 +7,9 @@ extern crate log; | ||||
| use anyhow::{anyhow, bail, Result}; | ||||
| use clap::{arg, value_parser, ArgMatches, Command}; | ||||
| use std::{env, path::PathBuf}; | ||||
| use velopack::locator::{self, auto_locate_app_manifest, LocationContext}; | ||||
| use velopack_bins::{*, shared::OperationWait}; | ||||
| use velopack::locator::{auto_locate_app_manifest, LocationContext}; | ||||
| use velopack::logging::*; | ||||
| use velopack_bins::{shared::OperationWait, *}; | ||||
|  | ||||
| #[rustfmt::skip] | ||||
| fn root_command() -> Command { | ||||
| @@ -132,8 +133,8 @@ fn main() -> Result<()> { | ||||
|  | ||||
|     let verbose = get_flag_or_false(&matches, "verbose"); | ||||
|     let log_file = matches.get_one("log"); | ||||
|     let desired_log_file = log_file.cloned().unwrap_or(locator::default_log_location(LocationContext::IAmUpdateExe)); | ||||
|     logging::setup_logging("update", Some(&desired_log_file), true, verbose)?; | ||||
|     let desired_log_file = log_file.cloned().unwrap_or(default_logfile_from_context(LocationContext::IAmUpdateExe)); | ||||
|     init_logging("update", Some(&desired_log_file), true, verbose); | ||||
|  | ||||
|     // change working directory to the parent directory of the exe | ||||
|     let mut containing_dir = env::current_exe()?; | ||||
| @@ -212,7 +213,6 @@ fn apply(matches: &ArgMatches) -> Result<()> { | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
|  | ||||
| fn get_start_args(matches: &ArgMatches) -> (OperationWait, Option<&String>, Option<&String>, Option<Vec<&str>>) { | ||||
|     let legacy_args = matches.get_one::<String>("args"); | ||||
|     let exe_name = matches.get_one::<String>("EXE_NAME"); | ||||
| @@ -246,10 +246,10 @@ fn uninstall(_matches: &ArgMatches) -> Result<()> { | ||||
| #[cfg(target_os = "windows")] | ||||
| #[test] | ||||
| fn test_cli_parse_handles_equals_spaces() { | ||||
|     let command = vec!["C:\\Some Path\\With = Spaces\\Update.exe", "apply" , "--package", "C:\\Some Path\\With = Spaces\\Package.zip"]; | ||||
|     let command = vec!["C:\\Some Path\\With = Spaces\\Update.exe", "apply", "--package", "C:\\Some Path\\With = Spaces\\Package.zip"]; | ||||
|     let matches = try_parse_command_line_matches(command.iter().map(|s| s.to_string()).collect()).unwrap(); | ||||
|     let (wait, restart, package, exe_args) = get_apply_args(matches.subcommand_matches("apply").unwrap()); | ||||
|      | ||||
|  | ||||
|     assert_eq!(wait, OperationWait::NoWait); | ||||
|     assert_eq!(restart, true); | ||||
|     assert_eq!(package, Some(&PathBuf::from("C:\\Some Path\\With = Spaces\\Package.zip"))); | ||||
|   | ||||
| @@ -179,13 +179,6 @@ typedef void (*vpkc_progress_callback_t)(void *p_user_data, size_t progress); | ||||
|  */ | ||||
| typedef void (*vpkc_hook_callback_t)(void *p_user_data, const char *psz_app_version); | ||||
|  | ||||
| /** | ||||
|  * Log callback function. | ||||
|  */ | ||||
| typedef void (*vpkc_log_callback_t)(void *p_user_data, | ||||
|                                     const char *psz_level, | ||||
|                                     const char *psz_message); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif // __cplusplus | ||||
| @@ -399,12 +392,6 @@ void vpkc_app_set_hook_restarted(vpkc_hook_callback_t cb_restarted); | ||||
|  */ | ||||
| size_t vpkc_get_last_error(char *psz_error, size_t c_error); | ||||
|  | ||||
| /** | ||||
|  * Set a custom log callback. This will be called for all log messages generated by the Velopack library. | ||||
|  */ | ||||
| void vpkc_set_logger(vpkc_log_callback_t cb_log, | ||||
|                      void *p_user_data); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| }  // extern "C" | ||||
| #endif  // __cplusplus | ||||
|   | ||||
| @@ -16,6 +16,8 @@ use libc::{c_char, c_void, size_t}; | ||||
| use log_derive::{logfn, logfn_inputs}; | ||||
| use std::{ffi::CString, ptr}; | ||||
| use velopack::{sources, ApplyWaitMode, Error as VelopackError, UpdateCheck, UpdateManager, VelopackApp}; | ||||
| use velopack::locator::{LocationContext}; | ||||
| use velopack::logging::{default_logfile_from_config, default_logfile_from_context, init_logging}; | ||||
|  | ||||
| /// Create a new FileSource update source for a given file path. | ||||
| #[no_mangle] | ||||
| @@ -437,7 +439,15 @@ pub extern "C" fn vpkc_app_run(p_user_data: *mut c_void) { | ||||
|             hook(p_user_data, c_string.as_ptr()); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|      | ||||
|     // init logging | ||||
|     let log_file = if let Some(locator) = &app_options.locator { | ||||
|         default_logfile_from_config(locator) | ||||
|     } else { | ||||
|         default_logfile_from_context(LocationContext::FromCurrentExe) | ||||
|     }; | ||||
|      | ||||
|     init_logging("lib-cpp", Some(&log_file), false, false); | ||||
|     app.run(); | ||||
| } | ||||
|  | ||||
| @@ -530,10 +540,4 @@ pub extern "C" fn vpkc_app_set_hook_restarted(cb_restarted: vpkc_hook_callback_t | ||||
| pub extern "C" fn vpkc_get_last_error(psz_error: *mut c_char, c_error: size_t) -> size_t { | ||||
|     let error = get_last_error(); | ||||
|     return_cstr(psz_error, c_error, &error) | ||||
| } | ||||
|  | ||||
| /// Set a custom log callback. This will be called for all log messages generated by the Velopack library. | ||||
| #[no_mangle] | ||||
| pub extern "C" fn vpkc_set_logger(cb_log: vpkc_log_callback_t, p_user_data: *mut c_void) { | ||||
|     set_log_callback(cb_log, p_user_data); | ||||
| } | ||||
| } | ||||
| @@ -1,7 +1,5 @@ | ||||
| use anyhow::Result; | ||||
| use log::{Level, Log, Metadata, Record}; | ||||
| use std::ffi::{c_void, CString}; | ||||
| use std::sync::{Mutex, RwLock}; | ||||
| use std::sync::RwLock; | ||||
| use velopack::locator::VelopackLocatorConfig; | ||||
|  | ||||
| use crate::types::*; | ||||
| @@ -21,7 +19,6 @@ pub struct AppOptions { | ||||
|  | ||||
| lazy_static::lazy_static! { | ||||
|     static ref LAST_ERROR: RwLock<String> = RwLock::new(String::new()); | ||||
|     static ref LOG_CALLBACK: Mutex<(vpkc_log_callback_t, usize)> = Mutex::new((None, 0)); | ||||
|     pub static ref VELOPACK_APP: RwLock<AppOptions> = RwLock::new(Default::default()); | ||||
| } | ||||
|  | ||||
| @@ -64,53 +61,3 @@ where | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub fn set_log_callback(callback: vpkc_log_callback_t, user_data: *mut c_void) { | ||||
|     // Initialize the logger if it hasn't been set yet | ||||
|     let _ = log::set_logger(&LOGGER); | ||||
|     log::set_max_level(log::LevelFilter::Trace); | ||||
|  | ||||
|     let mut log_callback = LOG_CALLBACK.lock().unwrap(); | ||||
|     *log_callback = (callback, user_data as usize); | ||||
| } | ||||
|  | ||||
| pub fn log_message(level: &str, message: &str) { | ||||
|     let log_callback = LOG_CALLBACK.lock().unwrap(); | ||||
|     let (callback, user_data) = *log_callback; | ||||
|     if let Some(callback) = callback { | ||||
|         let c_level = CString::new(level).unwrap(); | ||||
|         let c_message = CString::new(message).unwrap(); | ||||
|         callback(user_data as *mut c_void, c_level.as_ptr(), c_message.as_ptr()); | ||||
|     } | ||||
| } | ||||
|  | ||||
| struct LoggerImpl {} | ||||
|  | ||||
| static LOGGER: LoggerImpl = LoggerImpl {}; | ||||
|  | ||||
| impl Log for LoggerImpl { | ||||
|     fn enabled(&self, metadata: &Metadata) -> bool { | ||||
|         metadata.level() <= log::max_level() | ||||
|     } | ||||
|  | ||||
|     fn log(&self, record: &Record) { | ||||
|         if !self.enabled(record.metadata()) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let text = format!("{}", record.args()); | ||||
|  | ||||
|         let level = match record.level() { | ||||
|             Level::Error => "error", | ||||
|             Level::Warn => "warn", | ||||
|             Level::Info => "info", | ||||
|             Level::Debug => "debug", | ||||
|             Level::Trace => "trace", | ||||
|         } | ||||
|         .to_string(); | ||||
|  | ||||
|         log_message(&level, &text); | ||||
|     } | ||||
|  | ||||
|     fn flush(&self) {} | ||||
| } | ||||
|   | ||||
| @@ -22,9 +22,6 @@ pub type vpkc_update_source_t = c_void; | ||||
| /// Progress callback function. | ||||
| pub type vpkc_progress_callback_t = Option<extern "C" fn(p_user_data: *mut c_void, progress: size_t)>; | ||||
|  | ||||
| /// Log callback function. | ||||
| pub type vpkc_log_callback_t = Option<extern "C" fn(p_user_data: *mut c_void, psz_level: *const c_char, psz_message: *const c_char)>; | ||||
|  | ||||
| /// VelopackApp startup hook callback function. | ||||
| pub type vpkc_hook_callback_t = Option<extern "C" fn(p_user_data: *mut c_void, psz_app_version: *const c_char)>; | ||||
|  | ||||
|   | ||||
| @@ -47,10 +47,6 @@ declare module "./load" { | ||||
|     locator: string | null, | ||||
|     autoApply: boolean, | ||||
|   ): void; | ||||
|  | ||||
|   function js_set_logger_callback( | ||||
|     cb: (loglevel: LogLevel, msg: string) => void, | ||||
|   ): void; | ||||
| } | ||||
|  | ||||
| type VelopackHookType = | ||||
| @@ -63,8 +59,6 @@ type VelopackHookType = | ||||
|  | ||||
| type VelopackHook = (version: string) => void; | ||||
|  | ||||
| type LogLevel = "info" | "warn" | "error" | "debug" | "trace"; | ||||
|  | ||||
| /**  | ||||
|  * VelopackApp helps you to handle app activation events correctly. | ||||
|  * This should be used as early as possible in your application startup code. | ||||
| @@ -300,13 +294,4 @@ export class UpdateManager { | ||||
|       restartArgs, | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Set a custom logger callback to receive log messages from Velopack. The default behavior is to log to console.log. | ||||
|  */ | ||||
| export function setVelopackLogger( | ||||
|   callback: (loglevel: LogLevel, msg: string) => void, | ||||
| ) { | ||||
|   addon.js_set_logger_callback(callback); | ||||
| } | ||||
| } | ||||
| @@ -7,8 +7,7 @@ use std::sync::{Arc, Mutex}; | ||||
| use std::thread; | ||||
| use velopack::sources::*; | ||||
| use velopack::*; | ||||
|  | ||||
| mod logger; | ||||
| use velopack::logging::{default_logfile_from_config, default_logfile_from_context}; | ||||
|  | ||||
| struct UpdateManagerWrapper { | ||||
|     manager: UpdateManager, | ||||
| @@ -262,30 +261,29 @@ fn js_appbuilder_run(mut cx: FunctionContext) -> JsResult<JsUndefined> { | ||||
|             .on_after_update_fast_callback(|semver| hook_handler("after-update", semver)); | ||||
|     } | ||||
|  | ||||
|     if let Some(locator) = locator { | ||||
|         builder = builder.set_locator(locator); | ||||
|     if let Some(locator) = &locator { | ||||
|         builder = builder.set_locator(locator.clone()); | ||||
|     } | ||||
|  | ||||
|     if let Some(arg_array) = argarray { | ||||
|         builder = builder.set_args(arg_array); | ||||
|     } | ||||
|  | ||||
|     // init logging | ||||
|     let log_file = if let Some(locator) = &locator { | ||||
|         default_logfile_from_config(locator) | ||||
|     } else { | ||||
|         default_logfile_from_context(LocationContext::FromCurrentExe) | ||||
|     }; | ||||
|  | ||||
|     logging::init_logging("lib-nodejs", Some(&log_file), false, false); | ||||
|     builder.run(); | ||||
|  | ||||
|     Ok(undefined) | ||||
| } | ||||
|  | ||||
| fn js_set_logger_callback(mut cx: FunctionContext) -> JsResult<JsUndefined> { | ||||
|     let arg_cb = cx.argument::<JsFunction>(0)?; | ||||
|     let cb_root = arg_cb.root(&mut cx); | ||||
|     logger::set_logger_callback(Some(cb_root), &mut cx); | ||||
|     Ok(cx.undefined()) | ||||
| } | ||||
|  | ||||
| #[neon::main] | ||||
| fn main(mut cx: ModuleContext) -> NeonResult<()> { | ||||
|     logger::init_logger(&mut cx); | ||||
|  | ||||
|     cx.export_function("js_new_update_manager", js_new_update_manager)?; | ||||
|     cx.export_function("js_get_current_version", js_get_current_version)?; | ||||
|     cx.export_function("js_get_app_id", js_get_app_id)?; | ||||
| @@ -295,6 +293,5 @@ fn main(mut cx: ModuleContext) -> NeonResult<()> { | ||||
|     cx.export_function("js_download_update_async", js_download_update_async)?; | ||||
|     cx.export_function("js_wait_exit_then_apply_update", js_wait_exit_then_apply_update)?; | ||||
|     cx.export_function("js_appbuilder_run", js_appbuilder_run)?; | ||||
|     cx.export_function("js_set_logger_callback", js_set_logger_callback)?; | ||||
|     Ok(()) | ||||
| } | ||||
|   | ||||
| @@ -1,98 +0,0 @@ | ||||
| use std::sync::{Arc, Mutex}; | ||||
|  | ||||
| use lazy_static::lazy_static; | ||||
| use log::{Level, Log, Metadata, Record}; | ||||
| use neon::{event::Channel, prelude::*}; | ||||
|  | ||||
| static LOGGER: LoggerImpl = LoggerImpl {}; | ||||
|  | ||||
| lazy_static! { | ||||
|     static ref LOGGER_CB: Arc<Mutex<Option<Root<JsFunction>>>> = Arc::new(Mutex::new(None)); | ||||
|     static ref LOGGER_CONSOLE_LOG: Arc<Mutex<Option<Root<JsFunction>>>> = Arc::new(Mutex::new(None)); | ||||
|     static ref LOGGER_CHANNEL: Arc<Mutex<Option<Channel>>> = Arc::new(Mutex::new(None)); | ||||
| } | ||||
|  | ||||
| struct LoggerImpl {} | ||||
|  | ||||
| impl Log for LoggerImpl { | ||||
|     fn enabled(&self, metadata: &Metadata) -> bool { | ||||
|         metadata.level() <= log::max_level() | ||||
|     } | ||||
|  | ||||
|     fn log(&self, record: &Record) { | ||||
|         if !self.enabled(record.metadata()) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let text = format!("{}", record.args()); | ||||
|  | ||||
|         let level = match record.level() { | ||||
|             Level::Error => "error", | ||||
|             Level::Warn => "warn", | ||||
|             Level::Info => "info", | ||||
|             Level::Debug => "debug", | ||||
|             Level::Trace => "trace", | ||||
|         }; | ||||
|  | ||||
|         if let Ok(channel_opt) = LOGGER_CHANNEL.lock() { | ||||
|             if channel_opt.is_some() { | ||||
|                 let channel = channel_opt.as_ref().unwrap(); | ||||
|  | ||||
|                 channel.send(move |mut cx| { | ||||
|                     // If custom callback exists, then use that. | ||||
|                     if let Ok(cb_lock) = LOGGER_CB.lock() { | ||||
|                         if let Some(cb) = &*cb_lock { | ||||
|                             let undefined = cx.undefined(); | ||||
|                             let args = vec![cx.string(level).upcast(), cx.string(text).upcast()]; | ||||
|                             cb.to_inner(&mut cx).call(&mut cx, undefined, args)?; | ||||
|                             return Ok(()); | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     // If no custom callback, then use console.log | ||||
|                     if let Ok(console) = LOGGER_CONSOLE_LOG.lock() { | ||||
|                         if let Some(cb) = &*console { | ||||
|                             let undefined = cx.undefined(); | ||||
|                             let args = vec![cx.string(level).upcast(), cx.string(text).upcast()]; | ||||
|                             cb.to_inner(&mut cx).call(&mut cx, undefined, args)?; | ||||
|                             return Ok(()); | ||||
|                         } | ||||
|                     } | ||||
|                     Ok(()) | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn flush(&self) {} | ||||
| } | ||||
|  | ||||
| pub fn init_logger(cx: &mut ModuleContext) { | ||||
|     let _ = log::set_logger(&LOGGER); | ||||
|     log::set_max_level(log::LevelFilter::Trace); | ||||
|  | ||||
|     if let Ok(mut ch) = LOGGER_CONSOLE_LOG.lock() { | ||||
|         if let Ok(console) = cx.global::<JsObject>("console") { | ||||
|             if let Ok(log_fn) = console.get::<JsFunction, ModuleContext, &str>(cx, "log") { | ||||
|                 *ch = Some(log_fn.root(cx)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if let Ok(mut ch) = LOGGER_CHANNEL.lock() { | ||||
|         // let mut log_channel = Channel::new(cx); | ||||
|         let mut log_channel = cx.channel(); | ||||
|         log_channel.unref(cx); // Unref the channel so that the event loop can exit while this channel is open | ||||
|         *ch = Some(log_channel); | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub fn set_logger_callback(callback: Option<Root<JsFunction>>, cx: &mut FunctionContext) { | ||||
|     if let Ok(mut cb_lock) = LOGGER_CB.lock() { | ||||
|         let cb_taken = cb_lock.take(); | ||||
|         if let Some(cb_exist) = cb_taken { | ||||
|             cb_exist.drop(cx); | ||||
|         } | ||||
|         *cb_lock = callback; | ||||
|     } | ||||
| } | ||||
| @@ -18,6 +18,7 @@ default = ["zstd"] | ||||
| delta = ["zstd"] | ||||
| async = ["async-std"] | ||||
| typescript = ["ts-rs"] | ||||
| file-logging = ["log-panics", "simplelog", "file-rotate", "time"] | ||||
|  | ||||
| [package.metadata.docs.rs] | ||||
| features = ["async", "delta"] | ||||
| @@ -59,6 +60,12 @@ zstd = { workspace = true, optional = true } | ||||
| # async | ||||
| async-std = { workspace = true, optional = true } | ||||
|  | ||||
| # file logging | ||||
| log-panics = { workspace = true, optional = true } | ||||
| simplelog = { workspace = true, optional = true } | ||||
| file-rotate = { workspace = true, optional = true } | ||||
| time = { workspace = true, optional = true } | ||||
|  | ||||
| [target.'cfg(windows)'.dependencies] | ||||
| windows = { workspace = true, features = ["Win32_Foundation", "Win32_Storage", "Win32_Storage_FileSystem", "Win32_System_IO"] } | ||||
|  | ||||
|   | ||||
| @@ -103,6 +103,9 @@ pub mod delta; | ||||
| /// Acquire and manage file-system based lock files. | ||||
| pub mod lockfile; | ||||
|  | ||||
| /// Logging utilities and setup. | ||||
| pub mod logging; | ||||
|  | ||||
| pub use app::*; | ||||
| pub use manager::*; | ||||
|  | ||||
|   | ||||
| @@ -18,37 +18,6 @@ pub fn default_channel_name() -> String { | ||||
|     return "osx".to_owned(); | ||||
| } | ||||
|  | ||||
| /// Default log location for Velopack on the current OS. | ||||
| #[allow(unused_variables)] | ||||
| pub fn default_log_location(context: LocationContext) -> PathBuf { | ||||
|     #[cfg(target_os = "windows")] | ||||
|     { | ||||
|         if let Ok(locator) = auto_locate_app_manifest(context) { | ||||
|             return locator.get_root_dir().join("Velopack.log"); | ||||
|         } | ||||
|  | ||||
|         warn!("Could not auto-locate app manifest, writing log to current directory."); | ||||
|  | ||||
|         // If we can't locate the current app, we write to the current directory. | ||||
|         let mut my_exe = std::env::current_exe().expect("Could not locate current executable"); | ||||
|         my_exe.pop(); | ||||
|         return my_exe.join("Velopack.log"); | ||||
|     } | ||||
|     #[cfg(target_os = "linux")] | ||||
|     { | ||||
|         return std::path::Path::new("/tmp/velopack.log").to_path_buf(); | ||||
|     } | ||||
|     #[cfg(target_os = "macos")] | ||||
|     { | ||||
|         #[allow(deprecated)] | ||||
|         let mut user_home = std::env::home_dir().expect("Could not locate user home directory via $HOME or /etc/passwd"); | ||||
|         user_home.push("Library"); | ||||
|         user_home.push("Logs"); | ||||
|         user_home.push("velopack.log"); | ||||
|         return user_home; | ||||
|     } | ||||
| } | ||||
|  | ||||
| bitflags::bitflags! { | ||||
|     #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||||
|     /// ShortcutLocationFlags is a bitflags enumeration of system shortcut locations. | ||||
| @@ -121,8 +90,22 @@ pub struct VelopackLocator { | ||||
| } | ||||
|  | ||||
| impl VelopackLocator { | ||||
|     /// Creates a new VelopackLocator from the given paths, trying to auto-detect the manifest. | ||||
|     pub fn new(config: &VelopackLocatorConfig) -> Result<VelopackLocator, Error> | ||||
|     { | ||||
|         if !config.UpdateExePath.exists() { | ||||
|             return Err(Error::MissingUpdateExe); | ||||
|         } | ||||
|         if !config.ManifestPath.exists() { | ||||
|             return Err(Error::MissingNuspec); | ||||
|         } | ||||
|  | ||||
|         let manifest = read_current_manifest(&config.ManifestPath)?; | ||||
|         Ok(Self { paths: config.clone(), manifest }) | ||||
|     } | ||||
|      | ||||
|     /// Creates a new VelopackLocator from the given paths and manifest. | ||||
|     pub fn new(paths: VelopackLocatorConfig, manifest: Manifest) -> Self { | ||||
|     pub fn new_with_manifest(paths: VelopackLocatorConfig, manifest: Manifest) -> Self { | ||||
|         Self { paths, manifest } | ||||
|     } | ||||
|  | ||||
| @@ -333,19 +316,6 @@ pub fn create_config_from_root_dir<P: AsRef<std::path::Path>>(root_dir: P) -> Ve | ||||
|     } | ||||
| } | ||||
|  | ||||
| fn config_to_locator(config: &VelopackLocatorConfig) -> Result<VelopackLocator, Error> | ||||
| { | ||||
|     if !config.UpdateExePath.exists() { | ||||
|         return Err(Error::MissingUpdateExe); | ||||
|     } | ||||
|     if !config.ManifestPath.exists() { | ||||
|         return Err(Error::MissingNuspec); | ||||
|     } | ||||
|  | ||||
|     let manifest = read_current_manifest(&config.ManifestPath)?; | ||||
|     Ok(VelopackLocator::new(config.clone(), manifest)) | ||||
| } | ||||
|  | ||||
| /// LocationContext is an enumeration of possible contexts for locating the current app manifest. | ||||
| pub enum LocationContext | ||||
| { | ||||
| @@ -381,7 +351,7 @@ pub fn auto_locate_app_manifest(context: LocationContext) -> Result<VelopackLoca | ||||
|         } | ||||
|         LocationContext::FromSpecifiedRootDir(root_dir) => { | ||||
|             let config = create_config_from_root_dir(&root_dir); | ||||
|             let locator = config_to_locator(&config)?; | ||||
|             let locator = VelopackLocator::new(&config)?; | ||||
|             return Ok(locator); | ||||
|         } | ||||
|         LocationContext::FromSpecifiedAppExecutable(exe_path) => { | ||||
| @@ -390,7 +360,7 @@ pub fn auto_locate_app_manifest(context: LocationContext) -> Result<VelopackLoca | ||||
|                 if parent_dir.join("Update.exe").exists() { | ||||
|                     info!("Found Update.exe in parent directory: {}", parent_dir.to_string_lossy()); | ||||
|                     let config = create_config_from_root_dir(&parent_dir); | ||||
|                     let locator = config_to_locator(&config)?; | ||||
|                     let locator = VelopackLocator::new(&config)?; | ||||
|                     return Ok(locator); | ||||
|                 } | ||||
|             } | ||||
| @@ -404,7 +374,7 @@ pub fn auto_locate_app_manifest(context: LocationContext) -> Result<VelopackLoca | ||||
|                 if maybe_root.join("Update.exe").exists() { | ||||
|                     info!("Found Update.exe by current path pattern search in directory: {}", maybe_root.to_string_lossy()); | ||||
|                     let config = create_config_from_root_dir(&maybe_root); | ||||
|                     let locator = config_to_locator(&config)?; | ||||
|                     let locator = VelopackLocator::new(&config)?; | ||||
|                     return Ok(locator); | ||||
|                 } | ||||
|             } | ||||
| @@ -413,12 +383,12 @@ pub fn auto_locate_app_manifest(context: LocationContext) -> Result<VelopackLoca | ||||
|             let exe_path = std::env::current_exe()?; | ||||
|             if let Some(parent_dir) = exe_path.parent() { | ||||
|                 let config = create_config_from_root_dir(&parent_dir); | ||||
|                 let locator = config_to_locator(&config)?; | ||||
|                 let locator = VelopackLocator::new(&config)?; | ||||
|                 return Ok(locator); | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|      | ||||
|     Err(Error::NotInstalled("Could not auto-locate app manifest".to_owned())) | ||||
| } | ||||
|  | ||||
| @@ -472,7 +442,7 @@ pub fn auto_locate_app_manifest(context: LocationContext) -> Result<VelopackLoca | ||||
|         IsPortable: true, | ||||
|     }; | ||||
|  | ||||
|     config_to_locator(&config) | ||||
|     Ok(VelopackLocator::new_with_manifest(config, app)) | ||||
| } | ||||
|  | ||||
| #[cfg(target_os = "macos")] | ||||
| @@ -520,8 +490,8 @@ pub fn auto_locate_app_manifest(context: LocationContext) -> Result<VelopackLoca | ||||
|         CurrentBinaryDir: contents_dir, | ||||
|         IsPortable: true, | ||||
|     }; | ||||
|  | ||||
|     config_to_locator(&config) | ||||
|      | ||||
|     Ok(VelopackLocator::new_with_manifest(config, app)) | ||||
| } | ||||
|  | ||||
| fn read_current_manifest(nuspec_path: &PathBuf) -> Result<Manifest, Error> { | ||||
| @@ -569,7 +539,7 @@ fn test_locator_staged_id_for_new_user() { | ||||
|     //Esure the packages directory exists | ||||
|     assert!(std::fs::create_dir_all(&paths.PackagesDir).is_ok()); | ||||
|  | ||||
|     let locator = VelopackLocator::new(paths, Manifest::default()); | ||||
|     let locator = VelopackLocator::new_with_manifest(paths, Manifest::default()); | ||||
|  | ||||
|     let staged_user_id = locator.get_staged_user_id(); | ||||
|  | ||||
| @@ -596,7 +566,7 @@ fn test_locator_staged_id_for_existing_user() { | ||||
|     //Esure the packages directory exists | ||||
|     assert!(std::fs::create_dir_all(&paths.PackagesDir).is_ok()); | ||||
|  | ||||
|     let locator = VelopackLocator::new(paths, Manifest::default()); | ||||
|     let locator = VelopackLocator::new_with_manifest(paths, Manifest::default()); | ||||
|  | ||||
|     let packages_dir = locator.get_packages_dir(); | ||||
|     let beta_id_path = packages_dir.join(".betaId"); | ||||
|   | ||||
							
								
								
									
										162
									
								
								src/lib-rust/src/logging.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								src/lib-rust/src/logging.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,162 @@ | ||||
| #![allow(unused_variables)] | ||||
|  | ||||
| use crate::locator::{LocationContext, VelopackLocator, VelopackLocatorConfig}; | ||||
| use std::path::PathBuf; | ||||
|  | ||||
| #[cfg(not(target_os = "windows"))] | ||||
| use std::path::Path; | ||||
|  | ||||
| #[cfg(feature = "file-logging")] | ||||
| use simplelog::*; | ||||
| #[cfg(feature = "file-logging")] | ||||
| use time::format_description::{modifier, Component, FormatItem}; | ||||
|  | ||||
| #[cfg(target_os = "linux")] | ||||
| fn default_file_linux() -> PathBuf { | ||||
|     Path::new("/tmp/velopack.log").to_path_buf() | ||||
| } | ||||
|  | ||||
| #[cfg(target_os = "macos")] | ||||
| fn default_file_macos() -> PathBuf { | ||||
|     #[allow(deprecated)] | ||||
|     let user_home = std::env::home_dir(); | ||||
|  | ||||
|     if let Some(home) = user_home { | ||||
|         let mut lib_logs = home.clone(); | ||||
|         lib_logs.push("Library"); | ||||
|         lib_logs.push("Logs"); | ||||
|  | ||||
|         if lib_logs.exists() { | ||||
|             lib_logs.push("velopack.log"); | ||||
|             return lib_logs; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return Path::new("/tmp/velopack.log").to_path_buf(); | ||||
| } | ||||
|  | ||||
| /// Default log location for Velopack on the current OS. | ||||
| #[allow(unused_variables)] | ||||
| pub fn default_logfile_from_locator(locator: VelopackLocator) -> PathBuf { | ||||
|     #[cfg(target_os = "windows")] | ||||
|     { | ||||
|         return locator.get_root_dir().join("Velopack.log"); | ||||
|     } | ||||
|     #[cfg(target_os = "linux")] | ||||
|     { | ||||
|         return default_file_linux(); | ||||
|     } | ||||
|     #[cfg(target_os = "macos")] | ||||
|     { | ||||
|         return default_file_macos(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// Default log location for Velopack on the current OS. | ||||
| pub fn default_logfile_from_config(config: &VelopackLocatorConfig) -> PathBuf { | ||||
|     #[cfg(target_os = "windows")] | ||||
|     { | ||||
|         match VelopackLocator::new(config) { | ||||
|             Ok(locator) => { | ||||
|                 return default_logfile_from_locator(locator); | ||||
|             } | ||||
|             Err(e) => warn!("Could not auto-locate app manifest, writing log to current directory. ({})", e), | ||||
|         } | ||||
|  | ||||
|         // If we can't locate the current app, we write to the current directory. | ||||
|         let mut my_exe = std::env::current_exe().expect("Could not locate current executable"); | ||||
|         my_exe.pop(); | ||||
|         return my_exe.join("Velopack.log"); | ||||
|     } | ||||
|     #[cfg(target_os = "linux")] | ||||
|     { | ||||
|         return default_file_linux(); | ||||
|     } | ||||
|     #[cfg(target_os = "macos")] | ||||
|     { | ||||
|         return default_file_macos(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// Default log location for Velopack on the current OS. | ||||
| #[allow(unused_variables)] | ||||
| pub fn default_logfile_from_context(context: LocationContext) -> PathBuf { | ||||
|     use crate::locator::{auto_locate_app_manifest}; | ||||
|     #[cfg(target_os = "windows")] | ||||
|     { | ||||
|         match auto_locate_app_manifest(context) { | ||||
|             Ok(locator) => { | ||||
|                 return default_logfile_from_locator(locator); | ||||
|             } | ||||
|             Err(e) => warn!("Could not auto-locate app manifest, writing log to current directory. ({})", e), | ||||
|         } | ||||
|  | ||||
|         // If we can't locate the current app, we write to the current directory. | ||||
|         let mut my_exe = std::env::current_exe().expect("Could not locate current executable"); | ||||
|         my_exe.pop(); | ||||
|         return my_exe.join("Velopack.log"); | ||||
|     } | ||||
|     #[cfg(target_os = "linux")] | ||||
|     { | ||||
|         return default_file_linux(); | ||||
|     } | ||||
|     #[cfg(target_os = "macos")] | ||||
|     { | ||||
|         return default_file_macos(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// Initialize logging for the current process. This will log optionally to a file and/or the console. | ||||
| /// It can only be called once per process, and should be called early in the process lifecycle. | ||||
| /// Future calls to this function will fail. | ||||
| #[cfg(feature = "file-logging")] | ||||
| pub fn init_logging(process_name: &str, file: Option<&PathBuf>, console: bool, verbose: bool) { | ||||
|     let mut loggers: Vec<Box<dyn SharedLogger>> = Vec::new(); | ||||
|     let color_choice = ColorChoice::Never; | ||||
|     if console { | ||||
|         let console_level = if verbose { LevelFilter::Debug } else { LevelFilter::Info }; | ||||
|         loggers.push(TermLogger::new(console_level, get_config(None), TerminalMode::Mixed, color_choice)); | ||||
|     } | ||||
|  | ||||
|     if let Some(f) = file { | ||||
|         let file_level = if verbose { LevelFilter::Trace } else { LevelFilter::Info }; | ||||
|         let writer = file_rotate::FileRotate::new( | ||||
|             f.clone(), | ||||
|             file_rotate::suffix::AppendCount::new(1),          // keep 1 old log file | ||||
|             file_rotate::ContentLimit::Bytes(1 * 1024 * 1024), // 1MB max log file size | ||||
|             file_rotate::compression::Compression::None, | ||||
|             None, | ||||
|         ); | ||||
|         loggers.push(WriteLogger::new(file_level, get_config(Some(process_name)), writer)); | ||||
|     } | ||||
|  | ||||
|     if let Ok(()) = CombinedLogger::init(loggers) { | ||||
|         log_panics::init(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "file-logging")] | ||||
| fn get_config(process_name: Option<&str>) -> Config { | ||||
|     let mut c = ConfigBuilder::default(); | ||||
|     let mut prefix = "".to_owned(); | ||||
|     if let Some(pn) = process_name { | ||||
|         prefix = format!("[{}:{}] ", pn, std::process::id()); | ||||
|     } | ||||
|  | ||||
|     let prefix_heaped = Box::leak(prefix.into_boxed_str()); | ||||
|  | ||||
|     let time_format: &'static [FormatItem<'static>] = Box::leak(Box::new([ | ||||
|         FormatItem::Literal(prefix_heaped.as_bytes()), | ||||
|         FormatItem::Literal(b"["), | ||||
|         FormatItem::Component(Component::Hour(modifier::Hour::default())), | ||||
|         FormatItem::Literal(b":"), | ||||
|         FormatItem::Component(Component::Minute(modifier::Minute::default())), | ||||
|         FormatItem::Literal(b":"), | ||||
|         FormatItem::Component(Component::Second(modifier::Second::default())), | ||||
|         FormatItem::Literal(b"]"), | ||||
|     ])); | ||||
|  | ||||
|     c.set_time_format_custom(time_format); | ||||
|     let _ = c.set_time_offset_to_local(); // might fail if local tz can't be determined | ||||
|     c.build() | ||||
| } | ||||
| @@ -173,8 +173,7 @@ impl UpdateManager { | ||||
|     ) -> Result<UpdateManager, Error> { | ||||
|         let locator = if let Some(config) = locator { | ||||
|             warn!("Using explicit locator configuration, ignoring auto-locate."); | ||||
|             let manifest = config.load_manifest()?; | ||||
|             VelopackLocator::new(config.clone(), manifest) | ||||
|             VelopackLocator::new(&config)? | ||||
|         } else { | ||||
|             locator::auto_locate_app_manifest(LocationContext::FromCurrentExe)? | ||||
|         }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user