feat: add configurable log size and count options in settings
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
## v2.4.3
|
## v2.4.3
|
||||||
|
|
||||||
|
### ✨ 新增功能
|
||||||
|
|
||||||
|
- 支持前端修改日志(最大文件大小、最大保留数量)
|
||||||
|
|
||||||
### 🚀 优化改进
|
### 🚀 优化改进
|
||||||
|
|
||||||
- 重构并简化服务模式启动检测流程,消除重复检测
|
- 重构并简化服务模式启动检测流程,消除重复检测
|
||||||
|
|||||||
@@ -14,6 +14,12 @@ pub struct IVerge {
|
|||||||
/// silent | error | warn | info | debug | trace
|
/// silent | error | warn | info | debug | trace
|
||||||
pub app_log_level: Option<String>,
|
pub app_log_level: Option<String>,
|
||||||
|
|
||||||
|
/// app log max size in KB
|
||||||
|
pub app_log_max_size: Option<u64>,
|
||||||
|
|
||||||
|
/// app log max count
|
||||||
|
pub app_log_max_count: Option<usize>,
|
||||||
|
|
||||||
// i18n
|
// i18n
|
||||||
pub language: Option<String>,
|
pub language: Option<String>,
|
||||||
|
|
||||||
@@ -350,6 +356,8 @@ impl IVerge {
|
|||||||
|
|
||||||
pub fn template() -> Self {
|
pub fn template() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
app_log_max_size: Some(128),
|
||||||
|
app_log_max_count: Some(8),
|
||||||
clash_core: Some("verge-mihomo".into()),
|
clash_core: Some("verge-mihomo".into()),
|
||||||
language: Some(Self::get_system_language()),
|
language: Some(Self::get_system_language()),
|
||||||
theme_mode: Some("system".into()),
|
theme_mode: Some("system".into()),
|
||||||
@@ -426,6 +434,9 @@ impl IVerge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
patch!(app_log_level);
|
patch!(app_log_level);
|
||||||
|
patch!(app_log_max_size);
|
||||||
|
patch!(app_log_max_count);
|
||||||
|
|
||||||
patch!(language);
|
patch!(language);
|
||||||
patch!(theme_mode);
|
patch!(theme_mode);
|
||||||
patch!(tray_event);
|
patch!(tray_event);
|
||||||
@@ -524,6 +535,8 @@ impl IVerge {
|
|||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
pub struct IVergeResponse {
|
pub struct IVergeResponse {
|
||||||
pub app_log_level: Option<String>,
|
pub app_log_level: Option<String>,
|
||||||
|
pub app_log_max_size: Option<u64>,
|
||||||
|
pub app_log_max_count: Option<usize>,
|
||||||
pub language: Option<String>,
|
pub language: Option<String>,
|
||||||
pub theme_mode: Option<String>,
|
pub theme_mode: Option<String>,
|
||||||
pub tray_event: Option<String>,
|
pub tray_event: Option<String>,
|
||||||
@@ -595,6 +608,8 @@ impl From<IVerge> for IVergeResponse {
|
|||||||
let valid_clash_core = verge.get_valid_clash_core();
|
let valid_clash_core = verge.get_valid_clash_core();
|
||||||
Self {
|
Self {
|
||||||
app_log_level: verge.app_log_level,
|
app_log_level: verge.app_log_level,
|
||||||
|
app_log_max_size: verge.app_log_max_size,
|
||||||
|
app_log_max_count: verge.app_log_max_count,
|
||||||
language: verge.language,
|
language: verge.language,
|
||||||
theme_mode: verge.theme_mode,
|
theme_mode: verge.theme_mode,
|
||||||
tray_event: verge.tray_event,
|
tray_event: verge.tray_event,
|
||||||
|
|||||||
@@ -22,7 +22,16 @@ use tokio::fs::DirEntry;
|
|||||||
/// initialize this instance's log file
|
/// initialize this instance's log file
|
||||||
#[cfg(not(feature = "tauri-dev"))]
|
#[cfg(not(feature = "tauri-dev"))]
|
||||||
pub async fn init_logger() -> Result<()> {
|
pub async fn init_logger() -> Result<()> {
|
||||||
let log_level = Config::verge().await.latest_ref().get_log_level();
|
// TODO 提供 runtime 级别实时修改
|
||||||
|
let (log_level, log_max_size, log_max_count) = {
|
||||||
|
let verge_guard = Config::verge().await;
|
||||||
|
let verge = verge_guard.latest_ref();
|
||||||
|
(
|
||||||
|
verge.get_log_level(),
|
||||||
|
verge.app_log_max_size.unwrap_or(128),
|
||||||
|
verge.app_log_max_count.unwrap_or(8),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
let log_dir = dirs::app_logs_dir()?;
|
let log_dir = dirs::app_logs_dir()?;
|
||||||
let logger = Logger::with(LogSpecification::from(log_level))
|
let logger = Logger::with(LogSpecification::from(log_level))
|
||||||
@@ -31,14 +40,12 @@ pub async fn init_logger() -> Result<()> {
|
|||||||
.format(console_colored_format)
|
.format(console_colored_format)
|
||||||
.format_for_files(file_format)
|
.format_for_files(file_format)
|
||||||
.rotate(
|
.rotate(
|
||||||
// ? 总是保持单个日志最大 10 MB
|
Criterion::Size(log_max_size * 1024),
|
||||||
Criterion::Size(10 * 1024 * 1024),
|
|
||||||
flexi_logger::Naming::TimestampsCustomFormat {
|
flexi_logger::Naming::TimestampsCustomFormat {
|
||||||
current_infix: Some("latest"),
|
current_infix: Some("latest"),
|
||||||
format: "%Y-%m-%d_%H-%M-%S",
|
format: "%Y-%m-%d_%H-%M-%S",
|
||||||
},
|
},
|
||||||
// TODO 提供前端设置最大保留文件数量
|
Cleanup::KeepLogFiles(log_max_count),
|
||||||
Cleanup::Never,
|
|
||||||
)
|
)
|
||||||
.filter(Box::new(NoExternModule));
|
.filter(Box::new(NoExternModule));
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [values, setValues] = useState({
|
const [values, setValues] = useState({
|
||||||
appLogLevel: "warn",
|
appLogLevel: "warn",
|
||||||
|
appLogMaxSize: 8,
|
||||||
|
appLogMaxCount: 12,
|
||||||
autoCloseConnection: true,
|
autoCloseConnection: true,
|
||||||
autoCheckUpdate: true,
|
autoCheckUpdate: true,
|
||||||
enableBuiltinEnhanced: true,
|
enableBuiltinEnhanced: true,
|
||||||
@@ -37,6 +39,8 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
setOpen(true);
|
setOpen(true);
|
||||||
setValues({
|
setValues({
|
||||||
appLogLevel: verge?.app_log_level ?? "warn",
|
appLogLevel: verge?.app_log_level ?? "warn",
|
||||||
|
appLogMaxSize: verge?.app_log_max_size ?? 128,
|
||||||
|
appLogMaxCount: verge?.app_log_max_count ?? 8,
|
||||||
autoCloseConnection: verge?.auto_close_connection ?? true,
|
autoCloseConnection: verge?.auto_close_connection ?? true,
|
||||||
autoCheckUpdate: verge?.auto_check_update ?? true,
|
autoCheckUpdate: verge?.auto_check_update ?? true,
|
||||||
enableBuiltinEnhanced: verge?.enable_builtin_enhanced ?? true,
|
enableBuiltinEnhanced: verge?.enable_builtin_enhanced ?? true,
|
||||||
@@ -100,6 +104,66 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
</Select>
|
</Select>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
|
<ListItem sx={{ padding: "5px 2px" }}>
|
||||||
|
<ListItemText
|
||||||
|
primary={t("App Log Max Size")}
|
||||||
|
sx={{ maxWidth: "fit-content" }}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
autoComplete="new-password"
|
||||||
|
size="small"
|
||||||
|
type="number"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
|
sx={{ width: 140, marginLeft: "auto" }}
|
||||||
|
value={values.appLogMaxSize}
|
||||||
|
onChange={(e) =>
|
||||||
|
setValues((v) => ({
|
||||||
|
...v,
|
||||||
|
appLogMaxSize: Math.max(1, parseInt(e.target.value) || 128),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
slotProps={{
|
||||||
|
input: {
|
||||||
|
endAdornment: (
|
||||||
|
<InputAdornment position="end">{t("KB")}</InputAdornment>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
|
||||||
|
<ListItem sx={{ padding: "5px 2px" }}>
|
||||||
|
<ListItemText
|
||||||
|
primary={t("App Log Max Count")}
|
||||||
|
sx={{ maxWidth: "fit-content" }}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
autoComplete="new-password"
|
||||||
|
size="small"
|
||||||
|
type="number"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
|
sx={{ width: 140, marginLeft: "auto" }}
|
||||||
|
value={values.appLogMaxCount}
|
||||||
|
onChange={(e) =>
|
||||||
|
setValues((v) => ({
|
||||||
|
...v,
|
||||||
|
appLogMaxCount: Math.max(1, parseInt(e.target.value) || 1),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
slotProps={{
|
||||||
|
input: {
|
||||||
|
endAdornment: (
|
||||||
|
<InputAdornment position="end">{t("Files")}</InputAdornment>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
|
||||||
<ListItem sx={{ padding: "5px 2px" }}>
|
<ListItem sx={{ padding: "5px 2px" }}>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
primary={t("Auto Close Connections")}
|
primary={t("Auto Close Connections")}
|
||||||
@@ -153,7 +217,7 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
<ListItemText primary={t("Proxy Layout Columns")} />
|
<ListItemText primary={t("Proxy Layout Columns")} />
|
||||||
<Select
|
<Select
|
||||||
size="small"
|
size="small"
|
||||||
sx={{ width: 135, "> div": { py: "7.5px" } }}
|
sx={{ width: 160, "> div": { py: "7.5px" } }}
|
||||||
value={values.proxyLayoutColumn}
|
value={values.proxyLayoutColumn}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setValues((v) => ({
|
setValues((v) => ({
|
||||||
@@ -177,7 +241,7 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
<ListItemText primary={t("Auto Log Clean")} />
|
<ListItemText primary={t("Auto Log Clean")} />
|
||||||
<Select
|
<Select
|
||||||
size="small"
|
size="small"
|
||||||
sx={{ width: 135, "> div": { py: "7.5px" } }}
|
sx={{ width: 160, "> div": { py: "7.5px" } }}
|
||||||
value={values.autoLogClean}
|
value={values.autoLogClean}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setValues((v) => ({
|
setValues((v) => ({
|
||||||
|
|||||||
2
src/services/types.d.ts
vendored
2
src/services/types.d.ts
vendored
@@ -778,6 +778,8 @@ interface IProxyConfig
|
|||||||
|
|
||||||
interface IVergeConfig {
|
interface IVergeConfig {
|
||||||
app_log_level?: "trace" | "debug" | "info" | "warn" | "error" | string;
|
app_log_level?: "trace" | "debug" | "info" | "warn" | "error" | string;
|
||||||
|
app_log_max_size?: number; // KB
|
||||||
|
app_log_max_count?: number;
|
||||||
language?: string;
|
language?: string;
|
||||||
tray_event?:
|
tray_event?:
|
||||||
| "main_window"
|
| "main_window"
|
||||||
|
|||||||
Reference in New Issue
Block a user