初始化版本
This commit is contained in:
279
SLC1-N/mxlLog.cs
Normal file
279
SLC1-N/mxlLog.cs
Normal file
@@ -0,0 +1,279 @@
|
||||
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天
|
||||
Reference in New Issue
Block a user