Implement logging utilities and log file path management

This commit is contained in:
2026-05-07 11:16:11 +02:00
parent 3e929eabe0
commit 54c6521875

View File

@@ -3,11 +3,12 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::Value; use serde_json::Value;
use std::fs::{self, File}; use std::fs::{self, File};
use std::io::{BufRead, BufReader, Read, Seek, SeekFrom}; use std::io::{BufRead, BufReader, Read, Seek, SeekFrom, Write};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::{SystemTime, UNIX_EPOCH};
use tauri::{async_runtime, Env, State, Window}; use tauri::{async_runtime, Env, State, Window};
#[derive(Default, Clone)] #[derive(Default, Clone)]
@@ -28,6 +29,7 @@ struct MapInfo {
#[derive(Serialize)] #[derive(Serialize)]
struct GenerateResult { struct GenerateResult {
output_path: String, output_path: String,
log_path: String,
} }
#[derive(Debug, Deserialize, Default)] #[derive(Debug, Deserialize, Default)]
@@ -62,6 +64,13 @@ fn output_dir(root: &Path) -> Result<PathBuf, String> {
Ok(dir) Ok(dir)
} }
fn logs_dir(root: &Path) -> Result<PathBuf, String> {
let mut dir = root.to_path_buf();
dir.push("logs");
fs::create_dir_all(&dir).map_err(|e| format!("Failed to create logs dir: {e}"))?;
Ok(dir)
}
fn script_path(root: &Path) -> Result<PathBuf, String> { fn script_path(root: &Path) -> Result<PathBuf, String> {
let candidate = root.join("generate_equirect.py"); let candidate = root.join("generate_equirect.py");
if candidate.exists() { if candidate.exists() {
@@ -79,6 +88,67 @@ fn python_binary(root: &Path) -> PathBuf {
PathBuf::from("python3") PathBuf::from("python3")
} }
fn unix_timestamp_millis() -> u128 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|duration| duration.as_millis())
.unwrap_or(0)
}
fn log_slug(prompt: &str) -> String {
let mut slug = String::new();
let mut last_was_separator = false;
for ch in prompt.chars().flat_map(char::to_lowercase) {
if ch.is_ascii_alphanumeric() {
slug.push(ch);
last_was_separator = false;
} else if !last_was_separator && !slug.is_empty() {
slug.push('_');
last_was_separator = true;
}
if slug.len() >= 64 {
break;
}
}
while slug.ends_with('_') {
slug.pop();
}
if slug.is_empty() {
"generation".to_string()
} else {
slug
}
}
fn generation_log_path(root: &Path, prompt: &str) -> Result<PathBuf, String> {
let dir = logs_dir(root)?;
let timestamp = unix_timestamp_millis();
let slug = log_slug(prompt);
let mut index = 0;
loop {
let filename = if index == 0 {
format!("{timestamp}-{slug}.log")
} else {
format!("{timestamp}-{slug}-{index}.log")
};
let path = dir.join(filename);
if !path.exists() {
return Ok(path);
}
index += 1;
}
}
fn write_log_line(log_file: &mut File, line: impl AsRef<str>) {
let _ = writeln!(log_file, "{}", line.as_ref());
let _ = log_file.flush();
}
fn decode_latin1(bytes: &[u8]) -> String { fn decode_latin1(bytes: &[u8]) -> String {
bytes.iter().map(|&byte| byte as char).collect() bytes.iter().map(|&byte| byte as char).collect()
} }