在 MiGu 侧落地日志定时清理与磁盘空间告警。
系统配置可开关清理策略;日志管理页支持查看/保存清理选项。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -7,7 +7,7 @@ namespace MiGu.Server.Configs;
|
||||
/// <summary>
|
||||
/// 配置中心存储(内存 + JSON 文件持久化占位)。
|
||||
/// 前 14 个 section 对应 ARCHITECTURE.md §9 的 13+1 维度;外加 deployment —— 登录后「配置向导」的部署画像。
|
||||
/// 真实落地时由 SimpleShared.Persistence 接入 EF Core,并配合 YARP 下发至 SimpleLite。
|
||||
/// 真实落地时由 SimpleShared.Persistence 接入 EF Core,并配合 YARP 下发至 Simple3。
|
||||
/// </summary>
|
||||
public sealed class ConfigStore
|
||||
{
|
||||
@@ -99,6 +99,58 @@ public sealed class ConfigStore
|
||||
return Put("deployment", el);
|
||||
}
|
||||
|
||||
public LogCleanupOptions GetLogCleanup()
|
||||
{
|
||||
var env = Get("system");
|
||||
return env.Payload switch
|
||||
{
|
||||
SystemConfig sc => (sc.LogCleanup ?? new LogCleanupOptions()).Clamp(),
|
||||
JsonElement el => ParseLogCleanup(el),
|
||||
_ => LogCleanupOptions.CreateDefaults()
|
||||
};
|
||||
}
|
||||
|
||||
public Envelope PutLogCleanup(LogCleanupOptions options)
|
||||
{
|
||||
var opt = (options ?? new LogCleanupOptions()).Clamp();
|
||||
Dictionary<string, JsonElement> dict;
|
||||
try
|
||||
{
|
||||
var current = Get("system").Payload;
|
||||
var el = current is JsonElement je
|
||||
? je
|
||||
: JsonSerializer.SerializeToElement(current, _jsonOpts);
|
||||
dict = el.ValueKind == JsonValueKind.Object
|
||||
? JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(el.GetRawText()) ?? new()
|
||||
: new Dictionary<string, JsonElement>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "读取 system 配置失败,按空对象合并 logCleanup");
|
||||
dict = new Dictionary<string, JsonElement>();
|
||||
}
|
||||
|
||||
dict["logCleanup"] = JsonSerializer.SerializeToElement(opt, _jsonOpts);
|
||||
var merged = JsonSerializer.SerializeToElement(dict, _jsonOpts);
|
||||
return Put("system", merged);
|
||||
}
|
||||
|
||||
private LogCleanupOptions ParseLogCleanup(JsonElement el)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (el.ValueKind == JsonValueKind.Object && el.TryGetProperty("logCleanup", out var nested))
|
||||
return (nested.Deserialize<LogCleanupOptions>(_jsonOpts) ?? new LogCleanupOptions()).Clamp();
|
||||
var sc = el.Deserialize<SystemConfig>(_jsonOpts);
|
||||
return (sc?.LogCleanup ?? new LogCleanupOptions()).Clamp();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "反序列化 logCleanup 失败,回退默认值");
|
||||
return LogCleanupOptions.CreateDefaults();
|
||||
}
|
||||
}
|
||||
|
||||
private DeploymentProfile SafeDeserializeDeployment(JsonElement el)
|
||||
{
|
||||
try { return el.Deserialize<DeploymentProfile>(_jsonOpts) ?? DeploymentProfile.Default(); }
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
namespace MiGu.Server.Configs;
|
||||
|
||||
/// <summary>
|
||||
/// 日志清理与磁盘告警(system.logCleanup)。字段对齐 Simple3 <c>LogCleanupOptions</c>。
|
||||
/// </summary>
|
||||
public sealed class LogCleanupOptions
|
||||
{
|
||||
/// <summary>是否启用后台自动清理。关闭后仅「立即清理」可手动触发。默认 true。</summary>
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
/// <summary>保留天数:删除 log/ 下 LastWriteTime 早于「现在 − N 天」的 *.log。默认 30,最小 1。</summary>
|
||||
public int RetentionDays { get; set; } = 30;
|
||||
|
||||
/// <summary>后台清理间隔(小时)。默认 24;<= 0 归一为 1。</summary>
|
||||
public int CheckIntervalHours { get; set; } = 24;
|
||||
|
||||
/// <summary>启动时先执行一次清理。默认 true。</summary>
|
||||
public bool RunOnStartup { get; set; } = true;
|
||||
|
||||
/// <summary>是否启用磁盘剩余空间不足告警。默认 true。</summary>
|
||||
public bool DiskAlertEnabled { get; set; } = true;
|
||||
|
||||
/// <summary>日志所在盘剩余低于该值(GB)时告警。默认 5。</summary>
|
||||
public double DiskFreeAlertGB { get; set; } = 5;
|
||||
|
||||
/// <summary>磁盘检测间隔(分钟)。默认 30;<= 0 归一为 30。</summary>
|
||||
public int DiskCheckIntervalMinutes { get; set; } = 30;
|
||||
|
||||
public static LogCleanupOptions CreateDefaults() => new();
|
||||
|
||||
public LogCleanupOptions Clamp()
|
||||
{
|
||||
RetentionDays = Math.Clamp(RetentionDays, 1, 3650);
|
||||
CheckIntervalHours = Math.Max(1, CheckIntervalHours);
|
||||
if (DiskFreeAlertGB <= 0) DiskFreeAlertGB = 5;
|
||||
DiskCheckIntervalMinutes = DiskCheckIntervalMinutes <= 0 ? 30 : DiskCheckIntervalMinutes;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,8 @@
|
||||
namespace MiGu.Server.Configs;
|
||||
|
||||
public record LogPolicy(string Level, int RollDays, int MaxSizeMB);
|
||||
public record SecurityPolicy(int JwtExpireMin, bool EnableSwagger, List<string> CorsWhitelist);
|
||||
|
||||
public record SystemConfig(int DispatchLoopHz, LogPolicy Log, SecurityPolicy Security)
|
||||
public record SystemConfig
|
||||
{
|
||||
public static SystemConfig Default() => new(
|
||||
DispatchLoopHz: 50,
|
||||
Log: new LogPolicy("info", 7, 256),
|
||||
Security: new SecurityPolicy(1440, false, new List<string> { "http://localhost:5173" }));
|
||||
public LogCleanupOptions LogCleanup { get; init; } = new();
|
||||
|
||||
public static SystemConfig Default() => new();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user