Files
LL-28/SLC1-N/mxlLog.cs
moxiliang 7065cad6d7 251024
2025-10-24 14:08:41 +08:00

279 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Threading;
using SLC1_N;
namespace SLC1_N
{
public class mxlLog // 日志文件类
{
// 日志级别
public enum LogLevel
{
LOG_DEBUG,
LOG_INFO,
LOG_WARNING,
LOG_ERROR,
LOG_XXX
};
// 单例实例
private static readonly mxlLog instance = new mxlLog();
public static mxlLog Instance { get { return instance; } }
private readonly object mutex = new object();
private string logDir;
private string logPrefix = "log_";
private long maxFileSize = 10 * 1024 * 1024; // 10MB
private int maxBackupFiles = 5; // 允许文件最大备份数
private LogLevel minLevel = LogLevel.LOG_DEBUG; // 记录级别,大于则生成文件
// 标志位控制
public bool IsDebugEnabled { get; set; } = false;
public bool IsInfoEnabled { get; set; } = false;
public bool IsWarningEnabled { get; set; } = false;
public bool IsErrorEnabled { get; set; } = false;
public bool IsXXXEnabled { get; set; } = false;
// 构造函数 - 自动初始化到当前目录
private mxlLog()
{
// 自动设置为软件当前目录下的Logs文件夹
logDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
minLevel = LogLevel.LOG_DEBUG;
// 确保日志目录存在
if (!Directory.Exists(logDir))
{
Directory.CreateDirectory(logDir);
}
}
// 初始化
public void Initialize(string dir = null, // 修改日志目录
string prefix = null, // 修改日志文件名前缀
long? maxSize = null, // 限制单个日志文件最大
int? maxBackups = null,// 最多保留备份数
LogLevel? minLevel = null, // 只写入xxx及以上级别
bool? isDebugEnabled = null, bool? isInfoEnabled = null, // 写入使能
bool? isWarningEnabled = null, bool? isErrorEnabled = null,
bool? isXXXEnabled = null)
{
lock (mutex)
{
this.logDir = dir ?? this.logDir;
this.logPrefix = prefix ?? this.logPrefix;
this.maxFileSize = maxSize ?? this.maxFileSize;
this.maxBackupFiles = maxBackups ?? this.maxBackupFiles;
this.minLevel = minLevel ?? this.minLevel;
// 设置标志位
IsDebugEnabled = isDebugEnabled ?? IsDebugEnabled;
IsInfoEnabled = isInfoEnabled ?? IsInfoEnabled;
IsWarningEnabled = isWarningEnabled ?? IsWarningEnabled;
IsErrorEnabled = isErrorEnabled ?? IsErrorEnabled;
IsXXXEnabled = isXXXEnabled ?? IsXXXEnabled;
if (!Directory.Exists(logDir))
{
Directory.CreateDirectory(logDir);
}
}
}
// 写入日志
public void Write(LogLevel level, string message, Exception ex = null)
{
if (!IsLevelEnabled(level) || level < minLevel) // 检查使能
return;
lock (mutex)
{
try
{
string logFile = GetCurrentLogFilePath();
CheckFileSize(logFile);
string logEntry = $"{GetCurrentTimeStamp()} [{GetLevelString(level)}] {message}";
if (ex != null)
{
logEntry += $"\nException: {ex.GetType().Name}\nMessage: {ex.Message}\nStack Trace: {ex.StackTrace}";
}
File.AppendAllText(logFile, logEntry + Environment.NewLine);
}
catch (Exception logEx)
{
HandleLogFailure(logEx);
}
}
}
// 清理旧日志文件
public void ClearOldLogs(int keepDays = 30)
{
try
{
lock (mutex)
{
if (!Directory.Exists(logDir))
return;
var cutoffDate = DateTime.Now.AddDays(-keepDays); // 截止日期
var allLogFiles = Directory.GetFiles(logDir, $"{logPrefix}*.log*"); // 筛选
foreach (var file in allLogFiles)
{
try
{
// 尝试从文件名中解析日期
var fileName = Path.GetFileNameWithoutExtension(file);
if (fileName.StartsWith(logPrefix))
{
var datePart = fileName.Substring(logPrefix.Length); //去掉前缀,获取日期部分
// 尝试解析日期 yyyyMMdd
if (datePart.Length >= 8 && // 日期是否8个字符("20250101") 则存到fileDate
DateTime.TryParseExact(datePart.Substring(0, 8), "yyyyMMdd", null, System.Globalization.DateTimeStyles.None, out var fileDate))
{
if (fileDate < cutoffDate) // 对比日期
{
File.Delete(file);
Write(LogLevel.LOG_INFO, $"删除旧日志文件: {file}");
}
}
else if (File.Exists(file)) // 对于log.1, .log.2,检查最后修改时间
{
var lastWriteTime = File.GetLastWriteTime(file);
if (lastWriteTime < cutoffDate)
{
File.Delete(file);
Write(LogLevel.LOG_INFO, $"删除旧日志备份: {file}");
}
}
}
}
catch (Exception ex)
{
Write(LogLevel.LOG_ERROR, $"删除旧日志文件失败: {file}", ex);
}
}
}
}
catch (Exception ex)
{
Write(LogLevel.LOG_ERROR, "清除旧日志失败", ex);
}
}
// 快捷方法
public void Debug(string message) => Write(LogLevel.LOG_DEBUG, message);
public void Info(string message) => Write(LogLevel.LOG_INFO, message);
public void Warning(string message, Exception ex = null) => Write(LogLevel.LOG_WARNING, message, ex);
public void Error(string message, Exception ex = null) => Write(LogLevel.LOG_ERROR, message, ex);
public void XXX(string message, Exception ex = null) => Write(LogLevel.LOG_XXX, message, ex);
public void MESDebug(string message) => Write(LogLevel.LOG_DEBUG, $"[MES] {message}");
#region
// 获取使能
private bool IsLevelEnabled(LogLevel level)
{
switch (level)
{
case LogLevel.LOG_DEBUG: return IsDebugEnabled;
case LogLevel.LOG_INFO: return IsInfoEnabled;
case LogLevel.LOG_WARNING: return IsWarningEnabled;
case LogLevel.LOG_ERROR: return IsErrorEnabled;
case LogLevel.LOG_XXX: return IsXXXEnabled;
default: return true;
}
}
// 生成当前日志文件的完整路径
private string GetCurrentLogFilePath()
{
string dateStamp = DateTime.Now.ToString("yyyyMMdd");
return Path.Combine(logDir, $"{logPrefix}{dateStamp}.log");
}
// 超过大小,触发轮转(当前备份,重新新建)
private void CheckFileSize(string logFile)
{
if (!File.Exists(logFile)) return;
FileInfo fileInfo = new FileInfo(logFile);
if (fileInfo.Length >= maxFileSize)
{
RotateLogFiles(logFile);
}
}
// 实现日志轮转
private void RotateLogFiles(string currentLogFile)
{
for (int i = maxBackupFiles - 1; i >= 1; i--)
{
string source = $"{currentLogFile}.{i}";
string dest = $"{currentLogFile}.{i + 1}";
if (File.Exists(source))
{
File.Move(source, dest);
}
}
if (File.Exists(currentLogFile))
{
File.Move(currentLogFile, $"{currentLogFile}.1");
}
}
private string GetCurrentTimeStamp()
{
return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
}
private string GetLevelString(LogLevel level)
{
switch (level)
{
case LogLevel.LOG_DEBUG: return "DEBUG";
case LogLevel.LOG_INFO: return "INFO";
case LogLevel.LOG_WARNING: return "WARNING";
case LogLevel.LOG_ERROR: return "ERROR";
case LogLevel.LOG_XXX: return "XXX";
default: return "UNKNOWN";
}
}
// 主日志系统失败(如磁盘满、权限问题)
private void HandleLogFailure(Exception ex)
{
try
{
string fallbackPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
"LL_log_fallback.txt");
File.AppendAllText(fallbackPath,
$"{GetCurrentTimeStamp()} [LOG_ERROR] Failed to write log: {ex.Message}" +
Environment.NewLine);
}
catch { /* 最终保底措施 */ }
}
#endregion
}
}
// 使用方法 mxlLog.Instance.Error($"异常 ,行号{ex.StackTrace} ", ex);
// mxlLog.Instance.IsErrorEnabled = true; 使能错误log
// mxlLog.Instance.ClearOldLogs(5); 清理日志仅保留近5天