Skip to content

Commit

Permalink
feat: add better logging facilities
Browse files Browse the repository at this point in the history
  • Loading branch information
DASPRiD committed May 21, 2023
1 parent 874f1c2 commit 702f7aa
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 73 deletions.
113 changes: 64 additions & 49 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ cfg-if = "1.0.0"
chrono = "0.4.24"
clap = { version = "4.1.4", features = ["derive"] }
directories = "5.0.1"
env_logger = "0.10.0"
file-rotate = "0.7.4"
log = "0.4.17"
reqwest = { version = "0.11.17", features = ["default", "json"], optional = true }
serde = { version = "1.0.163", features = ["derive"] }
simplelog = "0.12.1"
sysinfo = "0.29.0"
tokio = { version = "1.27.0", features = ["full"] }
tokio-graceful-shutdown = "0.12.1"
Expand Down
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ This is an OSC manager for handling multiple VRChat OSC plugins at once.

## Configuration

Before you run the program, you should create a configuration file named `osc-manager.toml` in your config directory. On
Linux, that'd be `~/.config`, on Windows, that'd be `C:\Users\username\Application Data`. If the file does not exist,
the OSC Manager will create it with default values.
Before you run the program, you should create a configuration file named `vrc-osc-manager.toml` in your config
directory. On Linux, that'd be `~/.config`, on Windows, that'd be `C:\Users\username\Application Data`. If the file does
not exist, the OSC Manager will create it with default values.

You can find the skeleton for that config file in the `examples` folder.

Expand All @@ -33,7 +33,19 @@ Via the tray icon menu you also have two options available:
## Activity check

By default, plugins will only be started when VRChat is detected to be running. If you need them running for testing
outside of VRChat, you can disable the activity check by passing `--disable-activity-check` as command line argument.
outside VRChat, you can disable the activity check by passing `--disable-activity-check` as command line argument.

## Logging

The application normally logs all messages with info level and higher to the console as well as to a rotating log file.
In case you experience any unexpected crashes or behaviours, you should create a bug report with the latest log file
attached. To generate more verbose logging, you can pass the `--debug` command line argument.

Please note that on Windows oyu will not see any debug output on the console with a release build.

Log files can be found on Linux under `~/.local/share/vrc-osc-manager\logs`. On Windows they should be located under
`C:\Users\username\Application Data\vrc-osc-manager\logs`. The latest log file is always called `log`, while older
ones are suffixed with a timestamp. Log files are rotated every hour and a maximum of 12 log files is every kept.

## Dark mode

Expand Down
5 changes: 2 additions & 3 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,8 @@ pub struct Config {

pub async fn load_config() -> Result<Config> {
let base_dirs = BaseDirs::new().context("Base directories not available")?;
let home_dir = base_dirs.config_dir();

let path = home_dir.join("osc-manager.toml");
let config_dir = base_dirs.config_dir();
let path = config_dir.join("vrc-osc-manager.toml");

if !path.exists() {
let config: Config = Default::default();
Expand Down
65 changes: 54 additions & 11 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@ mod plugins;
mod tray;

use crate::config::{load_config, Config};
use anyhow::Result;
use anyhow::{bail, Context, Result};
use async_osc::OscMessage;
use clap::Parser;
use log::{debug, info};
use directories::BaseDirs;
use file_rotate::compression::Compression;
use file_rotate::suffix::{AppendTimestamp, FileLimit};
use file_rotate::{ContentLimit, FileRotate, TimeFrequency};
use log::{debug, error, info, LevelFilter};
use simplelog::{ColorChoice, CombinedLogger, TermLogger, TerminalMode, WriteLogger};
use std::sync::Arc;
use std::time::Duration;
use sysinfo::{ProcessRefreshKind, RefreshKind, System, SystemExt};
Expand Down Expand Up @@ -47,7 +52,7 @@ impl VrChatActivity {
vrchat_running = running;
self.tx.send(vrchat_running).await?;

info!(
debug!(
"VRChat has {}",
if vrchat_running { "started" } else { "stopped" }
);
Expand Down Expand Up @@ -134,6 +139,7 @@ impl Launcher {
loop {
select! {
Some(()) = reload_rx.recv() => {
info!("Reloading plugins");
self.config = Arc::new(load_config().await?);

if let Some(plugin_subsys) = maybe_plugin_subsys {
Expand All @@ -151,6 +157,7 @@ impl Launcher {
Some(vrchat_running) = self.rx.recv() => {
if vrchat_running {
if maybe_plugin_subsys.is_none() {
info!("Starting plugins");
tray.set_running(true)?;

let config = self.config.clone();
Expand All @@ -163,6 +170,7 @@ impl Launcher {
}
} else if !vrchat_running {
if let Some(plugin_subsys) = maybe_plugin_subsys {
info!("Stopping plugins");
tray.set_running(false)?;

subsys.perform_partial_shutdown(plugin_subsys).await?;
Expand All @@ -171,12 +179,10 @@ impl Launcher {
}
}
else => {
break;
bail!("Select yielded an unexpected result while waiting for activity message")
}
}
}

Ok(())
}

async fn run(mut self, subsys: SubsystemHandle) -> Result<()> {
Expand All @@ -199,14 +205,45 @@ struct Args {
/// Run all plugins, even when VRChat is not running
#[arg(long, default_value_t = false)]
disable_activity_check: bool,

/// Enable debug logging
#[arg(long, default_value_t = false)]
debug: bool,
}

#[tokio::main]
async fn main() -> Result<()> {
env_logger::init();

let args = Args::parse();

let base_dirs = BaseDirs::new().context("Base directories not available")?;
let data_dir = base_dirs.data_dir();
let log_dir = data_dir.join("vrc-osc-manager/logs/log");

let log_file = FileRotate::new(
log_dir,
AppendTimestamp::default(FileLimit::MaxFiles(12)),
ContentLimit::Time(TimeFrequency::Hourly),
Compression::None,
#[cfg(unix)]
None,
);

let log_filter = if args.debug {
LevelFilter::Debug
} else {
LevelFilter::Info
};

CombinedLogger::init(vec![
TermLogger::new(
log_filter,
simplelog::Config::default(),
TerminalMode::Mixed,
ColorChoice::Auto,
),
WriteLogger::new(log_filter, simplelog::Config::default(), log_file),
])?;

let config = Arc::new(load_config().await?);
let (tx, rx) = mpsc::channel(2);

Expand All @@ -217,7 +254,7 @@ async fn main() -> Result<()> {
let send_port = config.osc.send_port;
let receive_port = config.osc.receive_port;

Toplevel::new()
let result = Toplevel::new()
.start("VrChatActivity", move |subsys| {
VrChatActivity::new(tx, args.disable_activity_check).run(subsys)
})
Expand All @@ -239,6 +276,12 @@ async fn main() -> Result<()> {
})
.catch_signals()
.handle_shutdown_requests(Duration::from_millis(1000))
.await
.map_err(Into::into)
.await;

if let Err(error) = result {
error!("Program crash occurred: {}", error);
return Err(error.into());
}

Ok(())
}
Loading

0 comments on commit 702f7aa

Please sign in to comment.