2026-07-14 13:55:17 +08:00
|
|
|
using System;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using System.Xml;
|
|
|
|
|
using log4net;
|
|
|
|
|
using log4net.Appender;
|
|
|
|
|
using log4net.Config;
|
|
|
|
|
|
|
|
|
|
namespace JY.Utility
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// LogHelper 用来记录系统的日志,包括异常等.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static class LogHelper
|
|
|
|
|
{
|
|
|
|
|
private static readonly ILog log;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static bool DebugMode = false;
|
|
|
|
|
|
|
|
|
|
#region 构造函数
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 构造函数
|
|
|
|
|
/// </summary>
|
|
|
|
|
static LogHelper()
|
|
|
|
|
{
|
2026-07-14 19:40:17 +08:00
|
|
|
var log4netConfigPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Log4net.config");
|
|
|
|
|
if (!File.Exists(log4netConfigPath))
|
|
|
|
|
{
|
|
|
|
|
log4netConfigPath = Path.Combine(Environment.CurrentDirectory, "Log4net.config");
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-14 13:55:17 +08:00
|
|
|
var repository = LogManager.CreateRepository("NETCoreRepository");
|
2026-07-14 19:40:17 +08:00
|
|
|
var configFile = new FileInfo(log4netConfigPath);
|
|
|
|
|
if (configFile.Exists)
|
|
|
|
|
{
|
|
|
|
|
XmlConfigurator.Configure(repository, configFile);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine("Log4net.config 文件未找到,日志将无法正常写入");
|
|
|
|
|
}
|
2026-07-14 13:55:17 +08:00
|
|
|
log = LogManager.GetLogger(repository.Name, "Test");
|
|
|
|
|
RunClearJob();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 清除过期日志
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 启动清除过期日志线程
|
|
|
|
|
/// </summary>
|
|
|
|
|
private static void RunClearJob()
|
|
|
|
|
{
|
|
|
|
|
Task.Run(() =>
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
ClearOverdue();
|
|
|
|
|
WriteLine("清除log4net过期日志");
|
|
|
|
|
//24小时清一次
|
|
|
|
|
Thread.Sleep(1000 * 60 * 60 * 24);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
WriteException(e);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 定期清除过期日志
|
|
|
|
|
/// </summary>
|
|
|
|
|
private static void ClearOverdue()
|
|
|
|
|
{
|
|
|
|
|
var days = 7;
|
|
|
|
|
if (File.Exists("Log4net.config"))
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
XmlDocument doc = new XmlDocument();
|
|
|
|
|
doc.Load(@"Log4net.config");
|
|
|
|
|
var node = doc.SelectSingleNode("/configuration/log4net");
|
|
|
|
|
days = Convert.ToInt32(node.Attributes["OverdueDays"].Value);
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
// ignored
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var apps = log.Logger.Repository.GetAppenders();
|
|
|
|
|
if (apps.Length <= 0)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var now = DateTime.UtcNow.AddDays(-days);
|
|
|
|
|
foreach (var item in apps)
|
|
|
|
|
{
|
|
|
|
|
if (item is RollingFileAppender roll)
|
|
|
|
|
{
|
|
|
|
|
var dir = Path.GetDirectoryName(roll.File);
|
|
|
|
|
var files = Directory.GetFiles(dir, "*.log.*");
|
|
|
|
|
//var sample = "log.txt2017-10-23.txt";
|
|
|
|
|
|
|
|
|
|
foreach (var filePath in files)
|
|
|
|
|
{
|
|
|
|
|
var file = new FileInfo(filePath);
|
|
|
|
|
if (file.CreationTime < now || file.LastWriteTime < now)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
file.Delete();
|
|
|
|
|
}
|
|
|
|
|
catch (Exception)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region 公布的写日志函数
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 记录一条日志信息。注意:在记录时该程序会自动在左侧增加一格日期。
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="strFormat">字符串的组成格式</param>
|
|
|
|
|
/// <param name="args">参数</param>
|
|
|
|
|
public static void WriteLine(string strFormat, params object[] args)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
log.Info($"{string.Format(strFormat, args)}");
|
|
|
|
|
}
|
|
|
|
|
catch (Exception exp)
|
|
|
|
|
{
|
|
|
|
|
Trace.WriteLine("LOG ERROR: " + exp.Message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 记录一条日志信息。注意:在记录时该程序会自动在左侧增加一格日期。
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="strLog">字符串的组成格式</param>
|
|
|
|
|
public static void WriteLine(string strLog)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
Debug.Assert(strLog != null);
|
|
|
|
|
log.Info($"{strLog}");
|
|
|
|
|
}
|
|
|
|
|
catch (Exception exp)
|
|
|
|
|
{
|
|
|
|
|
Trace.WriteLine("LOG ERROR: " + exp.Message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 记录一条错误日志信息。注意:在记录时该程序会自动在左侧增加一格日期。
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="strLog"></param>
|
|
|
|
|
public static void WriteErrorLine(string strLog)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
Debug.Assert(strLog != null);
|
|
|
|
|
log.Error($"{strLog}");
|
|
|
|
|
}
|
|
|
|
|
catch (Exception exp)
|
|
|
|
|
{
|
|
|
|
|
Trace.WriteLine("LOG ERROR: " + exp.Message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 记录一条日志信息。注意:在记录时该程序会自动在左侧增加一格日期。
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="strLog">字符串的组成格式</param>
|
|
|
|
|
public static void WriteDebugLine(string strLog)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
Debug.Assert(strLog != null);
|
|
|
|
|
log.Debug($"{strLog}");
|
|
|
|
|
}
|
|
|
|
|
catch (Exception exp)
|
|
|
|
|
{
|
|
|
|
|
Trace.WriteLine("LOG ERROR: " + exp.Message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 记录异常(在调试模式)
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="exp"></param>
|
|
|
|
|
public static void WriteDebugException(Exception exp)
|
|
|
|
|
{
|
|
|
|
|
WriteDebugException(exp, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 记录异常(在调试模式)
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="exp"></param>
|
|
|
|
|
/// <param name="strFormat"></param>
|
|
|
|
|
/// <param name="args"></param>
|
|
|
|
|
public static void WriteDebugException(Exception exp, string strFormat, params object[] args)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
Debug.Assert(exp != null);
|
|
|
|
|
var sb = new StringBuilder();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sb.AppendFormat("[{0}] DEBUG 找到 [{1}] 异常: {2}\r\n", DateTime.Now.ToString("HH:mm:ss"),
|
|
|
|
|
exp.GetType().Name, exp.Message);
|
|
|
|
|
|
|
|
|
|
// 附加信息
|
|
|
|
|
if (strFormat != null) sb.AppendFormat(" Annex : {0}\r\n", string.Format(strFormat, args));
|
|
|
|
|
|
|
|
|
|
// 调试信息
|
|
|
|
|
sb.AppendFormat(" Source : {0}\r\n", exp.Source);
|
|
|
|
|
sb.AppendFormat(" Time : {0}\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
|
|
|
|
sb.AppendFormat(" OS/VER : {0} {1}\r\n", Environment.OSVersion.Platform,
|
|
|
|
|
Environment.OSVersion.Version);
|
|
|
|
|
sb.AppendFormat(" Thread : {0}\r\n", Thread.CurrentThread.Name);
|
|
|
|
|
|
|
|
|
|
// 栈信息
|
|
|
|
|
sb.AppendFormat(" Stack : {0}\r\n", exp.StackTrace);
|
|
|
|
|
|
|
|
|
|
// 内部异常, 最多5级
|
|
|
|
|
var inner = exp.InnerException;
|
|
|
|
|
for (var i = 0; i < 5 && inner != null; i++)
|
|
|
|
|
{
|
|
|
|
|
// 显示内部异常
|
|
|
|
|
sb.AppendFormat(" ----- InnerException ---------------------------\r\n");
|
|
|
|
|
sb.AppendFormat(" ExceptionType: {0}\r\n", inner.GetType().Name);
|
|
|
|
|
sb.AppendFormat(" Message: {0}\r\n", inner.Message);
|
|
|
|
|
sb.AppendFormat(" Stack : {0}\r\n", inner.StackTrace);
|
|
|
|
|
|
|
|
|
|
// 获取异常的内部异常
|
|
|
|
|
inner = inner.InnerException;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.Error(sb.ToString());
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Trace.WriteLine("LOG ERROR: " + ex.Message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 记录下该异常
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="exp">需要记录的异常对象</param>
|
|
|
|
|
public static void WriteException(Exception exp)
|
|
|
|
|
{
|
|
|
|
|
WriteException(exp, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 记录下该异常
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="exp">异常对象</param>
|
|
|
|
|
/// <param name="strFormat">附加信息格式字符串,如果不需要,则该参数为 null</param>
|
|
|
|
|
/// <param name="args">参数</param>
|
|
|
|
|
public static void WriteException(Exception exp, string strFormat, params object[] args)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
Debug.Assert(exp != null);
|
|
|
|
|
var sb = new StringBuilder();
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
sb.AppendFormat("[{0}] 找到 [{1}] 异常: {2}\r\n", DateTime.Now.ToString("HH:mm:ss"), exp.GetType().Name,
|
|
|
|
|
exp.Message);
|
|
|
|
|
|
|
|
|
|
// 附加信息
|
|
|
|
|
if (strFormat != null) sb.AppendFormat(" Annex : {0}\r\n", string.Format(strFormat, args));
|
|
|
|
|
|
|
|
|
|
// 调试信息
|
|
|
|
|
sb.AppendFormat(" Source : {0}\r\n", exp.Source);
|
|
|
|
|
sb.AppendFormat(" Time : {0}\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
|
|
|
|
sb.AppendFormat(" OS/VER : {0} {1}\r\n", Environment.OSVersion.Platform,
|
|
|
|
|
Environment.OSVersion.Version);
|
|
|
|
|
sb.AppendFormat(" Thread : {0}\r\n", Thread.CurrentThread.Name);
|
|
|
|
|
|
|
|
|
|
// 栈信息
|
|
|
|
|
sb.AppendFormat(" Stack : {0}\r\n", exp.StackTrace);
|
|
|
|
|
|
|
|
|
|
// 内部异常, 最多5级
|
|
|
|
|
var inner = exp.InnerException;
|
|
|
|
|
for (var i = 0; i < 5 && inner != null; i++)
|
|
|
|
|
{
|
|
|
|
|
// 显示内部异常
|
|
|
|
|
sb.AppendFormat(" ----- InnerException ---------------------------\r\n");
|
|
|
|
|
sb.AppendFormat(" ExceptionType: {0}\r\n", inner.GetType().Name);
|
|
|
|
|
sb.AppendFormat(" Message: {0}\r\n", inner.Message);
|
|
|
|
|
sb.AppendFormat(" Stack : {0}\r\n", inner.StackTrace);
|
|
|
|
|
|
|
|
|
|
// 获取异常的内部异常
|
|
|
|
|
inner = inner.InnerException;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.Error(sb.ToString());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Trace.WriteLine("LOG ERROR: " + ex.Message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Dump 一个对象
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="obj"></param>
|
|
|
|
|
public static void WriteObject(object obj)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var sb = new StringBuilder();
|
|
|
|
|
if (obj == null)
|
|
|
|
|
{
|
|
|
|
|
sb.AppendLine("-- The object is null\r\n");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
sb.AppendFormat("[{0}] {1} has {2} property\r\n",
|
|
|
|
|
DateTime.Now, obj.GetType().Name, obj.GetType().GetProperties().Length);
|
|
|
|
|
|
|
|
|
|
var pis = obj.GetType().GetProperties();
|
|
|
|
|
var iMaxLength = 0;
|
|
|
|
|
foreach (var pi in pis)
|
|
|
|
|
if (pi.CanRead && !pi.IsSpecialName)
|
|
|
|
|
iMaxLength = Math.Max(pi.Name.Length, iMaxLength);
|
|
|
|
|
|
|
|
|
|
foreach (var pi in pis)
|
|
|
|
|
if (pi.CanRead && !pi.IsSpecialName)
|
|
|
|
|
sb.AppendFormat(" {0} - {1}\r\n", pi.Name.PadRight(iMaxLength, ' '),
|
|
|
|
|
pi.GetValue(obj, null));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception exp)
|
|
|
|
|
{
|
|
|
|
|
Trace.WriteLine("LOG ERROR: " + exp.Message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 错误日志带异常
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="message"></param>
|
|
|
|
|
/// <param name="ex"></param>
|
|
|
|
|
public static void Error(string message,Exception ex)
|
|
|
|
|
{
|
|
|
|
|
ILog log = LogManager.GetLogger("Error");
|
|
|
|
|
if (log.IsErrorEnabled)
|
|
|
|
|
{
|
|
|
|
|
log.Error(message,ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// <summary>
|
|
|
|
|
/// 错误日志不带异常
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="message">错误日志</param>
|
|
|
|
|
public static void Error(string message)
|
|
|
|
|
{
|
|
|
|
|
ILog log = LogManager.GetLogger("Error");
|
|
|
|
|
if (log.IsErrorEnabled)
|
|
|
|
|
{
|
|
|
|
|
log.Error(message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|