using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using SmartScanner.ViewModel;
namespace SmartScanner
{
///
/// 优化的日志自动保存服务
/// 功能:批量保存48小时内每一条日志到D盘02 LBLog文件夹
/// 触发条件:最多300条或十分钟批量保存一次
///
public class LogAutoSaveService
{
private readonly ObservableCollection _logEntries;
private Timer _cleanupTimer;
private Timer _batchSaveTimer;
private const int CLEANUP_INTERVAL_MS = 60 * 60 * 1000; // 1小时清理一次
private const int BATCH_SAVE_INTERVAL_MS = 600000; // 十分钟批量保存一次
private const int MAX_BATCH_SIZE = 300; // 最多300条日志批量保存
private readonly string _logDirectory = @"D:\02 LBLog";
private bool _isSaving = false;
private readonly object _fileLock = new object();
private readonly object _bufferLock = new object();
private string _currentLogFilePath;
private readonly Queue _logBuffer = new Queue(); // 日志缓冲区
private int _bufferCount = 0; // 缓冲区计数
public LogAutoSaveService(ObservableCollection logEntries)
{
_logEntries = logEntries ?? throw new ArgumentNullException(nameof(logEntries));
// 创建日志目录
if (!Directory.Exists(_logDirectory))
{
Directory.CreateDirectory(_logDirectory);
}
// 初始化当前日志文件路径
InitializeCurrentLogFile();
// 启动批量保存定时器
_batchSaveTimer = new Timer(OnBatchSaveTimerElapsed, null, BATCH_SAVE_INTERVAL_MS, BATCH_SAVE_INTERVAL_MS);
// 启动清理定时器
_cleanupTimer = new Timer(OnCleanupTimerElapsed, null, CLEANUP_INTERVAL_MS, CLEANUP_INTERVAL_MS);
}
///
/// 初始化当前日志文件路径
///
private void InitializeCurrentLogFile()
{
string currentDate = DateTime.Now.ToString("yyyyMMdd");
string fileName = $"Log_{currentDate}.txt";
_currentLogFilePath = Path.Combine(_logDirectory, fileName);
}
///
/// 添加日志到缓冲区,延迟批量保存
///
public void LogAdded(LogEntry logEntry)
{
if (_isSaving) return;
lock (_bufferLock)
{
_logBuffer.Enqueue(logEntry);
_bufferCount++;
// 如果缓冲区达到最大大小,立即触发保存
if (_bufferCount >= MAX_BATCH_SIZE)
{
Task.Run(() => SaveBatchAsync());
}
}
}
///
/// 批量保存定时器回调
///
private void OnBatchSaveTimerElapsed(object state)
{
if (!_isSaving && _bufferCount > 0)
{
Task.Run(() => SaveBatchAsync());
}
}
///
/// 异步批量保存日志
///
private async Task SaveBatchAsync()
{
if (_isSaving) return;
_isSaving = true;
try
{
// 检查是否需要切换到新文件
await CheckAndSwitchLogFileAsync();
// 获取缓冲区中的所有日志
List batchToSave;
lock (_bufferLock)
{
if (_bufferCount == 0)
{
_isSaving = false;
return;
}
batchToSave = new List(_logBuffer);
_logBuffer.Clear();
_bufferCount = 0;
}
// 批量保存到文件
await SaveBatchToFileAsync(batchToSave);
Console.WriteLine($"批量保存了 {batchToSave.Count} 条日志到文件");
}
catch (Exception ex)
{
Console.WriteLine($"批量保存失败: {ex.Message}");
}
finally
{
_isSaving = false;
}
}
///
/// 批量保存日志到文件
///
private async Task SaveBatchToFileAsync(List batch)
{
await Task.Run(() =>
{
lock (_fileLock)
{
try
{
using (StreamWriter writer = new StreamWriter(_currentLogFilePath, true, Encoding.UTF8))
{
foreach (var entry in batch)
{
string logLine = $"[{entry.Timestamp:yyyy-MM-dd HH:mm:ss.fff}] [{entry.Level}] {entry.Message}";
writer.WriteLine(logLine);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"批量保存到文件失败: {ex.Message}");
}
}
});
}
///
/// 检查是否需要切换到新的日志文件
///
private async Task CheckAndSwitchLogFileAsync()
{
await Task.Run(() =>
{
string currentDate = DateTime.Now.ToString("yyyyMMdd");
string fileName = $"Log_{currentDate}.txt";
string newFilePath = Path.Combine(_logDirectory, fileName);
// 如果日期变化,切换到新文件
if (_currentLogFilePath != newFilePath)
{
_currentLogFilePath = newFilePath;
}
});
}
private void OnCleanupTimerElapsed(object state)
{
// 清理超过48小时的日志文件
if (!_isSaving)
{
Task.Run(() => CleanupOldLogFilesAsync());
}
}
///
/// 清理超过48小时的日志文件
///
private async Task CleanupOldLogFilesAsync()
{
await Task.Run(() =>
{
try
{
if (Directory.Exists(_logDirectory))
{
var files = Directory.GetFiles(_logDirectory, "Log_*.txt");
DateTime cutoffTime = DateTime.Now.AddHours(-48);
foreach (string file in files)
{
try
{
FileInfo fileInfo = new FileInfo(file);
if (fileInfo.LastWriteTime < cutoffTime)
{
File.Delete(file);
Console.WriteLine($"清理过期日志文件: {file}");
}
}
catch (Exception ex)
{
Console.WriteLine($"清理文件失败 {file}: {ex.Message}");
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"清理过期日志文件失败: {ex.Message}");
}
});
}
///
/// 手动保存当前所有日志
///
public void ForceSave()
{
if (!_isSaving)
{
Task.Run(() => SaveBatchAsync());
}
}
///
/// 停止服务
///
public void Stop()
{
_batchSaveTimer?.Dispose();
_batchSaveTimer = null;
_cleanupTimer?.Dispose();
_cleanupTimer = null;
// 保存最后的日志
if (!_isSaving && _bufferCount > 0)
{
ForceSave();
}
}
///
/// 获取保存统计信息
///
public string GetStatus()
{
try
{
string currentFileInfo = "";
if (File.Exists(_currentLogFilePath))
{
FileInfo fileInfo = new FileInfo(_currentLogFilePath);
currentFileInfo = $", 当前文件大小: {fileInfo.Length / 1024} KB";
}
return $"自动保存服务运行中 - 缓冲区: {_bufferCount} 条{currentFileInfo}";
}
catch
{
return $"自动保存服务运行中 - 缓冲区: {_bufferCount} 条";
}
}
}
}