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
@@ -2209,10 +2209,12 @@ dependencies = [
|
||||
"async-std",
|
||||
"bitflags 2.9.0",
|
||||
"derivative",
|
||||
"file-rotate",
|
||||
"glob",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"log-panics",
|
||||
"normpath",
|
||||
"rand",
|
||||
"regex",
|
||||
@@ -2221,8 +2223,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