chore: Add a bunch of logging

This commit is contained in:
LynithDev 2026-07-14 18:06:23 +02:00
parent b7e5b0b75b
commit 04c944ec30
69 changed files with 424 additions and 93 deletions

View file

@ -125,10 +125,12 @@ impl Component for DataSync {
last_clusters.set(clusters_pulse);
spawn(async move { invalidate_cluster_queries().await });
}
if *last_profiles.peek() != profiles_pulse {
last_profiles.set(profiles_pulse);
spawn(async move { invalidate_profile_queries().await });
}
if *last_java.peek() != java_pulse {
last_java.set(java_pulse);
spawn(async move { invalidate_java_queries().await });

View file

@ -21,6 +21,7 @@ impl QueryCapability for CachedImageQuery {
type Err = LauncherError;
type Keys = CachedImageKeys;
#[tracing::instrument(name = "cached_image", level = "debug", skip(self, keys), fields(url = %keys.url, max_edge = keys.max_edge))]
async fn run(&self, keys: &Self::Keys) -> Result<Self::Ok, Self::Err> {
if keys.url.is_empty() {
return Err(LauncherError::Minecraft("no image url".to_string()));

View file

@ -39,6 +39,7 @@ impl QueryCapability for PackageSearchQuery {
type Err = LauncherError;
type Keys = PackageSearchKeys;
#[tracing::instrument(name = "package_search", level = "debug", skip(self, keys), fields(provider = ?keys.provider, page = keys.page))]
async fn run(&self, keys: &Self::Keys) -> Result<Self::Ok, Self::Err> {
let state = LauncherState::get()?;
let provider = state.services.packages.get(keys.provider)?;
@ -165,6 +166,7 @@ impl QueryCapability for PackageMetaBatchQuery {
type Err = LauncherError;
type Keys = PackageMetaBatchKeys;
#[tracing::instrument(name = "package_meta_batch", level = "debug", skip(self, keys), fields(provider = ?keys.provider, ids = keys.project_ids.len()))]
async fn run(&self, keys: &Self::Keys) -> Result<Self::Ok, Self::Err> {
let state = LauncherState::get()?;
oneclient_core::packages::fetch_package_meta(
@ -286,6 +288,7 @@ impl QueryCapability for PackageCategoriesQuery {
type Err = LauncherError;
type Keys = PackageCategoriesKeys;
#[tracing::instrument(name = "package_categories", level = "debug", skip(self, keys), fields(provider = ?keys.provider))]
async fn run(&self, keys: &Self::Keys) -> Result<Self::Ok, Self::Err> {
let state = LauncherState::get()?;
let provider = state.services.packages.get(keys.provider)?;

View file

@ -1,5 +1,7 @@
// TODO: Remove this once freya has some workaround for this
#![allow(float_literal_f32_fallback)]
// Deeply nested async call chains through instrumented oneclient_core fns exceed the default limit
#![recursion_limit = "256"]
mod assets;
mod bridge;

View file

@ -1,4 +1,4 @@
#![recursion_limit = "256"]
use oneclient_core::clusters::{ClusterManager, CreateClusterOptions};
use oneclient_core::dev;
use oneclient_core::packages::domain::GameLoader;

View file

@ -1,3 +1,4 @@
#![recursion_limit = "256"]
use oneclient_core::LauncherResult;
use oneclient_core::auth;

View file

@ -18,7 +18,9 @@ use crate::LauncherResult;
use crate::notification::MicrosoftLoginStatus;
use crate::state::LauncherState;
#[tracing::instrument(skip_all)]
pub async fn begin_microsoft_login() -> LauncherResult<MicrosoftLoginSession> {
tracing::info!("beginning Microsoft login");
let state = LauncherState::get()?;
let client = state.services.requester.http();
@ -34,9 +36,11 @@ pub async fn begin_microsoft_login() -> LauncherResult<MicrosoftLoginSession> {
Ok(MicrosoftLoginSession { browser, device })
}
#[tracing::instrument(skip_all)]
pub async fn finish_microsoft_login(
session: MicrosoftLoginSession,
) -> LauncherResult<MinecraftAccount> {
tracing::info!("finishing Microsoft login");
let state = LauncherState::get()?;
let pending = state
@ -68,17 +72,24 @@ pub async fn finish_microsoft_login(
state.services.notifier.microsoft_login_status(None);
if let Err(err) = &result {
tracing::warn!("Microsoft login failed: {err}");
}
let account = result?;
tracing::info!(username = %account.username, "Microsoft login succeeded");
let mut auth = state.auth.lock().await;
auth.commit_account(account, &state.services).await
}
#[tracing::instrument(level = "debug", skip_all)]
pub async fn cancel_microsoft_login(state_token: &str) {
if let Ok(state) = LauncherState::get() {
state.microsoft_logins.lock().await.remove(state_token);
}
}
#[tracing::instrument(skip_all, fields(username = %username))]
pub async fn add_offline_account(username: String) -> LauncherResult<MinecraftAccount> {
let state = LauncherState::get()?;
let mut auth = state.auth.lock().await;
@ -97,18 +108,21 @@ pub async fn get_account(id: Uuid) -> LauncherResult<Option<MinecraftAccount>> {
Ok(auth.get_account(id).cloned())
}
#[tracing::instrument(level = "debug", skip_all)]
pub async fn get_default_account() -> LauncherResult<Option<MinecraftAccount>> {
let state = LauncherState::get()?;
let mut auth = state.auth.lock().await;
auth.default_account(&state.services).await
}
#[tracing::instrument(level = "debug", skip_all, fields(?id))]
pub async fn set_default_account(id: Option<Uuid>) -> LauncherResult<()> {
let state = LauncherState::get()?;
let mut auth = state.auth.lock().await;
auth.set_default_user(id).await
}
#[tracing::instrument(skip_all, fields(%id))]
pub async fn remove_account(id: Uuid) -> LauncherResult<()> {
let state = LauncherState::get()?;
let mut auth = state.auth.lock().await;
@ -116,12 +130,14 @@ pub async fn remove_account(id: Uuid) -> LauncherResult<()> {
Ok(())
}
#[tracing::instrument(level = "debug", skip_all, fields(%id))]
pub async fn refresh_account(id: Uuid) -> LauncherResult<Option<MinecraftAccount>> {
let state = LauncherState::get()?;
let mut auth = state.auth.lock().await;
auth.refresh_microsoft_account(id, &state.services).await
}
#[tracing::instrument(level = "debug", skip_all)]
pub async fn refresh_all_accounts() -> LauncherResult<Vec<MinecraftAccount>> {
let state = LauncherState::get()?;
let mut auth = state.auth.lock().await;
@ -137,6 +153,7 @@ pub async fn refresh_all_accounts() -> LauncherResult<Vec<MinecraftAccount>> {
Ok(refreshed)
}
#[tracing::instrument(level = "debug", skip_all, fields(%id))]
pub async fn account_for_launch(id: Uuid) -> LauncherResult<MinecraftAccount> {
let state = LauncherState::get()?;
let mut auth = state.auth.lock().await;

View file

@ -30,16 +30,19 @@ const TOKEN_URL: &str = "https://login.microsoftonline.com/consumers/oauth2/v2.0
const AUTH_STEPS: u64 = 5;
#[tracing::instrument(level = "debug", skip_all)]
pub async fn begin_device_login(client: &Client) -> Result<DeviceCodeLogin, MinecraftAuthError> {
request_device_code(client).await
}
#[tracing::instrument(level = "debug", skip_all)]
pub async fn finish_dual_login(
client: &Client,
pending: PendingBrowserLogin,
device: &DeviceCodeLogin,
on_progress: impl Fn(&str, u64, u64),
) -> Result<MinecraftAccount, MinecraftAuthError> {
tracing::info!("waiting for Microsoft sign-in (browser or device code)");
on_progress("Waiting for sign-in", 0, AUTH_STEPS);
let deadline = Duration::from_secs(device.expires_in);
@ -50,6 +53,7 @@ pub async fn finish_dual_login(
account_from_msa_token(client, msa, on_progress).await
}
#[tracing::instrument(level = "debug", skip_all)]
async fn race_msa_token(
client: &Client,
pending: &PendingBrowserLogin,
@ -97,6 +101,7 @@ pub struct PendingBrowserLogin {
csrf_state: String,
}
#[tracing::instrument(level = "debug", skip_all)]
pub async fn begin_browser_login() -> Result<(BrowserLogin, PendingBrowserLogin), MinecraftAuthError>
{
let listener = TcpListener::bind("127.0.0.1:0")
@ -139,6 +144,7 @@ pub async fn begin_browser_login() -> Result<(BrowserLogin, PendingBrowserLogin)
Ok((login, pending))
}
#[tracing::instrument(level = "debug", skip_all)]
async fn browser_msa_token(
client: &Client,
pending: &PendingBrowserLogin,
@ -147,6 +153,7 @@ async fn browser_msa_token(
exchange_auth_code(client, &code, pending).await
}
#[tracing::instrument(level = "debug", skip_all)]
async fn wait_for_redirect(pending: &PendingBrowserLogin) -> Result<String, MinecraftAuthError> {
loop {
let (mut stream, _) = pending
@ -186,6 +193,7 @@ async fn wait_for_redirect(pending: &PendingBrowserLogin) -> Result<String, Mine
}
if let Some(error) = error {
tracing::warn!(%error, "browser authorization failed");
respond(&mut stream, RedirectPage::Failed).await;
return Err(MinecraftAuthError::BrowserAuthorizationFailed { error });
}
@ -292,6 +300,7 @@ p{{font-size:14px;line-height:1.55;color:#6b7280}}
)
}
#[tracing::instrument(level = "debug", skip_all)]
async fn exchange_auth_code(
client: &Client,
code: &str,
@ -336,10 +345,12 @@ fn pkce_challenge(verifier: &str) -> String {
BASE64_URL_SAFE_NO_PAD.encode(digest)
}
#[tracing::instrument(level = "debug", skip_all, fields(username = %creds.username))]
pub async fn refresh_microsoft_account(
client: &Client,
creds: &MinecraftAccount,
) -> Result<MinecraftAccount, MinecraftAuthError> {
tracing::debug!("refreshing Microsoft account token");
let msa = refresh_msa_token(client, &creds.refresh_token).await?;
let mut account = account_from_msa_token(client, msa, |_, _, _| {}).await?;
account.id = creds.id;
@ -347,6 +358,7 @@ pub async fn refresh_microsoft_account(
Ok(account)
}
#[tracing::instrument(level = "debug", skip_all)]
async fn request_device_code(client: &Client) -> Result<DeviceCodeLogin, MinecraftAuthError> {
let body = [
("client_id", MICROSOFT_CLIENT_ID),
@ -369,6 +381,7 @@ async fn request_device_code(client: &Client) -> Result<DeviceCodeLogin, Minecra
parse_json_response(res, MinecraftAuthStep::DeviceCodeRequest).await
}
#[tracing::instrument(level = "debug", skip_all)]
async fn poll_device_token(
client: &Client,
flow: &DeviceCodeLogin,
@ -452,6 +465,7 @@ async fn poll_device_token(
}
}
#[tracing::instrument(level = "debug", skip_all)]
async fn refresh_msa_token(
client: &Client,
refresh_token: &str,
@ -498,6 +512,7 @@ impl MsaToken {
}
}
#[tracing::instrument(level = "debug", skip_all)]
async fn account_from_msa_token(
client: &Client,
msa: MsaToken,
@ -536,6 +551,7 @@ async fn account_from_msa_token(
})
}
#[tracing::instrument(level = "debug", skip_all)]
async fn xbl_authenticate(
client: &Client,
rps_ticket: &str,
@ -576,6 +592,7 @@ async fn xbl_authenticate(
})
}
#[tracing::instrument(level = "debug", skip_all)]
async fn xsts_authorize(
client: &Client,
user_token: &str,
@ -612,6 +629,7 @@ struct MinecraftToken {
access_token: String,
}
#[tracing::instrument(level = "debug", skip_all)]
async fn minecraft_login(
client: &Client,
uhs: &str,
@ -641,6 +659,7 @@ struct MinecraftProfile {
name: String,
}
#[tracing::instrument(level = "debug", skip_all)]
async fn minecraft_profile(
client: &Client,
token: &str,
@ -665,6 +684,7 @@ async fn minecraft_profile(
#[serde(rename_all = "camelCase")]
struct MinecraftEntitlements {}
#[tracing::instrument(level = "debug", skip_all)]
async fn minecraft_entitlements(
client: &Client,
token: &str,

View file

@ -40,7 +40,9 @@ pub fn validate_offline_username(username: &str) -> LauncherResult<()> {
Ok(())
}
#[tracing::instrument(level = "debug", fields(username = %username))]
pub fn offline_account(username: String) -> MinecraftAccount {
tracing::info!("creating offline account");
MinecraftAccount {
id: offline_uuid(&username),
username,

View file

@ -17,6 +17,7 @@ pub struct CredentialsStore {
}
impl CredentialsStore {
#[tracing::instrument(level = "debug")]
pub async fn load() -> LauncherResult<Self> {
let path = paths::auth_file()?;
if !path.exists() {
@ -32,6 +33,7 @@ impl CredentialsStore {
}
}
#[tracing::instrument(level = "debug", skip_all)]
pub async fn save(&self) -> LauncherResult<()> {
let path = paths::auth_file()?;
@ -57,6 +59,7 @@ impl CredentialsStore {
self.users.get(&id)
}
#[tracing::instrument(level = "debug", skip_all, fields(username = %account.username))]
pub async fn commit_account(
&mut self,
account: MinecraftAccount,
@ -69,6 +72,7 @@ impl CredentialsStore {
}
self.save().await?;
tracing::debug!("committed account to credentials store");
services
.notifier
.send_info("Account added", &format!("Signed in as {}", account.username));
@ -80,6 +84,7 @@ impl CredentialsStore {
Ok(account)
}
#[tracing::instrument(level = "debug", skip(self), fields(username = %username))]
pub async fn add_offline_account_and_save(
&mut self,
username: String,
@ -109,6 +114,7 @@ impl CredentialsStore {
Ok(account)
}
#[tracing::instrument(level = "debug", skip(self, services), fields(%id))]
pub async fn refresh_microsoft_account(
&mut self,
id: Uuid,
@ -129,10 +135,12 @@ impl CredentialsStore {
self.users.insert(id, account.clone());
self.save().await?;
tracing::debug!("refreshed Microsoft account");
Ok(Some(account))
}
#[tracing::instrument(level = "debug", skip(self), fields(%id))]
pub async fn remove_account(&mut self, id: Uuid) -> LauncherResult<Option<MinecraftAccount>> {
let removed = self.users.remove(&id);
@ -144,6 +152,7 @@ impl CredentialsStore {
Ok(removed)
}
#[tracing::instrument(level = "debug", skip(self), fields(?id))]
pub async fn set_default_user(&mut self, id: Option<Uuid>) -> LauncherResult<()> {
if let Some(id) = id
&& !self.users.contains_key(&id)
@ -156,6 +165,7 @@ impl CredentialsStore {
Ok(())
}
#[tracing::instrument(level = "debug", skip_all)]
pub async fn default_account(
&mut self,
services: &LauncherServices,
@ -202,6 +212,7 @@ impl CredentialsStore {
}
}
#[tracing::instrument(level = "debug", skip(self, services), fields(%id))]
pub async fn account_for_launch(
&mut self,
id: Uuid,

View file

@ -21,6 +21,7 @@ fn is_base62(s: &str) -> bool {
!s.is_empty() && s.chars().all(|c| c.is_ascii_alphanumeric())
}
#[tracing::instrument(level = "debug", skip(file, child, services), fields(package = %file.display_name()))]
pub async fn install_package_from_bundle(
file: &BundleFile,
cluster_id: i64,
@ -88,6 +89,7 @@ pub async fn install_package_from_bundle(
Ok(hash)
}
#[tracing::instrument(level = "debug", skip(ext, cluster, child, services), fields(file = %ext.name))]
async fn install_external(
ext: &ExternalFile,
cluster: &ClusterRow,
@ -102,6 +104,7 @@ async fn install_external(
Ok(artifact.hash)
}
#[tracing::instrument(level = "debug", skip(archive, services), fields(bundle = %archive.manifest.name))]
pub async fn extract_bundle_overrides_for_cluster(
archive: &BundleArchive,
cluster_id: i64,
@ -113,6 +116,7 @@ pub async fn extract_bundle_overrides_for_cluster(
Ok(())
}
#[tracing::instrument(skip(bundles, services))]
pub async fn install_bundle(
cluster_id: i64,
bundle_name: &str,
@ -137,6 +141,7 @@ pub async fn install_bundle(
install_enabled_bundle_files(&archive, cluster_id, skip_compatibility, None, services).await
}
#[tracing::instrument(level = "debug", skip(archive, progress, services), fields(bundle = %archive.manifest.name))]
pub async fn install_enabled_bundle_files(
archive: &BundleArchive,
cluster_id: i64,
@ -199,6 +204,13 @@ pub async fn install_enabled_bundle_files(
.cloned()
.collect();
tracing::info!(
cluster_id,
bundle = %bundle_name,
to_install = to_install.len(),
"installing enabled bundle files"
);
let bundle_name = &bundle_name;
let results = futures_util::stream::iter(to_install.into_iter().map(|file| async move {
let child = progress.map(|p| {
@ -241,6 +253,7 @@ pub async fn install_enabled_bundle_files(
const BUNDLE_INSTALL_CONCURRENCY: usize = 6;
#[tracing::instrument(level = "debug", skip(bundles, services))]
pub async fn enabled_bundle_bytes(
cluster_id: i64,
bundles: &BundlesManager,
@ -303,6 +316,7 @@ pub async fn enabled_bundle_bytes(
Ok(total)
}
#[tracing::instrument(level = "debug", skip(services))]
pub async fn set_bundle_package_enabled(
cluster_id: i64,
bundle_name: &str,
@ -326,6 +340,7 @@ pub async fn set_bundle_package_enabled(
Ok(())
}
#[tracing::instrument(level = "debug", skip(services))]
pub async fn list_cluster_bundle_overrides(
cluster_id: i64,
services: &LauncherServices,
@ -337,6 +352,7 @@ pub async fn list_cluster_bundle_overrides(
.collect())
}
#[tracing::instrument(skip(bundles, progress, services))]
pub async fn install_cluster_bundles(
cluster_id: i64,
bundles: &BundlesManager,
@ -373,6 +389,7 @@ pub async fn install_cluster_bundles(
Ok(())
}
#[tracing::instrument(level = "debug", skip(services))]
pub async fn on_user_remove_artifact(
cluster_id: i64,
hash: &str,
@ -381,6 +398,7 @@ pub async fn on_user_remove_artifact(
handle_user_artifact_action(cluster_id, hash, services, OverrideType::Removed).await
}
#[tracing::instrument(level = "debug", skip(services))]
pub async fn on_user_disable_artifact(
cluster_id: i64,
hash: &str,
@ -389,6 +407,7 @@ pub async fn on_user_disable_artifact(
handle_user_artifact_action(cluster_id, hash, services, OverrideType::Disabled).await
}
#[tracing::instrument(level = "debug", skip(services))]
pub async fn on_user_enable_artifact(
cluster_id: i64,
hash: &str,
@ -402,6 +421,7 @@ pub async fn on_user_enable_artifact(
Ok(())
}
#[tracing::instrument(level = "debug", skip(services))]
async fn handle_user_artifact_action(
cluster_id: i64,
hash: &str,
@ -429,6 +449,7 @@ async fn handle_user_artifact_action(
Ok(())
}
#[tracing::instrument(level = "debug", skip(services))]
pub async fn remove_artifact_from_cluster(
cluster_id: i64,
hash: &str,

View file

@ -9,7 +9,6 @@ use reqwest::Method;
use reqwest::header;
use reqwest::StatusCode;
use tokio::sync::RwLock;
use tracing::instrument;
use crate::bundles::error::BundleError;
use crate::bundles::manifest::{BundleManifest as RemoteBundleManifest, RemoteBundleRef};
@ -73,6 +72,7 @@ impl BundlesManager {
}
}
#[tracing::instrument(skip_all)]
pub async fn sync(&self, services: &LauncherServices) -> LauncherResult<bool> {
let Some((manifest, manifest_changed)) = Self::fetch_manifest(services).await? else {
tracing::debug!(
@ -112,6 +112,7 @@ impl BundlesManager {
Ok(true)
}
#[tracing::instrument(level = "debug", skip(self, services))]
pub async fn archives_for(
&self,
services: &LauncherServices,
@ -126,6 +127,7 @@ impl BundlesManager {
Ok(archives)
}
#[tracing::instrument(level = "debug", skip(self))]
async fn manifest_for_archive(
&self,
path: &Path,
@ -141,6 +143,7 @@ impl BundlesManager {
Ok(manifest)
}
#[tracing::instrument(level = "debug", skip(self, services))]
pub async fn list_for(
&self,
services: &LauncherServices,
@ -156,6 +159,7 @@ impl BundlesManager {
.collect::<Result<Vec<_>, _>>()
}
#[tracing::instrument(level = "debug", skip(self, entry, services, bundles_root), fields(remote_path = %entry.remote_path))]
async fn sync_bundle(
&self,
entry: &RemoteBundleRef,
@ -208,6 +212,7 @@ impl BundlesManager {
Ok(())
}
#[tracing::instrument(level = "debug", skip(services))]
async fn fetch_manifest(
services: &LauncherServices,
) -> LauncherResult<Option<(RemoteBundleManifest, bool)>> {
@ -288,7 +293,7 @@ async fn read_cached_manifest(
Ok(Some((manifest, changed)))
}
#[instrument(skip(services))]
#[tracing::instrument(level = "debug", skip(services))]
async fn download_bundle_if_needed(
services: &LauncherServices,
url: &str,

View file

@ -53,6 +53,7 @@ pub struct OverrideSyncReport {
pub deleted: Vec<String>,
}
#[tracing::instrument(level = "debug", skip(cluster, notifier))]
pub async fn sync_bundle_overrides(
archive_path: &Path,
bundle_name: &str,
@ -63,6 +64,7 @@ pub async fn sync_bundle_overrides(
sync_bundle_overrides_at(archive_path, bundle_name, &root, notifier).await
}
#[tracing::instrument(level = "debug", skip(notifier))]
async fn sync_bundle_overrides_at(
archive_path: &Path,
bundle_name: &str,
@ -155,6 +157,14 @@ async fn sync_bundle_overrides_at(
tracing::warn!(error = %err, "failed to persist bundle override lock");
}
tracing::debug!(
bundle = bundle_name,
written = report.written.len(),
conflicts = report.conflicts.len(),
deleted = report.deleted.len(),
"synced bundle overrides"
);
if !report.conflicts.is_empty() {
notify_conflicts(notifier, bundle_name, &report.conflicts);
}

View file

@ -56,6 +56,7 @@ struct PolyMrpackHashes {
pub sha1: String,
}
#[tracing::instrument(level = "debug")]
pub async fn read_meta_from_archive(path: &Path) -> LauncherResult<PolyMrpackMeta> {
let manifest = read_manifest_from_archive(path).await?;
Ok(PolyMrpackMeta {
@ -69,6 +70,7 @@ pub async fn read_meta_from_archive(path: &Path) -> LauncherResult<PolyMrpackMet
})
}
#[tracing::instrument(level = "debug")]
pub async fn read_manifest_from_archive(path: &Path) -> LauncherResult<BundleManifest> {
let file = tokio::fs::File::open(path).await?;
let reader = tokio::io::BufReader::new(file);

View file

@ -1,5 +1,6 @@
use std::sync::atomic::{AtomicBool, Ordering};
use crate::bundles::manager::BundlesManager;
use crate::bundles::ApplyBundleUpdatesResult;
use crate::bundles::updates::apply_bundle_updates_for_all_clusters;
@ -11,10 +12,12 @@ pub fn is_bundle_syncing() -> bool {
BUNDLE_SYNCING.load(Ordering::Relaxed)
}
#[tracing::instrument(skip_all)]
pub async fn sync_all_cluster_bundles(
bundles: &BundlesManager,
services: &LauncherServices,
) -> Vec<(i64, ApplyBundleUpdatesResult)> {
tracing::info!("syncing all cluster bundles");
BUNDLE_SYNCING.store(true, Ordering::Relaxed);
let changed = match apply_bundle_updates_for_all_clusters(bundles, services).await {
Ok(changed) => changed,

View file

@ -8,7 +8,6 @@ use oneclient_db::dao::cluster_bundle as bundle_dao;
use oneclient_db::models::ClusterPatch;
use oneclient_db::models::{BundleTrackedArtifactRow, ClusterBundleOverrideRow, OverrideType};
use tokio::sync::Mutex as AsyncMutex;
use tracing::instrument;
use crate::bundles::install::{install_package_from_bundle, remove_artifact_from_cluster};
use crate::bundles::manager::BundlesManager;
@ -34,6 +33,7 @@ fn cluster_lock(cluster_id: i64) -> Arc<AsyncMutex<()>> {
.clone()
}
#[tracing::instrument(level = "debug", skip(bundles, services))]
pub async fn check_bundle_updates(
cluster_id: i64,
bundles: &BundlesManager,
@ -43,7 +43,7 @@ pub async fn check_bundle_updates(
check_bundle_updates_inner(cluster_id, bundles, services, &overrides).await
}
#[instrument(skip(bundles, services, overrides))]
#[tracing::instrument(level = "debug", skip(bundles, services, overrides))]
async fn check_bundle_updates_inner(
cluster_id: i64,
bundles: &BundlesManager,
@ -307,6 +307,7 @@ async fn check_bundle_updates_inner(
})
}
#[tracing::instrument(skip(bundles, services))]
pub async fn apply_bundle_updates(
cluster_id: i64,
bundles: &BundlesManager,
@ -317,6 +318,14 @@ pub async fn apply_bundle_updates(
let overrides = bundle_dao::list_overrides(&services.db, cluster_id).await?;
let check = check_bundle_updates_inner(cluster_id, bundles, services, &overrides).await?;
tracing::info!(
cluster_id,
updates = check.updates_available.len(),
additions = check.additions_available.len(),
removals = check.removals_available.len(),
"applying bundle updates"
);
let mut result = ApplyBundleUpdatesResult::default();
for removal in check.removals_available {
@ -400,6 +409,7 @@ pub async fn apply_bundle_updates(
Ok(result)
}
#[tracing::instrument(level = "debug", skip_all, fields(cluster_id = update.cluster_id, bundle = %update.bundle_name, new_version = %update.new_version_id))]
async fn apply_single_update(
update: &BundlePackageUpdate,
overrides: &[ClusterBundleOverrideRow],
@ -432,6 +442,7 @@ async fn apply_single_update(
remove_artifact_from_cluster(update.cluster_id, &update.installed_hash, false, services).await
}
#[tracing::instrument(level = "debug", skip_all, fields(cluster_id = addition.cluster_id, bundle = %addition.bundle_name))]
async fn apply_single_addition(
addition: &BundlePackageAddition,
overrides: &[ClusterBundleOverrideRow],
@ -472,6 +483,7 @@ fn should_be_disabled(
})
}
#[tracing::instrument(level = "debug", skip(bundles, services))]
async fn sync_cluster_loader_version_from_bundles(
cluster_id: i64,
bundles: &BundlesManager,
@ -520,6 +532,7 @@ async fn sync_cluster_loader_version_from_bundles(
Ok(())
}
#[tracing::instrument(level = "debug", skip(bundles, services))]
pub async fn get_bundles_with_update_status(
cluster_id: i64,
bundles: &BundlesManager,
@ -616,6 +629,7 @@ pub async fn get_bundles_with_update_status(
Ok(results)
}
#[tracing::instrument(level = "debug", skip_all)]
pub async fn apply_bundle_updates_for_all_clusters(
bundles: &BundlesManager,
services: &LauncherServices,
@ -655,6 +669,7 @@ fn bundle_package_key(
}
}
#[tracing::instrument(level = "debug", skip_all)]
async fn installed_bundle_keys(
services: &LauncherServices,
linked: &[LinkedArtifactInfo],

View file

@ -35,6 +35,7 @@ pub fn parse_changelog(data: &str) -> Vec<ChangelogGroup> {
groups
}
#[tracing::instrument(level = "debug", skip(services))]
pub async fn fetch_changelog(services: &LauncherServices) -> LauncherResult<String> {
let url = format!("{}/oneclient/CHANGE_LOG.md", meta_url_base());
let cache_path = paths::caches_dir()?.join("CHANGE_LOG.md");

View file

@ -1,6 +1,5 @@
use oneclient_db::dao::{cluster as cluster_dao, setting_profile as profile_dao};
use oneclient_db::models::{ClusterId, ClusterPatch, NewCluster};
use tracing::instrument;
use crate::packages::domain::ContentType;
use crate::settings::store::{
@ -28,6 +27,7 @@ impl ClusterManager {
name.trim().to_string()
}
#[tracing::instrument(level = "debug", skip(state))]
pub async fn get(state: &LauncherState, cluster_id: ClusterId) -> LauncherResult<Cluster> {
let row = cluster_dao::get_by_id(&state.services.db, cluster_id)
.await?
@ -35,6 +35,7 @@ impl ClusterManager {
Ok(Cluster::try_from_row(row)?)
}
#[tracing::instrument(level = "debug", skip(state))]
pub async fn list(state: &LauncherState) -> LauncherResult<Vec<Cluster>> {
let rows = cluster_dao::list_all(&state.services.db).await?;
rows.into_iter()
@ -43,7 +44,7 @@ impl ClusterManager {
.map_err(Into::into)
}
#[instrument(skip(state))]
#[tracing::instrument(skip(state))]
pub async fn create(
state: &LauncherState,
options: CreateClusterOptions,
@ -57,14 +58,19 @@ impl ClusterManager {
let cluster_path = crate::paths::clusters_dir()?.join(&folder_name);
match create_inner(state, &options, &name, &folder_name, &cluster_path).await {
Ok(cluster) => Ok(cluster),
Ok(cluster) => {
tracing::info!(cluster_id = cluster.id, name = %cluster.name, "created cluster");
Ok(cluster)
}
Err(err) => {
tracing::warn!(name = %name, error = %err, "cluster creation failed, cleaning up directory");
let _ = polyio::remove_dir_all(&cluster_path).await;
Err(err)
}
}
}
#[tracing::instrument(level = "debug", skip(state))]
pub async fn update(
state: &LauncherState,
cluster_id: ClusterId,
@ -92,6 +98,7 @@ impl ClusterManager {
Ok(Cluster::try_from_row(row)?)
}
#[tracing::instrument(skip(state))]
pub async fn delete(
state: &LauncherState,
cluster_id: ClusterId,
@ -110,9 +117,11 @@ impl ClusterManager {
}
}
tracing::info!(cluster_id, remove_files, "deleted cluster");
Ok(())
}
#[tracing::instrument(level = "debug", skip(state))]
pub async fn set_stage(
state: &LauncherState,
cluster_id: ClusterId,
@ -122,6 +131,7 @@ impl ClusterManager {
Ok(Cluster::try_from_row(row)?)
}
#[tracing::instrument(level = "debug", skip(state))]
pub async fn uses_dedicated_dir(
state: &LauncherState,
cluster_id: ClusterId,
@ -129,6 +139,7 @@ impl ClusterManager {
Ok(Self::get(state, cluster_id).await?.uses_dedicated_dir())
}
#[tracing::instrument(level = "debug", skip(state))]
pub async fn set_dedicated_dir(
state: &LauncherState,
cluster_id: ClusterId,
@ -149,6 +160,7 @@ impl ClusterManager {
Ok(())
}
#[tracing::instrument(level = "debug", skip(state))]
pub async fn add_playtime(
state: &LauncherState,
cluster_id: ClusterId,
@ -160,6 +172,7 @@ impl ClusterManager {
Ok(Cluster::try_from_row(row)?)
}
#[tracing::instrument(level = "debug", skip(state, cluster), fields(cluster_id = cluster.id))]
pub async fn resolve_settings(
state: &LauncherState,
cluster: &Cluster,
@ -174,6 +187,7 @@ impl ClusterManager {
.await
}
#[tracing::instrument(level = "debug", skip(state, update))]
pub async fn update_profile(
state: &LauncherState,
cluster_id: ClusterId,
@ -187,6 +201,7 @@ impl ClusterManager {
update_named_profile(&state.services.db, &profile_name, update).await
}
#[tracing::instrument(skip(state, shared_progress))]
pub async fn prepare(
state: &Arc<LauncherState>,
cluster_id: ClusterId,
@ -208,6 +223,7 @@ impl ClusterManager {
.await
}
#[tracing::instrument(level = "debug", skip(state))]
pub async fn create_and_assign_profile(
state: &LauncherState,
cluster_id: ClusterId,
@ -235,6 +251,7 @@ impl ClusterManager {
}
}
#[tracing::instrument(level = "debug", skip(state, options))]
async fn create_inner(
state: &LauncherState,
options: &CreateClusterOptions,
@ -273,6 +290,7 @@ async fn create_inner(
Ok(Cluster::try_from_row(row)?)
}
#[tracing::instrument(level = "debug", skip(pool))]
async fn ensure_profile_exists(pool: &oneclient_db::DbPool, name: &str) -> LauncherResult<()> {
if profile_dao::get_by_name(pool, name).await?.is_none() {
return Err(ClusterError::ProfileNotFound(name.to_string()).into());
@ -280,6 +298,7 @@ async fn ensure_profile_exists(pool: &oneclient_db::DbPool, name: &str) -> Launc
Ok(())
}
#[tracing::instrument(level = "debug")]
async fn resolve_unique_folder_name(name: &str) -> LauncherResult<String> {
let cluster_dir = crate::paths::clusters_dir()?;
let mut folder_name = name.to_string();
@ -301,6 +320,7 @@ async fn resolve_unique_folder_name(name: &str) -> LauncherResult<String> {
Ok(folder_name)
}
#[tracing::instrument(level = "debug")]
async fn ensure_content_dirs(cluster_path: &std::path::Path) -> LauncherResult<()> {
for content_type in [
ContentType::Mod,

View file

@ -4,7 +4,6 @@ use std::sync::Arc;
use interfrost::api::minecraft::{DownloadType, VersionInfo};
use interfrost::api::modded::SidedDataEntry;
use tokio::process::Command;
use tracing::instrument;
use crate::clusters::cluster::Cluster;
use crate::clusters::error::ClusterError;
@ -21,7 +20,7 @@ use crate::paths;
use crate::state::LauncherState;
use crate::{GameError, LauncherResult};
#[instrument(skip(state, metadata, shared_progress))]
#[tracing::instrument(skip(state, metadata, shared_progress))]
pub async fn prepare_cluster(
state: &Arc<LauncherState>,
metadata: &mut MetadataStore,
@ -34,6 +33,14 @@ pub async fn prepare_cluster(
let cluster = ClusterManager::get(state, cluster_id).await?;
let continuing = cluster.stage == ClusterStage::Downloading;
tracing::info!(
cluster_id,
mc_version = %cluster.mc_version,
force,
continuing,
"preparing cluster"
);
if !continuing {
ClusterManager::set_stage(state, cluster_id, ClusterStage::Downloading).await?;
}
@ -62,6 +69,7 @@ pub async fn prepare_cluster(
}
if let Err(err) = result {
tracing::error!(cluster_id, error = %err, "cluster preparation failed");
if !continuing {
let _ = ClusterManager::set_stage(state, cluster_id, ClusterStage::NotReady).await;
}
@ -69,6 +77,7 @@ pub async fn prepare_cluster(
}
let cluster = ClusterManager::set_stage(state, cluster_id, ClusterStage::Ready).await?;
tracing::debug!(cluster_id, "cluster stage set to Ready");
Ok(cluster)
}
@ -91,6 +100,7 @@ fn game_download_bytes(info: &VersionInfo) -> u64 {
client + assets + libraries
}
#[tracing::instrument(level = "debug", skip(state, bundles))]
pub async fn estimate_cluster_download(
state: &Arc<LauncherState>,
cluster_id: i64,
@ -134,6 +144,7 @@ pub async fn estimate_cluster_download(
Ok(total)
}
#[tracing::instrument(skip(state, metadata, cluster, progress), fields(cluster_id = cluster.id))]
async fn install_cluster(
state: &Arc<LauncherState>,
metadata: &mut MetadataStore,
@ -205,6 +216,7 @@ async fn install_cluster(
Ok(())
}
#[tracing::instrument(level = "debug", skip(cluster, version_info, java), fields(cluster_id = cluster.id))]
async fn run_forge_processors(
cluster: &Cluster,
version_info: &mut VersionInfo,

View file

@ -1,7 +1,6 @@
use std::str::FromStr;
use oneclient_db::dao::{bundle as bundle_dao, cluster as cluster_dao};
use tracing::instrument;
use crate::packages::domain::GameLoader;
use crate::state::LauncherState;
@ -12,7 +11,7 @@ use super::cluster::Cluster;
use super::manager::ClusterManager;
use super::options::CreateClusterOptions;
#[instrument(skip(state))]
#[tracing::instrument(skip(state))]
pub async fn ensure_from_bundles(state: &LauncherState) -> LauncherResult<Vec<Cluster>> {
let groups = bundle_dao::list_distinct_version_loaders(&state.services.db).await?;
let mut created = Vec::new();
@ -69,7 +68,7 @@ pub async fn ensure_from_bundles(state: &LauncherState) -> LauncherResult<Vec<Cl
Ok(created)
}
#[instrument(skip(state))]
#[tracing::instrument(skip(state))]
pub async fn ensure_from_versions(state: &LauncherState) -> LauncherResult<Vec<Cluster>> {
let metadata = state.versions.metadata().await;
let mut created = Vec::new();

View file

@ -233,6 +233,7 @@ pub struct Analytics {
pub servers: Vec<ServerStat>,
}
#[tracing::instrument(level = "debug")]
pub async fn global_analytics() -> LauncherResult<Analytics> {
let state = LauncherState::get()?;
let db = &state.services.db;
@ -244,6 +245,7 @@ pub async fn global_analytics() -> LauncherResult<Analytics> {
})
}
#[tracing::instrument(level = "debug")]
pub async fn cluster_analytics(cluster_id: i64) -> LauncherResult<Analytics> {
let state = LauncherState::get()?;
let db = &state.services.db;

View file

@ -168,6 +168,7 @@ pub fn processor_arguments<T: AsRef<str>, S: std::hash::BuildHasher>(
Ok(parsed)
}
#[tracing::instrument(skip_all, level = "debug")]
pub async fn main_class(path: impl AsRef<std::path::Path>) -> LauncherResult<Option<String>> {
let data = polyio::read(path.as_ref()).await?;
let mut class_name = None;

View file

@ -6,6 +6,7 @@ use crate::http::{RequestClient, ResponseExt, ResponseNotifyOptions, ResponseOpt
use crate::notification::{GroupedProgressSession, NotificationService, TaskPhase};
use crate::{LauncherError, LauncherResult};
#[tracing::instrument(skip(requester, notifier, progress, label, expected_sha1), fields(%url), level = "debug")]
pub async fn download_to_path(
requester: &RequestClient,
notifier: &NotificationService,
@ -56,6 +57,7 @@ pub async fn download_to_path(
Ok(())
}
#[tracing::instrument(skip(requester, notifier, progress, label), fields(%url), level = "debug")]
pub async fn fetch_bytes_verified(
requester: &RequestClient,
notifier: &NotificationService,

View file

@ -40,8 +40,11 @@ pub async fn launch_cluster(
account: &MinecraftAccount,
search_for_java: bool,
) -> LauncherResult<LaunchedGame> {
tracing::info!(cluster_id, search_for_java, "launching cluster");
let parallel = state.settings.read().allow_parallel_running_clusters;
if !parallel && state.games.is_running(cluster_id) {
tracing::warn!(cluster_id, "cluster already running; refusing launch");
return Err(GameError::AlreadyRunning(cluster_id).into());
}
@ -435,6 +438,7 @@ fn apply_env(command: &mut Command, profile: &GameSettingsProfile) {
}
}
#[tracing::instrument(skip(cwd), fields(hook), level = "debug")]
async fn run_hook(hook: Option<&str>, cwd: &Path) {
let Some(hook) = hook.map(str::trim).filter(|h| !h.is_empty()) else {
return;

View file

@ -4,7 +4,6 @@ use futures_util::{StreamExt, stream};
use interfrost::api::minecraft::{AssetsIndex, DownloadType, Library, Os, Version, VersionInfo};
use interfrost::api::modded::LoaderVersion;
use reqwest::Method;
use tracing::instrument;
use crate::game::GameError;
use crate::game::download::{download_to_path, fetch_bytes_verified};
@ -18,7 +17,7 @@ use crate::paths;
use crate::state::LauncherServices;
use crate::{LauncherError, LauncherResult};
#[instrument(skip_all)]
#[tracing::instrument(skip_all)]
pub async fn download_minecraft(
services: &LauncherServices,
progress: &GroupedProgressSession,
@ -51,7 +50,7 @@ pub async fn download_minecraft(
Ok(())
}
#[instrument(skip(services, progress))]
#[tracing::instrument(skip(services, progress), level = "debug")]
pub async fn download_version_info(
services: &LauncherServices,
progress: Option<&GroupedProgressSession>,
@ -71,7 +70,7 @@ pub async fn download_version_info(
let data = polyio::read(&path).await?;
serde_json::from_slice(&data)?
} else {
tracing::info!(
tracing::debug!(
version_id = %version_id,
"downloading Minecraft version metadata"
);
@ -150,7 +149,7 @@ pub async fn download_version_info(
Ok(result)
}
#[instrument(skip_all)]
#[tracing::instrument(skip_all, level = "debug")]
pub async fn download_assets_index(
services: &LauncherServices,
progress: &GroupedProgressSession,
@ -180,7 +179,7 @@ pub async fn download_assets_index(
polyio::read_json(&path).await.map_err(Into::into)
}
#[instrument(skip_all)]
#[tracing::instrument(skip_all, level = "debug")]
pub async fn download_assets(
services: &LauncherServices,
progress: &GroupedProgressSession,
@ -245,6 +244,7 @@ pub async fn download_assets(
Ok(failed)
}
#[tracing::instrument(skip(services, progress, version), fields(version_id = %version.id, force), level = "debug")]
pub async fn download_client(
services: &LauncherServices,
progress: &GroupedProgressSession,
@ -283,6 +283,7 @@ pub async fn download_client(
Ok(path)
}
#[tracing::instrument(skip(version_info), level = "debug")]
pub fn libraries_missing(
version_info: &VersionInfo,
java_arch: &str,
@ -317,6 +318,7 @@ fn lib_short(name: &str) -> String {
}
}
#[tracing::instrument(skip(services, progress, libraries), level = "debug")]
pub async fn download_libraries(
services: &LauncherServices,
progress: &GroupedProgressSession,
@ -452,6 +454,7 @@ pub async fn download_libraries(
Ok(failed)
}
#[tracing::instrument(skip(metadata, services), level = "debug")]
pub async fn get_loader_versions(
metadata: &mut MetadataStore,
services: &LauncherServices,
@ -475,6 +478,7 @@ pub async fn get_loader_versions(
Ok(Vec::new())
}
#[tracing::instrument(skip(metadata, services), level = "debug")]
pub async fn get_loader_version(
metadata: &mut MetadataStore,
services: &LauncherServices,
@ -557,6 +561,7 @@ pub async fn get_loader_version(
}
}
#[tracing::instrument(skip(metadata, services), level = "debug")]
pub async fn resolve_minecraft_version(
metadata: &mut MetadataStore,
services: &LauncherServices,
@ -581,6 +586,7 @@ pub async fn resolve_minecraft_version(
))
}
#[tracing::instrument(skip(metadata, services), level = "debug")]
pub async fn get_game_versions(
metadata: &mut MetadataStore,
services: &LauncherServices,
@ -589,6 +595,7 @@ pub async fn get_game_versions(
Ok(manifest.versions.clone())
}
#[tracing::instrument(skip(metadata, services), level = "debug")]
pub async fn get_loaders_for_version(
metadata: &mut MetadataStore,
services: &LauncherServices,

View file

@ -31,9 +31,13 @@ impl GameProcessManager {
self.kills.lock().unwrap().insert(cluster_id, tx);
}
#[tracing::instrument(skip(self), level = "debug")]
pub fn kill(&self, cluster_id: i64) -> bool {
match self.kills.lock().unwrap().remove(&cluster_id) {
Some(tx) => tx.send(()).is_ok(),
Some(tx) => {
tracing::debug!(cluster_id, "signalling kill to running game");
tx.send(()).is_ok()
}
None => false,
}
}

View file

@ -50,6 +50,7 @@ pub(crate) struct SessionRecorder {
}
impl SessionRecorder {
#[tracing::instrument(skip(state, java), fields(cluster_id, ram_allocated_mb), level = "debug")]
pub(crate) async fn start(
state: &Arc<LauncherState>,
cluster_id: i64,
@ -110,6 +111,7 @@ impl SessionRecorder {
}
}
#[tracing::instrument(skip(self), fields(exit_code), level = "debug")]
pub(crate) async fn finish(self, exit_code: Option<i64>) {
if let Some(open) = self.open_server.lock().await.take()
&& let Err(err) = session_dao::finish_server(&self.db, &open).await
@ -125,6 +127,7 @@ impl SessionRecorder {
}
}
#[tracing::instrument(skip(state), fields(cluster_id), level = "debug")]
async fn count_enabled_mods(state: &Arc<LauncherState>, cluster_id: i64) -> usize {
match PackageStore::list_linked_artifacts(cluster_id, &state.services).await {
Ok(linked) => linked

View file

@ -20,6 +20,7 @@ const SWAP_TYPES: [ContentType; 3] = [
const FABRIC_DEP_OVERRIDES: &str = "config/fabric_loader_dependencies.json";
#[tracing::instrument(skip(services, cluster), fields(cluster_id = cluster.id, game_dir = %game_dir.display()), level = "debug")]
pub async fn sync_shared_content(
services: &LauncherServices,
cluster: &Cluster,
@ -71,6 +72,7 @@ pub async fn sync_shared_content(
Ok(())
}
#[tracing::instrument(skip(services, cluster), fields(cluster_id = cluster.id), level = "debug")]
pub async fn import_manual_content(
services: &LauncherServices,
cluster: &Cluster,
@ -117,7 +119,7 @@ pub async fn import_manual_content(
match PackageStore::import_local_file(&path, content_type, cluster.id, services).await {
Ok(_) => {
tracing::info!(file = name, "registered manually-added shared content")
tracing::debug!(file = name, "registered manually-added shared content")
}
Err(err) => tracing::warn!(
file = name,
@ -140,6 +142,7 @@ fn has_content_extension(content_type: ContentType, name: &str) -> bool {
const ALLOWED_SYMLINKS_NAME: &str = "allowed_symlinks.txt";
#[tracing::instrument(level = "debug")]
pub async fn write_allowed_symlinks(game_dir: &Path) -> LauncherResult<()> {
let root = crate::paths::launcher_dir()?;
let base = polyio::canonicalize(root).unwrap_or_else(|_| root.to_path_buf());
@ -203,6 +206,7 @@ async fn ensure_note(dir: &Path, content_type: ContentType) {
.ok();
}
#[tracing::instrument(level = "debug")]
pub async fn clear_shared_content(game_dir: &Path) -> LauncherResult<()> {
for content_type in SWAP_TYPES {
let dir = game_dir.join(content_type.folder_name());
@ -213,6 +217,7 @@ pub async fn clear_shared_content(game_dir: &Path) -> LauncherResult<()> {
Ok(())
}
#[tracing::instrument(skip(cluster), fields(cluster_id = cluster.id), level = "debug")]
pub async fn link_cluster_logs(cluster: &Cluster, game_dir: &Path) {
let cluster_dir = match cluster.dir() {
Ok(dir) => dir,
@ -268,6 +273,7 @@ async fn redirect_dir(shared: &Path, target: &Path) -> LauncherResult<()> {
Ok(())
}
#[tracing::instrument(level = "debug")]
pub async fn unlink_cluster_logs(game_dir: &Path) {
for name in REDIRECTED_DIRS {
let shared = game_dir.join(name);

View file

@ -58,6 +58,7 @@ pub trait ResponseExt {
#[async_trait::async_trait]
impl ResponseExt for Response {
#[tracing::instrument(level = "debug", skip_all)]
async fn stream(
self,
options: ResponseOptions,

View file

@ -87,6 +87,7 @@ impl RequestClient {
}
impl RequestClient {
#[tracing::instrument(level = "debug", skip_all)]
pub async fn send(&self, request: impl Into<HttpRequest>) -> Result<Response, RequestError> {
let request: HttpRequest = request.into();
let mut retries = 0;
@ -103,6 +104,12 @@ impl RequestClient {
let mut active_request = request.request;
tracing::debug!(
method = %active_request.method(),
url = %active_request.url(),
"dispatching http request"
);
let res = loop {
let permit = if request.options.use_semaphore {
self.semaphore.acquire().await.ok()
@ -159,6 +166,7 @@ impl RequestClient {
Ok(res)
}
#[tracing::instrument(level = "debug", skip(self, request, options, services), fields(dest = %dest.as_ref().display()))]
pub async fn download_file(
&self,
request: impl Into<HttpRequest>,
@ -169,12 +177,13 @@ impl RequestClient {
let res = self.send(request).await?;
let http_stream = res.stream(options, &services.notifier).await?;
let http_stream = std::pin::pin!(http_stream);
polyio::write_stream(dest, http_stream).await?;
Ok(())
}
#[tracing::instrument(level = "debug", skip_all)]
pub async fn send_as<T: DeserializeOwned>(&self, request: impl Into<HttpRequest>) -> Result<T, RequestError> {
let res = self.send(request).await?;
let status = res.status();
@ -198,6 +207,7 @@ impl RequestClient {
})
}
#[tracing::instrument(level = "debug", skip(self, body, extra_headers), fields(method = %method, %url))]
pub async fn send_json<T: DeserializeOwned>(
&self,
method: reqwest::Method,

View file

@ -4,7 +4,6 @@ use std::path::PathBuf;
use bytes::Bytes;
use reqwest::Method;
use tokio::sync::Mutex;
use tracing::instrument;
use crate::crypto::sha1_bytes;
use crate::http::RequestError;
@ -25,7 +24,7 @@ impl ImageCacheStore {
Self::default()
}
#[instrument(skip(self, services))]
#[tracing::instrument(level = "debug", skip(self, services))]
pub async fn get(
&self,
services: &LauncherServices,
@ -109,6 +108,7 @@ fn downscale(bytes: &[u8], max_edge: u32) -> Option<Bytes> {
Some(Bytes::from(out))
}
#[tracing::instrument(level = "debug", skip(services))]
async fn download(services: &LauncherServices, url: &str) -> LauncherResult<Bytes> {
let parsed = url.parse().map_err(RequestError::from)?;
let request = reqwest::Request::new(Method::GET, parsed);

View file

@ -2,7 +2,6 @@ use std::{collections::HashMap, path::PathBuf};
use async_tempfile::TempDir;
use tokio::sync::OnceCell;
use tracing::instrument;
use crate::java::{JavaError, JavaResult};
@ -15,7 +14,7 @@ pub struct JavaCheckInfo {
pub os_arch: String,
}
#[instrument(level = "info", skip(absolute_path))]
#[tracing::instrument(level = "debug", skip(absolute_path))]
pub async fn check_java_runtime(absolute_path: String) -> JavaResult<JavaCheckInfo> {
let temp_dir = get_java_info_dir().await?;
@ -33,7 +32,7 @@ pub async fn check_java_runtime(absolute_path: String) -> JavaResult<JavaCheckIn
.map(|arg| arg.to_string_lossy().into_owned())
.collect();
tracing::info!("running command: {} {}", program, args.join(" "));
tracing::debug!("running command: {} {}", program, args.join(" "));
let output = command.output().await
.map_err(|e| JavaError::RuntimeCheckError {
@ -72,6 +71,7 @@ pub async fn check_java_runtime(absolute_path: String) -> JavaResult<JavaCheckIn
static TEMP_JAVA_INFO: OnceCell<TempDir> = OnceCell::const_new();
#[tracing::instrument(level = "debug")]
async fn get_java_info_dir() -> Result<&'static PathBuf, polyio::IOError> {
let dir: Result<&TempDir, polyio::IOError> = TEMP_JAVA_INFO
.get_or_try_init(async || {

View file

@ -1,7 +1,6 @@
use std::path::{Path, PathBuf};
use reqwest::Method;
use tracing::instrument;
use url::Url;
use crate::http::{ResponseNotifyOptions, ResponseOptions};
@ -12,7 +11,7 @@ use crate::paths;
use crate::state::LauncherServices;
use crate::LauncherResult;
#[instrument(skip(services))]
#[tracing::instrument(level = "debug", skip(services))]
pub async fn install_package(
package: &JavaPackage,
services: &LauncherServices,
@ -60,10 +59,12 @@ pub async fn install_package(
let _ = tokio::fs::remove_file(&archive_path).await;
tracing::info!(vendor = %package.vendor, major, "installed Java runtime");
Ok(executable)
}
#[instrument]
#[tracing::instrument(level = "debug")]
fn resolve_installed_executable(extract_root: &Path, package: &JavaPackage) -> PathBuf {
let mut base_path = extract_root.to_path_buf();
@ -93,7 +94,7 @@ fn resolve_installed_executable(extract_root: &Path, package: &JavaPackage) -> P
#[cfg(target_os = "macos")]
{
use crate::java::vendors::JavaVendor;
if !base_path.join("Contents").join("Home").exists() {
if let Ok(mut entries) = std::fs::read_dir(&base_path) {
if let Some(dir) = entries.flatten().find(|entry| {

View file

@ -1,11 +1,13 @@
use std::collections::HashMap;
use std::path::PathBuf;
use crate::constants::JAVA_BIN;
use crate::java::checker::{check_java_runtime, JavaCheckInfo};
use crate::java::data::java_executable_relative_path;
use crate::LauncherResult;
#[tracing::instrument(level = "debug")]
pub async fn locate_java() -> LauncherResult<HashMap<PathBuf, JavaCheckInfo>> {
let paths = internal_locate_java();
let mut valid = HashMap::new();
@ -18,10 +20,13 @@ pub async fn locate_java() -> LauncherResult<HashMap<PathBuf, JavaCheckInfo>> {
valid.insert(path, info);
}
tracing::debug!(count = valid.len(), "located Java runtimes");
Ok(valid)
}
#[cfg(target_os = "windows")]
#[tracing::instrument(level = "debug")]
fn internal_locate_java() -> Vec<PathBuf> {
let mut java_homes = Vec::new();
@ -78,6 +83,7 @@ fn internal_locate_java() -> Vec<PathBuf> {
}
#[cfg(target_os = "macos")]
#[tracing::instrument(level = "debug")]
fn internal_locate_java() -> Vec<PathBuf> {
let mut found = Vec::new();
@ -115,6 +121,7 @@ fn internal_locate_java() -> Vec<PathBuf> {
}
#[cfg(target_os = "linux")]
#[tracing::instrument(level = "debug")]
fn internal_locate_java() -> Vec<PathBuf> {
let mut found = Vec::new();

View file

@ -24,6 +24,7 @@ pub struct AvailableJava {
pub struct JavaManager;
impl JavaManager {
#[tracing::instrument(skip(state))]
pub async fn prepare_java(
state: &Arc<LauncherState>,
major: u32,
@ -32,6 +33,7 @@ impl JavaManager {
Self::prepare_java_with_services(&state.services, major, search_system, false).await
}
#[tracing::instrument(skip(state))]
pub async fn prepare_java_auto(
state: &Arc<LauncherState>,
major: u32,
@ -40,6 +42,7 @@ impl JavaManager {
Self::prepare_java_with_services(&state.services, major, search_system, true).await
}
#[tracing::instrument(level = "debug", skip(services))]
pub async fn prepare_java_with_services(
services: &LauncherServices,
major: u32,
@ -69,15 +72,18 @@ impl JavaManager {
}
}
#[tracing::instrument(level = "debug", skip(pool))]
pub async fn list_runtimes(pool: &DbPool) -> LauncherResult<Vec<JavaRuntime>> {
let rows = dao::java::list_all(pool).await?;
Ok(rows.into_iter().map(JavaRuntime::from_row).collect())
}
#[tracing::instrument(level = "debug", skip(pool))]
pub async fn rescan(pool: &DbPool) -> LauncherResult<()> {
register_located_runtimes(pool, java::locate::locate_java().await?).await
}
#[tracing::instrument(skip(services))]
pub async fn install_runtime(
services: &LauncherServices,
major: u32,
@ -85,6 +91,7 @@ impl JavaManager {
download_and_register(major, services).await
}
#[tracing::instrument(level = "debug", skip(services))]
pub async fn available_versions(
services: &LauncherServices,
vendor: &JavaVendor,
@ -115,6 +122,7 @@ impl JavaManager {
Ok(available)
}
#[tracing::instrument(skip(services))]
pub async fn install_runtime_from(
services: &LauncherServices,
vendor: &JavaVendor,
@ -130,6 +138,7 @@ impl JavaManager {
register_checked_java(&services.db, &executable, Some(major)).await
}
#[tracing::instrument(skip(pool))]
pub async fn add_custom_runtime(
pool: &DbPool,
folder: PathBuf,
@ -138,11 +147,14 @@ impl JavaManager {
register_checked_java(pool, &executable, None).await
}
#[tracing::instrument(skip(pool))]
pub async fn remove_runtime(pool: &DbPool, absolute_path: &str) -> LauncherResult<()> {
dao::java::delete_by_path(pool, absolute_path).await?;
tracing::info!("removed Java runtime");
Ok(())
}
#[tracing::instrument(level = "debug", skip(pool))]
pub async fn java_for_profile(
pool: &DbPool,
java_path: Option<&str>,
@ -165,6 +177,7 @@ fn provider_for_vendor(vendor: &JavaVendor) -> Option<Box<dyn vendors::JavaRunti
.find(|provider| &provider.vendor() == vendor)
}
#[tracing::instrument(level = "debug", skip(services))]
async fn download_and_register(
major: u32,
services: &LauncherServices,
@ -203,6 +216,7 @@ async fn download_and_register(
Err(JavaError::PackageNotFound { major }.into())
}
#[tracing::instrument(level = "debug", skip(pool))]
async fn register_custom_java(
pool: &DbPool,
selection: PathBuf,
@ -212,6 +226,7 @@ async fn register_custom_java(
register_checked_java(pool, &executable, Some(expected_major)).await
}
#[tracing::instrument(level = "debug", skip(pool))]
async fn register_checked_java(
pool: &DbPool,
executable: &Path,
@ -233,11 +248,13 @@ async fn register_checked_java(
persist_runtime(pool, executable, &info).await
}
#[tracing::instrument(level = "debug", skip(pool))]
async fn get_latest_runtime(pool: &DbPool, major: u32) -> LauncherResult<Option<JavaRuntime>> {
let row = dao::java::get_latest_by_major(pool, major).await?;
Ok(row.map(JavaRuntime::from_row))
}
#[tracing::instrument(level = "debug", skip_all)]
async fn register_located_runtimes(
pool: &DbPool,
located: impl IntoIterator<Item = (PathBuf, JavaCheckInfo)>,
@ -248,6 +265,7 @@ async fn register_located_runtimes(
Ok(())
}
#[tracing::instrument(level = "debug", skip(pool))]
async fn persist_runtime(
pool: &DbPool,
executable: &Path,

View file

@ -1,9 +1,11 @@
use std::path::{Path, PathBuf};
use crate::constants::JAVA_BIN;
use crate::java::data::java_executable_relative_path;
use crate::java::{JavaError, JavaResult};
#[tracing::instrument(level = "debug", skip_all)]
pub fn resolve_java_executable(selection: impl AsRef<Path>) -> JavaResult<PathBuf> {
let selection = selection.as_ref();
@ -42,6 +44,8 @@ pub fn resolve_java_executable(selection: impl AsRef<Path>) -> JavaResult<PathBu
}
}
tracing::warn!(path = %selection.display(), "no Java executable found in selection");
Err(JavaError::InvalidJavaPath {
path: selection.display().to_string(),
})

View file

@ -45,6 +45,7 @@ impl JavaRuntimeProvider for AdoptiumRuntimeProvider {
JavaVendor::Adoptium
}
#[tracing::instrument(level = "debug", skip(self, services))]
async fn list_packages(
&self,
major: Option<u32>,
@ -97,6 +98,8 @@ impl JavaRuntimeProvider for AdoptiumRuntimeProvider {
}
}
tracing::debug!(count = packages.len(), "listed Adoptium packages");
Ok(packages)
}
}

View file

@ -20,6 +20,7 @@ impl JavaRuntimeProvider for CorrettoRuntimeProvider {
JavaVendor::Corretto
}
#[tracing::instrument(level = "debug", skip(self, services))]
async fn list_packages(
&self,
major: Option<u32>,
@ -74,6 +75,7 @@ impl JavaRuntimeProvider for CorrettoRuntimeProvider {
}
packages.sort_by_key(|p| std::cmp::Reverse(p.java_version.first().copied().unwrap_or(0)));
tracing::debug!(count = packages.len(), "listed Corretto packages");
Ok(packages)
}
}

View file

@ -30,6 +30,7 @@ impl JavaRuntimeProvider for LibericaRuntimeProvider {
JavaVendor::Liberica
}
#[tracing::instrument(level = "debug", skip(self, services))]
async fn list_packages(
&self,
major: Option<u32>,
@ -68,6 +69,8 @@ impl JavaRuntimeProvider for LibericaRuntimeProvider {
})
.collect();
tracing::debug!(count = packages.len(), "listed Liberica packages");
Ok(packages)
}
}

View file

@ -1,5 +1,6 @@
use std::{path::PathBuf, str::FromStr};
use crate::java::JavaPackage;
use crate::state::LauncherServices;
use crate::LauncherResult;
@ -34,6 +35,7 @@ pub trait JavaRuntimeProvider: Send + Sync {
services: &LauncherServices,
) -> LauncherResult<Vec<JavaPackage>>;
#[tracing::instrument(level = "debug", skip(self, services))]
async fn latest_package_by_major(
&self,
major: u32,
@ -43,6 +45,7 @@ pub trait JavaRuntimeProvider: Send + Sync {
Ok(packages.into_iter().find(|p| p.java_version.first() == Some(&major)))
}
#[tracing::instrument(level = "debug", skip_all)]
async fn install_package(
&self,
package: &JavaPackage,

View file

@ -23,10 +23,13 @@ impl JavaRuntimeProvider for ZuluRuntimeProvider {
JavaVendor::Zulu
}
#[tracing::instrument(level = "debug", skip(self, services))]
async fn list_packages(&self, major: Option<u32>, services: &LauncherServices) -> LauncherResult<Vec<JavaPackage>> {
let url = zulu_url(major)?;
let packages = services.requester.send_as::<Vec<ZuluPackage>>(Request::new(Method::GET, url)).await?;
let packages = packages.into_iter().map(map_zulu_package).collect();
let packages: Vec<JavaPackage> = packages.into_iter().map(map_zulu_package).collect();
tracing::debug!(count = packages.len(), "listed Zulu packages");
Ok(packages)
}

View file

@ -19,6 +19,7 @@ pub fn init() -> LauncherResult<()> {
pub fn init_filtered(filter: impl FnOnce() -> EnvFilter) -> LauncherResult<()> {
let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| filter());
let stdout_layer = tracing_subscriber::fmt::layer().with_writer(io::stdout);
#[cfg(debug_assertions)]

View file

@ -65,6 +65,7 @@ fn collect_dir(
}
}
#[tracing::instrument(level = "debug", skip(cluster), fields(cluster_id = cluster.id))]
pub fn list_cluster_logs(cluster: &Cluster) -> LauncherResult<Vec<LogFileInfo>> {
let mut out = Vec::new();
@ -148,12 +149,14 @@ pub(super) async fn read_file_string(path: &Path) -> LauncherResult<String> {
}
}
#[tracing::instrument(level = "debug", skip(opts))]
pub async fn read_log_at(path: &Path, opts: &ReadOptions) -> LauncherResult<Vec<LogLine>> {
let path = ensure_allowed(path)?;
let content = read_file_string(&path).await?;
Ok(lines_from(&content, opts))
}
#[tracing::instrument(level = "debug")]
pub async fn delete_log_at(path: &Path) -> LauncherResult<()> {
let path = ensure_allowed(path)?;

View file

@ -26,6 +26,7 @@ struct MclogsResponse {
error: Option<String>,
}
#[tracing::instrument(skip(services))]
pub async fn upload_log_at(
services: &LauncherServices,
path: &Path,
@ -62,9 +63,13 @@ pub async fn upload_log_at(
let parsed: MclogsResponse = serde_json::from_slice(&bytes)?;
if !parsed.success {
return Err(LogsError::Upload(parsed.error.unwrap_or_else(|| "unknown error".into())).into());
let reason = parsed.error.unwrap_or_else(|| "unknown error".into());
tracing::warn!(reason = %reason, "mclogs upload failed");
return Err(LogsError::Upload(reason).into());
}
tracing::info!(url = parsed.url.as_deref().unwrap_or(""), "uploaded log to mclo.gs");
Ok(MclogsUploadResponse {
id: parsed.id.unwrap_or_default(),
url: parsed.url.unwrap_or_default(),

View file

@ -6,7 +6,6 @@ use interfrost::api::modded::Manifest as ModdedManifest;
use reqwest::Method;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use tracing::instrument;
use crate::api_config::metadata_api_url;
use crate::metadata::MetadataError;
@ -43,7 +42,7 @@ impl MetadataStore {
Self::default()
}
#[instrument(skip(self, services))]
#[tracing::instrument(level = "debug", skip(self, services))]
pub async fn get_vanilla_or_fetch(
&mut self,
services: &LauncherServices,
@ -55,7 +54,7 @@ impl MetadataStore {
self.get_vanilla()
}
#[instrument(skip(self, services))]
#[tracing::instrument(level = "debug", skip(self, services))]
pub async fn get_modded_or_fetch(
&mut self,
services: &LauncherServices,
@ -95,7 +94,7 @@ impl MetadataStore {
.ok_or_else(|| MetadataError::FetchError.into())
}
#[instrument(skip_all)]
#[tracing::instrument(skip_all)]
pub async fn initialize(&mut self, services: &LauncherServices) -> LauncherResult<()> {
let path = paths::caches_dir()?.join("metadata.json");
let mut save_file = false;
@ -130,7 +129,7 @@ impl MetadataStore {
Ok(())
}
#[instrument(skip_all)]
#[tracing::instrument(level = "debug", skip_all)]
pub async fn refetch_errored(&mut self, services: &LauncherServices) -> u8 {
let mut changed: u8 = 0;
@ -171,7 +170,7 @@ impl MetadataStore {
changed
}
#[instrument(skip_all)]
#[tracing::instrument(level = "debug", skip_all)]
pub async fn fetch_all(&mut self, services: &LauncherServices) {
let (minecraft, forge, neo, fabric, quilt, legacyfabric) = tokio::join!(
fetch_vanilla_manifest(services),
@ -190,6 +189,7 @@ impl MetadataStore {
self.inner.legacyfabric = legacyfabric.ok();
}
#[tracing::instrument(level = "debug", skip(self, services))]
pub async fn get_loaders_for_version(
&mut self,
services: &LauncherServices,
@ -233,6 +233,7 @@ impl MetadataStore {
}
}
#[tracing::instrument(level = "debug", skip(services))]
async fn fetch_vanilla_manifest(services: &LauncherServices) -> LauncherResult<VanillaManifest> {
match fetch_manifest::<VanillaManifest>(services, GameLoader::Vanilla).await {
Ok(manifest) => Ok(manifest),
@ -255,6 +256,7 @@ async fn fetch_vanilla_manifest(services: &LauncherServices) -> LauncherResult<V
}
}
#[tracing::instrument(level = "debug", skip(services))]
async fn fetch_modded_manifest(
services: &LauncherServices,
loader: GameLoader,
@ -262,6 +264,7 @@ async fn fetch_modded_manifest(
fetch_manifest(services, loader).await
}
#[tracing::instrument(level = "debug", skip(services))]
async fn fetch_manifest<T: DeserializeOwned>(
services: &LauncherServices,
loader: GameLoader,

View file

@ -1,7 +1,9 @@
use std::path::{Path, PathBuf};
use crate::LauncherResult;
#[tracing::instrument(level = "debug", skip(exclude_top))]
pub async fn copy_tree(src: &Path, dst: &Path, exclude_top: &[&str]) -> LauncherResult<()> {
let mut stack: Vec<(PathBuf, PathBuf, bool)> =
vec![(src.to_path_buf(), dst.to_path_buf(), true)];

View file

@ -65,6 +65,7 @@ pub enum ImportTarget {
Dedicated { new_cluster_id: i64 },
}
#[tracing::instrument]
pub async fn detect() -> LauncherResult<Option<MigrationDetection>> {
for source in MigrationSource::ALL.iter().copied() {
let detection = match source {
@ -80,6 +81,7 @@ pub async fn detect() -> LauncherResult<Option<MigrationDetection>> {
Ok(None)
}
#[tracing::instrument]
pub async fn import_game_dir(
source: MigrationSource,
folder_name: &str,

View file

@ -2,7 +2,6 @@ use std::path::{Path, PathBuf};
use sqlx::Row;
use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions};
use tracing::instrument;
use crate::LauncherResult;
use crate::packages::domain::GameLoader;
@ -33,7 +32,7 @@ pub fn category_from_bundle_name(name: &str) -> Option<String> {
(!inner.is_empty()).then(|| inner.to_string())
}
#[instrument]
#[tracing::instrument]
pub async fn detect() -> LauncherResult<Option<MigrationDetection>> {
let Some(root) = old_root() else {
return Ok(None);
@ -60,6 +59,7 @@ pub async fn detect() -> LauncherResult<Option<MigrationDetection>> {
}
}
#[tracing::instrument(level = "debug")]
async fn detect_inner(root: &Path, db_path: &Path) -> LauncherResult<MigrationDetection> {
let opts = SqliteConnectOptions::new()
.filename(db_path)
@ -113,6 +113,7 @@ async fn detect_inner(root: &Path, db_path: &Path) -> LauncherResult<MigrationDe
})
}
#[tracing::instrument(level = "debug", skip(pool))]
async fn fetch_categories(pool: &sqlx::SqlitePool, cluster_id: i64) -> LauncherResult<Vec<String>> {
let rows = sqlx::query(
"SELECT DISTINCT bundle_name FROM cluster_packages \
@ -137,7 +138,7 @@ async fn fetch_categories(pool: &sqlx::SqlitePool, cluster_id: i64) -> LauncherR
Ok(categories)
}
#[instrument(skip(target))]
#[tracing::instrument(skip(target))]
pub async fn import_game_dir(folder_name: &str, target: ImportTarget) -> LauncherResult<()> {
let Some(root) = old_root() else {
return Ok(());

View file

@ -126,6 +126,7 @@ fn auth_headers(access_token: &str) -> [(&'static str, String); 1] {
[("Authorization", format!("Bearer {access_token}"))]
}
#[tracing::instrument(level = "debug", skip(client))]
pub async fn fetch_player_profile(
client: &RequestClient,
uuid: &str,
@ -213,6 +214,7 @@ pub async fn fetch_player_profile(
})
}
#[tracing::instrument(level = "debug", skip(client, access_token))]
pub async fn fetch_logged_in_profile(
client: &RequestClient,
access_token: &str,
@ -241,6 +243,7 @@ pub async fn fetch_logged_in_profile(
Ok(profile)
}
#[tracing::instrument(level = "debug", skip(client, access_token))]
pub async fn fetch_player_profile_view(
client: &RequestClient,
uuid: &str,

View file

@ -41,6 +41,7 @@ impl NotificationService {
}
}
#[tracing::instrument(level = "debug", skip(self))]
pub async fn prompt_java_install(&self, major: u32) -> Result<UserChoice, NotificationError> {
self.prompt(
"Java required",
@ -52,6 +53,7 @@ impl NotificationService {
.await
}
#[tracing::instrument(level = "debug", skip(self))]
pub async fn prompt_update(&self, version: &str) -> Result<UserChoice, NotificationError> {
self.prompt(
"Update available",
@ -61,6 +63,7 @@ impl NotificationService {
.await
}
#[tracing::instrument(level = "debug", skip(self, question))]
pub async fn prompt(
&self,
title: &str,

View file

@ -1,5 +1,6 @@
use std::path::Path;
use crate::LauncherResult;
use crate::crypto::{normalize_hash, sha1_bytes};
@ -17,6 +18,7 @@ impl FileIdentity {
}
}
#[tracing::instrument(level = "debug", skip(path))]
pub async fn from_path(path: impl AsRef<Path>) -> LauncherResult<Self> {
let bytes = polyio::read(path).await?;
Ok(Self::from_bytes(&bytes))

View file

@ -23,6 +23,7 @@ pub struct CachedPackageMeta {
pub icon_url: Option<String>,
}
#[tracing::instrument(level = "debug", skip(services, project_ids))]
pub async fn read_cached_package_meta(
services: &LauncherServices,
provider: ProviderId,
@ -53,6 +54,7 @@ pub async fn read_cached_package_meta(
.collect()
}
#[tracing::instrument(level = "debug", skip(services))]
pub async fn cached_project_detail(
services: &LauncherServices,
provider: ProviderId,
@ -89,6 +91,7 @@ pub async fn cached_project_detail(
}
}
#[tracing::instrument(level = "debug", skip(services))]
pub async fn get_version_cached(
services: &LauncherServices,
provider: ProviderId,
@ -106,6 +109,7 @@ pub async fn get_version_cached(
.await
}
#[tracing::instrument(level = "debug", skip(services))]
async fn cached_version_detail(
services: &LauncherServices,
provider: ProviderId,
@ -157,6 +161,7 @@ async fn cached_version_detail(
})
}
#[tracing::instrument(level = "debug", skip(services, project_ids))]
pub async fn fetch_package_meta(
services: &LauncherServices,
provider: ProviderId,
@ -193,6 +198,8 @@ pub async fn fetch_package_meta(
return Ok(out);
}
tracing::debug!(count = missing.len(), "fetching missing package metadata from provider");
let details = services
.packages
.get(provider)?

View file

@ -2,11 +2,13 @@ mod mrpack;
use std::path::Path;
pub use mrpack::{install_mrpack_to_cluster, MrpackInstaller};
use crate::state::LauncherServices;
use crate::LauncherResult;
#[tracing::instrument(level = "debug", skip(archive_path, services))]
pub async fn install_modpack_archive(
archive_path: impl AsRef<Path>,
cluster_id: i64,

View file

@ -41,11 +41,13 @@ struct MrpackHashes {
}
impl MrpackInstaller {
#[tracing::instrument(skip(services))]
pub async fn install_archive(
archive_path: PathBuf,
cluster_id: i64,
services: &LauncherServices,
) -> LauncherResult<()> {
tracing::info!("installing mrpack archive to cluster");
let cluster = PackageStore::get_cluster(cluster_id, services).await?;
let cluster_root = crate::paths::clusters_dir()?.join(&cluster.folder_name);
@ -131,13 +133,16 @@ impl MrpackInstaller {
.await?;
if failed > 0 {
tracing::error!(failed, total, "modpack install completed with failures");
return Err(PackageError::PartialModpackInstall { failed, total }.into());
}
tracing::info!(total, "modpack install complete");
Ok(())
}
}
#[tracing::instrument(level = "debug", skip(entry, cluster, services))]
async fn install_mrpack_file(
entry: MrpackFileEntry,
content_type: ContentType,
@ -208,6 +213,7 @@ fn io_err(err: impl std::error::Error + Send + Sync + 'static) -> polyio::IOErro
}
}
#[tracing::instrument(level = "debug", skip(services))]
pub async fn install_mrpack_to_cluster(
archive_path: PathBuf,
cluster_id: i64,

View file

@ -31,11 +31,13 @@ impl PackageProvider for CurseForgeProvider {
ProviderId::CurseForge
}
#[tracing::instrument(level = "debug", skip(self, filters, services))]
async fn search(
&self,
filters: &SearchFilters,
services: &LauncherServices,
) -> LauncherResult<Page<ProjectSummary>> {
tracing::debug!(query = ?filters.query, "searching curseforge");
let mut url = Url::parse(&api_url("/mods/search"))?;
{
@ -93,6 +95,7 @@ impl PackageProvider for CurseForgeProvider {
})
}
#[tracing::instrument(level = "debug", skip(self, services))]
async fn get_project(
&self,
project_id: &str,
@ -109,6 +112,7 @@ impl PackageProvider for CurseForgeProvider {
Ok(response.data.into_detail())
}
#[tracing::instrument(level = "debug", skip(self, project_ids, services))]
async fn get_projects(
&self,
project_ids: &[String],
@ -127,6 +131,7 @@ impl PackageProvider for CurseForgeProvider {
Ok(response.data.into_iter().map(CfMod::into_detail).collect())
}
#[tracing::instrument(level = "debug", skip(self, services))]
async fn list_versions(
&self,
project_id: &str,
@ -172,6 +177,7 @@ impl PackageProvider for CurseForgeProvider {
})
}
#[tracing::instrument(level = "debug", skip(self, services))]
async fn list_categories(
&self,
content_type: ContentType,
@ -197,6 +203,7 @@ impl PackageProvider for CurseForgeProvider {
Ok(response.data.into_iter().map(|c| c.name).collect())
}
#[tracing::instrument(level = "debug", skip(self, _project_id, services))]
async fn get_version(
&self,
_project_id: &str,
@ -214,6 +221,7 @@ impl PackageProvider for CurseForgeProvider {
Ok(response.data.into())
}
#[tracing::instrument(level = "debug", skip(self, version_ids, services))]
async fn get_versions(
&self,
version_ids: &[String],
@ -232,6 +240,7 @@ impl PackageProvider for CurseForgeProvider {
Ok(response.data.into_iter().map(Into::into).collect())
}
#[tracing::instrument(level = "debug", skip_all)]
async fn lookup_versions(
&self,
identities: &[FileIdentity],

View file

@ -5,6 +5,7 @@ use crate::http::{RequestClient, RequestError, ResponseNotifyOptions, ResponseOp
use crate::notification::GroupedProgressChild;
use crate::state::LauncherServices;
#[tracing::instrument(level = "debug", skip(client, url, body))]
pub async fn fetch_json<T: DeserializeOwned>(
client: &RequestClient,
method: Method,
@ -15,6 +16,7 @@ pub async fn fetch_json<T: DeserializeOwned>(
client.send_json(method, url, body, &[]).await
}
#[tracing::instrument(level = "debug", skip(client, url, body, headers))]
pub async fn fetch_json_with_headers<T: DeserializeOwned>(
client: &RequestClient,
method: Method,
@ -30,6 +32,7 @@ pub async fn fetch_json_with_headers<T: DeserializeOwned>(
client.send_json(method, url, body, &borrowed).await
}
#[tracing::instrument(level = "debug", skip(client, dest, child, services))]
pub async fn download_url(
client: &RequestClient,
url: &str,

View file

@ -43,11 +43,13 @@ impl PackageProvider for ModrinthProvider {
ProviderId::Modrinth
}
#[tracing::instrument(level = "debug", skip(self, filters, services))]
async fn search(
&self,
filters: &SearchFilters,
services: &LauncherServices,
) -> LauncherResult<Page<ProjectSummary>> {
tracing::debug!(query = ?filters.query, "searching modrinth");
let mut url = Url::parse(&v2("/search"))?;
{
let limit = filters
@ -152,6 +154,7 @@ impl PackageProvider for ModrinthProvider {
})
}
#[tracing::instrument(level = "debug", skip(self, services))]
async fn get_project(
&self,
project_id: &str,
@ -172,6 +175,7 @@ impl PackageProvider for ModrinthProvider {
Ok(detail)
}
#[tracing::instrument(level = "debug", skip(self, services))]
async fn list_categories(
&self,
content_type: ContentType,
@ -192,6 +196,7 @@ impl PackageProvider for ModrinthProvider {
.collect())
}
#[tracing::instrument(level = "debug", skip(self, project_ids, services))]
async fn get_projects(
&self,
project_ids: &[String],
@ -205,7 +210,7 @@ impl PackageProvider for ModrinthProvider {
.map(|id| format!("\"{id}\""))
.collect::<Vec<_>>()
.join(",");
let raw: Vec<ModrinthProject> = fetch_json(
&services.requester,
Method::GET,
@ -220,7 +225,7 @@ impl PackageProvider for ModrinthProvider {
.collect::<HashSet<_>>()
.into_iter()
.collect();
let mut members_by_team = fetch_modrinth_team_members(&services.requester, &team_ids)
.await
.unwrap_or_default();
@ -238,6 +243,7 @@ impl PackageProvider for ModrinthProvider {
.collect())
}
#[tracing::instrument(level = "debug", skip(self, services))]
async fn list_versions(
&self,
project_id: &str,
@ -276,6 +282,7 @@ impl PackageProvider for ModrinthProvider {
})
}
#[tracing::instrument(level = "debug", skip(self, _project_id, services))]
async fn get_version(
&self,
_project_id: &str,
@ -292,6 +299,7 @@ impl PackageProvider for ModrinthProvider {
Ok(raw.into())
}
#[tracing::instrument(level = "debug", skip(self, version_ids, services))]
async fn get_versions(
&self,
version_ids: &[String],
@ -315,6 +323,7 @@ impl PackageProvider for ModrinthProvider {
Ok(raw.into_iter().map(Into::into).collect())
}
#[tracing::instrument(level = "debug", skip_all)]
async fn lookup_versions(
&self,
identities: &[FileIdentity],
@ -355,6 +364,7 @@ impl PackageProvider for ModrinthProvider {
}
}
#[tracing::instrument(level = "debug", skip(client, team_ids))]
async fn fetch_modrinth_team_members(
client: &RequestClient,
team_ids: &[String],

View file

@ -1,6 +1,7 @@
use std::collections::HashMap;
use std::sync::Arc;
use super::{CurseForgeProvider, ModrinthProvider, PackageProvider};
use crate::LauncherResult;
use crate::packages::domain::ProviderId;
@ -51,6 +52,7 @@ impl PackageProviderRegistry {
.collect()
}
#[tracing::instrument(level = "debug", skip_all)]
pub async fn lookup_versions(
&self,
identities: &[FileIdentity],
@ -76,6 +78,7 @@ impl PackageProviderRegistry {
Ok(merged)
}
#[tracing::instrument(level = "debug", skip(self, sha1, services))]
pub async fn lookup_version(
&self,
sha1: impl AsRef<str>,
@ -96,6 +99,7 @@ impl PackageProviderRegistry {
Ok(None)
}
#[tracing::instrument(level = "debug", skip(self, services), fields(sha1 = %identity.sha1))]
pub async fn lookup_version_identity(
&self,
identity: &FileIdentity,
@ -123,6 +127,7 @@ impl Default for PackageProviderRegistry {
}
}
#[tracing::instrument(level = "debug", skip(identity, services), fields(sha1 = %identity.sha1))]
async fn enrich_curseforge_fingerprint(
identity: &mut FileIdentity,
services: &LauncherServices,

View file

@ -11,6 +11,7 @@ use crate::packages::provider::http::download_url;
use crate::packages::types::{ExternalFile, VersionDetail, VersionFile};
use crate::state::LauncherServices;
#[tracing::instrument(level = "debug", skip(child, services))]
pub async fn ensure_artifact_file(
hash: &str,
url: &str,
@ -28,6 +29,7 @@ pub async fn ensure_artifact_file(
tokio::fs::remove_file(dest).await?;
}
tracing::debug!("downloading artifact file");
download_url(&services.requester, url, dest, child, services).await?;
if let Some(child) = child {
@ -35,6 +37,7 @@ pub async fn ensure_artifact_file(
}
let actual = sha1_file(dest).await?;
if normalize_hash(&actual) != normalize_hash(hash) {
tracing::warn!(expected = %hash, %actual, "downloaded artifact hash mismatch");
return Err(PackageError::HashMismatch {
expected: hash.to_string(),
actual,
@ -46,6 +49,7 @@ pub async fn ensure_artifact_file(
}
#[allow(clippy::too_many_arguments)]
#[tracing::instrument(level = "debug", skip(version, file, child, services))]
pub async fn download_version_file(
provider: ProviderId,
project_id: &str,
@ -107,6 +111,7 @@ pub async fn download_version_file(
Ok(row)
}
#[tracing::instrument(level = "debug", skip(file, child, services), fields(name = %file.name))]
pub async fn download_external(
file: &ExternalFile,
force: bool,

View file

@ -9,6 +9,7 @@ use crate::packages::error::PackageError;
use crate::paths;
use crate::{LauncherError, LauncherResult};
#[tracing::instrument(level = "debug", skip(artifact, cluster))]
pub async fn link_artifact_to_cluster(
artifact: &ArtifactRow,
cluster: &ClusterRow,
@ -47,6 +48,7 @@ pub async fn link_artifact_to_cluster(
Ok(())
}
#[tracing::instrument(level = "debug")]
pub async fn link_or_copy(src: &Path, dest: &Path) -> LauncherResult<()> {
if dest.exists() {
polyio::remove_file(dest).await?;
@ -60,6 +62,7 @@ pub async fn link_or_copy(src: &Path, dest: &Path) -> LauncherResult<()> {
Ok(())
}
#[tracing::instrument(level = "debug", skip(cluster))]
pub async fn unlink_cluster_file(
cluster: &ClusterRow,
content_type: ContentType,

View file

@ -21,6 +21,7 @@ use std::path::Path;
pub struct PackageStore;
impl PackageStore {
#[tracing::instrument(level = "debug", skip(services))]
pub async fn get_cluster(
cluster_id: i64,
services: &LauncherServices,
@ -30,6 +31,7 @@ impl PackageStore {
.ok_or(PackageError::ClusterNotFound(cluster_id).into())
}
#[tracing::instrument(level = "debug", skip(services))]
pub async fn cached_artifact(
hash: &str,
services: &LauncherServices,
@ -41,6 +43,7 @@ impl PackageStore {
Ok(Some(row_to_cached(row, services).await?))
}
#[tracing::instrument(level = "debug", skip(project, version, child, services), fields(project_id = %project.id, version_id = %version.version_id))]
pub async fn download_and_cache(
provider_id: ProviderId,
project: &ProjectDetail,
@ -65,6 +68,7 @@ impl PackageStore {
}
#[allow(clippy::too_many_arguments)]
#[tracing::instrument(skip(project, version, child, services), fields(project_id = %project.id, version_id = %version.version_id))]
pub async fn install_to_cluster(
provider_id: ProviderId,
project: &ProjectDetail,
@ -75,6 +79,7 @@ impl PackageStore {
child: Option<&GroupedProgressChild>,
services: &LauncherServices,
) -> LauncherResult<ArtifactRow> {
tracing::info!("installing package to cluster");
let cluster = Self::get_cluster(cluster_id, services).await?;
if !skip_compatibility {
@ -95,6 +100,7 @@ impl PackageStore {
Ok(artifact)
}
#[tracing::instrument(level = "debug", skip(artifact, cluster, services))]
pub async fn link_artifact(
artifact: &ArtifactRow,
cluster: &ClusterRow,
@ -109,6 +115,7 @@ impl PackageStore {
Ok(())
}
#[tracing::instrument(level = "debug", skip(services))]
pub async fn link_by_hash(
hash: &str,
cluster_id: i64,
@ -124,6 +131,7 @@ impl PackageStore {
Self::link_artifact(&artifact, &cluster, cluster_file_name, services).await
}
#[tracing::instrument(level = "debug", skip(services))]
pub async fn unlink_from_cluster(
hash: &str,
cluster_id: i64,
@ -132,6 +140,7 @@ impl PackageStore {
crate::bundles::remove_artifact_from_cluster(cluster_id, hash, true, services).await
}
#[tracing::instrument(level = "debug", skip(services))]
pub async fn unlink_from_cluster_system(
hash: &str,
cluster_id: i64,
@ -140,6 +149,7 @@ impl PackageStore {
crate::bundles::remove_artifact_from_cluster(cluster_id, hash, false, services).await
}
#[tracing::instrument(level = "debug", skip(services))]
pub async fn list_linked_artifacts(
cluster_id: i64,
services: &LauncherServices,
@ -176,6 +186,7 @@ impl PackageStore {
Ok(items)
}
#[tracing::instrument(level = "debug", skip(services))]
pub async fn toggle_artifact_enabled(
cluster_id: i64,
hash: &str,
@ -228,6 +239,7 @@ impl PackageStore {
Ok(enabled)
}
#[tracing::instrument(level = "debug", skip(services))]
pub async fn import_local_file(
path: &Path,
content_type: ContentType,
@ -278,6 +290,7 @@ impl PackageStore {
Ok(row)
}
#[tracing::instrument(level = "debug", skip(services))]
pub async fn resolve_or_download(
provider_id: ProviderId,
project_id: &str,
@ -296,6 +309,7 @@ impl PackageStore {
}
}
#[tracing::instrument(level = "debug", skip(row, services), fields(hash = %row.hash))]
async fn row_to_cached(
row: ArtifactRow,
services: &LauncherServices,

View file

@ -6,7 +6,6 @@ use oneclient_db::dao::{
use oneclient_db::models::NewCluster;
use oneclient_db::DbPool;
use strum::IntoEnumIterator;
use tracing::instrument;
use crate::clusters::{ClusterManager, ClusterStage};
use crate::crypto::sha1_file;
@ -37,7 +36,7 @@ impl RecoveryReport {
}
}
#[instrument(skip(state))]
#[tracing::instrument(skip(state))]
pub async fn reconstruct_from_disk(state: &LauncherState) -> LauncherResult<RecoveryReport> {
let mut report = RecoveryReport::default();
@ -77,6 +76,7 @@ pub async fn reconstruct_from_disk(state: &LauncherState) -> LauncherResult<Reco
Ok(report)
}
#[tracing::instrument(level = "debug", skip(pool))]
async fn orphan_cluster_folders(
pool: &DbPool,
clusters_dir: &Path,
@ -90,6 +90,7 @@ async fn orphan_cluster_folders(
Ok(orphans)
}
#[tracing::instrument(level = "debug", skip(pool))]
async fn rebuild_artifact_cache(pool: &DbPool) -> LauncherResult<usize> {
let cache_root = paths::packages_cache_dir()?;
if !cache_root.exists() {
@ -143,6 +144,7 @@ async fn rebuild_artifact_cache(pool: &DbPool) -> LauncherResult<usize> {
}
#[allow(clippy::too_many_arguments)]
#[tracing::instrument(level = "debug", skip(pool, launcher_dir, file))]
async fn index_cache_file(
pool: &DbPool,
launcher_dir: &Path,
@ -189,6 +191,7 @@ async fn index_cache_file(
Ok(())
}
#[tracing::instrument(level = "debug", skip(state, report))]
async fn adopt_cluster(
state: &LauncherState,
folder_name: &str,
@ -226,6 +229,7 @@ async fn adopt_cluster(
Ok(())
}
#[tracing::instrument(level = "debug", skip(state, report))]
async fn relink_cluster_files(
state: &LauncherState,
cluster_id: i64,
@ -284,7 +288,7 @@ async fn relink_cluster_files(
Ok(())
}
#[instrument(skip(state))]
#[tracing::instrument(skip(state))]
pub async fn restore_bundle_tracking(state: &LauncherState) -> LauncherResult<()> {
let clusters = ClusterManager::list(state).await?;

View file

@ -44,6 +44,7 @@ fn ensure_in_clusters(path: &Path) -> LauncherResult<PathBuf> {
Err(ScreenshotsError::InvalidPath(path.display().to_string()).into())
}
#[tracing::instrument(level = "debug", skip(cluster), fields(cluster_id = cluster.id))]
pub fn list_cluster_screenshots(cluster: &Cluster) -> LauncherResult<Vec<ScreenshotInfo>> {
let dir = cluster.game_dir()?.join("screenshots");
let mut out = Vec::new();
@ -91,6 +92,7 @@ pub fn list_cluster_screenshots(cluster: &Cluster) -> LauncherResult<Vec<Screens
Ok(out)
}
#[tracing::instrument(level = "debug")]
pub fn load_screenshot(path: &Path, max_edge: Option<u32>) -> LauncherResult<Bytes> {
let path = ensure_in_clusters(path)?;
let raw = std::fs::read(&path).map_err(ScreenshotsError::Io)?;
@ -114,9 +116,10 @@ fn thumbnail(raw: &[u8], max_edge: u32) -> Option<Bytes> {
Some(Bytes::from(out))
}
#[tracing::instrument(level = "debug")]
pub fn delete_screenshot(path: &Path) -> LauncherResult<()> {
let path = ensure_in_clusters(path)?;
// TODO: maybe async?
match trash::delete(&path) {
Ok(()) => Ok(()),

View file

@ -1,6 +1,5 @@
use oneclient_db::DbPool;
use parking_lot::RwLock;
use tracing::instrument;
use crate::notification::NotificationService;
use crate::patch::Patch;
@ -10,7 +9,7 @@ use crate::{LauncherError, LauncherResult};
use super::launcher::LauncherSettings;
use super::profile::{GameSettingsProfile, Resolution, SettingsOsExtra};
#[instrument(skip(notify))]
#[tracing::instrument(level = "debug", skip(notify))]
pub async fn load_settings(notify: Option<&NotificationService>) -> LauncherSettings {
match async {
let path = paths::settings_file()?;
@ -38,7 +37,7 @@ pub async fn load_settings(notify: Option<&NotificationService>) -> LauncherSett
}
}
#[instrument(skip(settings))]
#[tracing::instrument(level = "debug", skip(settings))]
pub async fn save_settings(settings: &LauncherSettings) -> LauncherResult<()> {
let path = paths::settings_file()?;
@ -51,6 +50,7 @@ pub async fn save_settings(settings: &LauncherSettings) -> LauncherResult<()> {
Ok(())
}
#[tracing::instrument(level = "debug", skip(pool, settings))]
pub async fn get_profile_or_default(
pool: &DbPool,
settings: &LauncherSettings,
@ -65,6 +65,7 @@ pub async fn get_profile_or_default(
Ok(settings.global_game_settings.clone())
}
#[tracing::instrument(level = "debug", skip(pool, settings))]
pub async fn resolve_cluster_profile(
pool: &DbPool,
settings: &LauncherSettings,
@ -88,6 +89,7 @@ pub async fn resolve_cluster_profile(
Ok(profile)
}
#[tracing::instrument(level = "debug", skip_all)]
pub async fn upsert_named_profile(
pool: &DbPool,
profile: &GameSettingsProfile,
@ -103,6 +105,7 @@ pub async fn upsert_named_profile(
GameSettingsProfile::from_row(saved)
}
#[tracing::instrument(level = "debug", skip(pool, settings))]
pub async fn create_profile_from_global(
pool: &DbPool,
settings: &LauncherSettings,
@ -124,6 +127,7 @@ pub async fn create_profile_from_global(
upsert_named_profile(pool, &profile).await
}
#[tracing::instrument(level = "debug", skip(pool, settings))]
pub async fn create_settings_profile(
pool: &DbPool,
settings: &LauncherSettings,
@ -132,6 +136,7 @@ pub async fn create_settings_profile(
create_profile_from_global(pool, settings, name, None, None).await
}
#[tracing::instrument(level = "debug", skip(pool))]
pub async fn list_named_profiles(pool: &DbPool) -> LauncherResult<Vec<GameSettingsProfile>> {
let rows = oneclient_db::dao::setting_profile::list_all(pool).await?;
rows.into_iter()
@ -139,6 +144,7 @@ pub async fn list_named_profiles(pool: &DbPool) -> LauncherResult<Vec<GameSettin
.collect()
}
#[tracing::instrument(level = "debug", skip(pool))]
pub async fn delete_named_profile(pool: &DbPool, name: &str) -> LauncherResult<()> {
oneclient_db::dao::setting_profile::delete_by_name(pool, name).await?;
Ok(())
@ -178,6 +184,7 @@ impl ProfileUpdate {
}
}
#[tracing::instrument(level = "debug", skip(pool, update))]
pub async fn update_named_profile(
pool: &DbPool,
name: &str,
@ -195,6 +202,7 @@ pub async fn update_named_profile(
upsert_named_profile(pool, &profile).await
}
#[tracing::instrument(level = "debug", skip_all)]
pub async fn save_global_profile(
settings: &RwLock<LauncherSettings>,
global: GameSettingsProfile,

View file

@ -3,7 +3,6 @@ use std::sync::Arc;
use oneclient_db::DbPool;
use tokio::sync::{Mutex, OnceCell};
use tracing::instrument;
use crate::auth::{CredentialsStore, PendingBrowserLogin};
use crate::bundles::BundlesManager;
@ -42,7 +41,7 @@ pub struct LauncherState {
}
impl LauncherState {
#[instrument(skip(notifier))]
#[tracing::instrument(skip(notifier))]
pub async fn initialize(
notifier: NotificationService,
) -> LauncherResult<Arc<Self>> {

View file

@ -3,7 +3,6 @@ use std::path::Path;
use reqwest::header;
use reqwest::{Method, StatusCode};
use tokio::sync::RwLock;
use tracing::instrument;
use crate::api_config::meta_url_base;
use crate::paths;
@ -23,7 +22,7 @@ impl VersionsManager {
}
}
#[instrument(skip(self, services))]
#[tracing::instrument(level = "debug", skip(self, services))]
pub async fn sync(&self, services: &LauncherServices) -> LauncherResult<bool> {
let Some((manifest, changed)) = Self::fetch_manifest(services).await? else {
tracing::debug!("skipping versions sync; no remote or cached manifest available");
@ -37,6 +36,7 @@ impl VersionsManager {
self.manifest.read().await.metadata()
}
#[tracing::instrument(level = "debug", skip(services))]
async fn fetch_manifest(
services: &LauncherServices,
) -> LauncherResult<Option<(VersionsManifest, bool)>> {

View file

@ -2,14 +2,13 @@ use sqlx::SqlitePool;
use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions};
use std::path::Path;
use std::str::FromStr;
use tracing::instrument;
use crate::DbError;
pub type DbPool = SqlitePool;
#[instrument(
skip(database_path),
#[tracing::instrument(
skip(database_path),
fields(database_path = %database_path.as_ref().display())
)]
pub async fn connect(database_path: impl AsRef<Path>) -> Result<DbPool, DbError> {

View file

@ -5,12 +5,11 @@ use async_zip::StoredZipEntry;
use async_zip::base::read::WithoutEntry;
use futures_util::{Stream, TryStreamExt, pin_mut};
use tokio_util::compat::TokioAsyncWriteCompatExt;
use tracing::instrument;
use crate::{IOError, PolyIOResult};
/// Reads a zip archive from a byte array
#[instrument(skip(data, f), level = "debug")]
#[tracing::instrument(skip(data, f), level = "debug")]
pub async fn read_zip_entries_bytes<F>(data: Vec<u8>, mut f: F) -> PolyIOResult<()>
where
F: AsyncFnMut(
@ -40,7 +39,7 @@ where
}
/// Reads a zip archive from a byte array and returns a stream of entries.
#[instrument(skip(data), level = "debug")]
#[tracing::instrument(skip(data), level = "debug")]
pub fn stream_zip_entries_bytes(
data: Vec<u8>,
) -> impl Stream<
@ -66,7 +65,7 @@ pub fn stream_zip_entries_bytes(
}
/// Unzips a zip archive from a byte array
#[instrument(
#[tracing::instrument(
level = "debug",
skip(data, dest_path),
fields(
@ -81,7 +80,7 @@ pub async fn unzip_bytes(
}
/// Unzips a zip archive from a byte array
#[instrument(
#[tracing::instrument(
level = "debug",
skip(data, filter_entries, dest_path),
fields(
@ -128,7 +127,7 @@ pub async fn unzip_bytes_filtered(
Ok(())
}
#[instrument(
#[tracing::instrument(
level = "debug",
skip(zip_path, dest_path),
fields(
@ -150,7 +149,7 @@ pub async fn extract_zip(
}
/// Unzips a zip archive from a file
#[instrument(
#[tracing::instrument(
level = "debug",
skip(zip_path, dest_path, filter_entries, modify_entry_name),
fields(
@ -212,7 +211,7 @@ pub async fn extract_zip_filtered(
/// Returns `(entry_name, bytes)` pairs. Each matching entry is read fully into
/// memory, so this is meant for small files (e.g. bundle config overrides), not
/// large archives.
#[instrument(
#[tracing::instrument(
level = "debug",
skip(zip_path, filter),
fields(zip_path = %zip_path.as_ref().display())
@ -247,7 +246,7 @@ pub async fn read_zip_file_entries(
}
/// Returns a zip file entry's bytes without reading the entire file into memory.
#[instrument(
#[tracing::instrument(
level = "debug",
skip(reader)
)]
@ -278,7 +277,7 @@ where
Ok(data)
}
#[instrument(
#[tracing::instrument(
level = "debug",
skip(archive, dest),
fields(

View file

@ -2,12 +2,11 @@ use std::{fs::Metadata, path::PathBuf};
use async_tempfile::{TempDir, TempFile};
use serde::{Serialize, de::DeserializeOwned};
use tracing::instrument;
use crate::{IOError, PolyIOResult};
/// Returns a stream over the entries within a directory.
#[instrument(
#[tracing::instrument(
level = "debug",
skip(path),
fields(path = %path.as_ref().display())
@ -24,7 +23,7 @@ pub async fn read_dir(path: impl AsRef<std::path::Path>) -> PolyIOResult<tokio::
}
/// Creates a directory if they are missing.
#[instrument(
#[tracing::instrument(
level = "debug",
skip(path),
fields(path = %path.as_ref().display())
@ -44,7 +43,7 @@ pub async fn create_dir(path: impl AsRef<std::path::Path>) -> PolyIOResult<()> {
}
/// Recursively creates a directory and all of its parent components if they are missing.
#[instrument(
#[tracing::instrument(
level = "debug",
skip(path),
fields(path = %path.as_ref().display())
@ -60,7 +59,7 @@ pub async fn create_dir_all(path: impl AsRef<std::path::Path>) -> PolyIOResult<(
}
/// Removes a directory at this path, after removing all its contents. Use carefully!
#[instrument(
#[tracing::instrument(
level = "debug",
skip(path),
fields(path = %path.as_ref().display())
@ -77,7 +76,7 @@ pub async fn remove_dir_all(path: impl AsRef<std::path::Path>) -> PolyIOResult<(
}
/// Checks if a path exists
#[instrument(
#[tracing::instrument(
level = "debug",
skip(path),
fields(path = %path.as_ref().display())
@ -93,7 +92,7 @@ pub async fn try_exists(path: impl AsRef<std::path::Path>) -> PolyIOResult<bool>
}
/// Creates a future which will open a gzip compressed file for reading and read the entire contents into a string and return said string.
#[instrument(
#[tracing::instrument(
level = "debug",
skip(path),
fields(path = %path.as_ref().display())
@ -111,7 +110,7 @@ pub async fn read_gz_to_string(path: impl AsRef<std::path::Path>) -> PolyIOResul
}
/// Creates a future which will open a file for reading and read the entire contents into a string and return said string.
#[instrument(
#[tracing::instrument(
level = "debug",
skip(path),
fields(path = %path.as_ref().display())
@ -128,7 +127,7 @@ pub async fn read_to_string(path: impl AsRef<std::path::Path>) -> PolyIOResult<S
}
/// Asynchronously reads the entire contents of a file into a bytes vector.
#[instrument(
#[tracing::instrument(
level = "debug",
skip(path),
fields(path = %path.as_ref().display())
@ -145,7 +144,7 @@ pub async fn read(path: impl AsRef<std::path::Path>) -> PolyIOResult<Vec<u8>> {
}
/// Asynchronously read a file as JSON and return the deserialized object
#[instrument(
#[tracing::instrument(
level = "debug",
skip(path),
fields(path = %path.as_ref().display())
@ -161,7 +160,7 @@ pub async fn read_json<T: DeserializeOwned>(
}
/// Asynchrously write to a file.
#[instrument(
#[tracing::instrument(
level = "debug",
skip(path, data),
fields(path = %path.as_ref().display())
@ -181,7 +180,7 @@ pub async fn write(
}
/// Asynchronously write buffered data to a file, creating it if it does not exist.
#[instrument(
#[tracing::instrument(
level = "debug",
skip(path, f),
fields(path = %path.as_ref().display())
@ -206,7 +205,7 @@ where
Ok(())
}
#[instrument(
#[tracing::instrument(
level = "debug",
skip(path, stream),
fields(path = %path.as_ref().display())
@ -243,7 +242,7 @@ where
}
/// Asynchronously write json to a file, creating it if it does not exist.
#[instrument(
#[tracing::instrument(
level = "debug",
skip(path, data),
fields(path = %path.as_ref().display())
@ -261,7 +260,7 @@ pub async fn write_json<T: Serialize>(
}
/// Renames a file or directory to a new name, replacing the original file if `to` already exists.
#[instrument(
#[tracing::instrument(
level = "debug",
skip(from, to),
fields(
@ -285,7 +284,7 @@ pub async fn rename(
}
/// Copies the contents of one file to another. This function will also copy the permission bits of the original file to the destination file. This function will overwrite the contents of to.
#[instrument(
#[tracing::instrument(
level = "debug",
skip(from, to),
fields(
@ -309,7 +308,7 @@ pub async fn copy(
}
/// Removes a file from the filesystem.
#[instrument(
#[tracing::instrument(
level = "debug",
skip(path),
fields(path = %path.as_ref().display())
@ -328,7 +327,7 @@ pub async fn remove_file(path: impl AsRef<std::path::Path>) -> PolyIOResult<()>
///
/// Unlike [`stat`], if `path` is a symlink this returns metadata about the
/// link itself, not its target.
#[instrument(
#[tracing::instrument(
level = "debug",
skip(path),
fields(path = %path.as_ref().display())
@ -348,7 +347,7 @@ pub async fn symlink_metadata(path: impl AsRef<std::path::Path>) -> PolyIOResult
/// On Unix this creates a symlink. On Windows it creates a hard link
/// instead (both paths must then live on the same volume). Either way the
/// caller gets a file at `link` that shares the contents of `original`.
#[instrument(
#[tracing::instrument(
level = "debug",
skip(original, link),
fields(
@ -379,7 +378,7 @@ pub async fn symlink_file(
/// On Windows this creates a directory *junction* (a reparse point), which
/// needs no elevated privilege unlike a real directory symlink. On Unix it
/// creates an ordinary directory symlink. Remove it with [`remove_symlink_dir`].
#[instrument(
#[tracing::instrument(
level = "debug",
skip(original, link),
fields(
@ -422,7 +421,7 @@ pub async fn symlink_dir(
///
/// On Windows a junction must be removed with `remove_dir` rather than
/// `remove_file`; this handles the platform difference.
#[instrument(
#[tracing::instrument(
level = "debug",
skip(path),
fields(path = %path.as_ref().display())
@ -443,19 +442,19 @@ pub async fn remove_symlink_dir(path: impl AsRef<std::path::Path>) -> PolyIOResu
}
/// Creates a temporary directory.
#[instrument(level = "debug")]
#[tracing::instrument(level = "debug")]
pub async fn tempdir() -> PolyIOResult<TempDir> {
Ok(TempDir::new().await?)
}
/// Creates a temporary file.
#[instrument(level = "debug")]
#[tracing::instrument(level = "debug")]
pub async fn tempfile() -> PolyIOResult<TempFile> {
Ok(TempFile::new().await?)
}
/// Makes sure a path is a valid path
#[instrument(
#[tracing::instrument(
level = "debug",
skip(path),
fields(path = %path.as_ref().display())
@ -470,7 +469,7 @@ pub fn sanitize_path(path: impl AsRef<std::path::Path>) -> PathBuf {
}
/// Returns file metadata
#[instrument(
#[tracing::instrument(
level = "debug",
skip(path),
fields(path = %path.as_ref().display())