Files
lserp_cs_6.0/插件库/Lskj.Util/LogHelper.cs
2026-08-14 14:28:28 +08:00

527 lines
18 KiB
C#

/******************************
* 说明:本地日志帮助类
* 创建人:龚宇超
* 创建日期:2017-08-10
* 修改人:
* 修改日期:
* 修改备注:
* 版本:1.0.0.0
******************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.IO;
namespace Lskj.Util
{
/// <summary>
/// 日志类型
/// </summary>
public enum LogType
{
Error,
Warning,
Notice
}
/// <summary>
/// 日志帮助类
/// </summary>
public class LogHelper
{
[ThreadStatic]
private static DiagnosticExceptionObservationScope
_diagnosticExceptionObservation;
[ThreadStatic]
private static bool _observingDiagnosticException;
/// <summary>
/// 在当前线程建立短时异常观察范围。仅供受信任的 ERP 初始化诊断
/// 使用;异常对象不会因此写入桥协议,原有日志行为也不会改变。
/// </summary>
public static IDisposable BeginDiagnosticExceptionObservation(
Action<Exception> observer)
{
if (observer == null)
throw new ArgumentNullException("observer");
DiagnosticExceptionObservationScope scope =
new DiagnosticExceptionObservationScope(
observer,
_diagnosticExceptionObservation,
Thread.CurrentThread.ManagedThreadId);
_diagnosticExceptionObservation = scope;
return scope;
}
private static void ObserveDiagnosticException(Exception exception)
{
if (exception == null || _observingDiagnosticException) return;
_observingDiagnosticException = true;
try
{
DiagnosticExceptionObservationScope current =
_diagnosticExceptionObservation;
int depth = 0;
while (current != null && depth < 16)
{
try { current.Observer(exception); }
catch { }
current = current.Previous;
depth += 1;
}
}
finally
{
_observingDiagnosticException = false;
}
}
private sealed class DiagnosticExceptionObservationScope : IDisposable
{
private readonly int _ownerThreadId;
private bool _disposed;
public DiagnosticExceptionObservationScope(
Action<Exception> observer,
DiagnosticExceptionObservationScope previous,
int ownerThreadId)
{
Observer = observer;
Previous = previous;
_ownerThreadId = ownerThreadId;
}
public Action<Exception> Observer { get; private set; }
public DiagnosticExceptionObservationScope Previous
{
get;
private set;
}
public void Dispose()
{
if (_disposed) return;
if (Thread.CurrentThread.ManagedThreadId != _ownerThreadId
|| !object.ReferenceEquals(
_diagnosticExceptionObservation,
this))
{
throw new InvalidOperationException(
"诊断异常观察范围必须在创建线程按嵌套顺序释放。");
}
_diagnosticExceptionObservation = Previous;
Observer = null;
Previous = null;
_disposed = true;
}
}
/// <summary>
/// 日志文件存放文件夹
/// </summary>
private string _dicPath { get { return AppDomain.CurrentDomain.BaseDirectory + "Log"; } }
private string _pattern = ".txt";
/// <summary>
/// 单个日志文件大小
/// </summary>
private int _fileSize = 1024*2048;
/// <summary>
/// 日志队列
/// </summary>
private Queue<string> _logQueue = new Queue<string>();
/// <summary>
/// 日志队列锁
/// </summary>
private object _queueLock = new object();
private object _objLock = new object();
/// <summary>
/// 日志文件名列表
/// </summary>
private List<string> _fileList = new List<string>();
private static LogHelper instance = null;
public static LogHelper Instance
{
get {
if (instance == null)
{
instance = new LogHelper();
instance.Start();
}
return instance;
}
}
public LogHelper()
{
if(Directory.Exists(_dicPath))
{
_fileList.Clear();
foreach (string fileName in Directory.GetFiles(_dicPath,"*"+_pattern))
{
string name = fileName.Substring(fileName.LastIndexOf("\\")+1);
_fileList.Add(name);
}
}
}
public void Start()
{
Task.Factory.StartNew(()=> {
WriteLogFunc();
});
}
/// <summary>
/// <para>说明:写入文件</para>
/// <para>创建人:龚宇超</para>
/// <para>创建日期:2017-08-10 </para>
/// <para>修改人:</para>
/// <para>修改日期:</para>
/// <para>修改备注:</para>
/// <para>版本:1.0</para>
/// </summary>
private void WriteLogFunc()
{
while(true)
{
if (CurrentLogCount() > 0)
{
string strWriteLog = GetLog();
WriteLogToFile(strWriteLog);
}
else
Thread.Sleep(1000);
}
}
#region 日志队列使用方式
/// <summary>
/// <para>说明:加入日志</para>
/// <para>创建人:龚宇超</para>
/// <para>创建日期:2017-08-10 </para>
/// <para>修改人:</para>
/// <para>修改日期:</para>
/// <para>修改备注:</para>
/// <para>版本:1.0</para>
/// </summary>
/// <param name="strLog">The string log.</param>
private void AddLog(string strLog)
{
lock (_queueLock)
{
_logQueue.Enqueue(strLog);
}
}
/// <summary>
/// <para>说明:获取日志</para>
/// <para>创建人:龚宇超</para>
/// <para>创建日期:2017-08-10 </para>
/// <para>修改人:</para>
/// <para>修改日期:</para>
/// <para>修改备注:</para>
/// <para>版本:1.0</para>
/// </summary>
/// <returns>System.String.</returns>
private string GetLog()
{
string strLog = "";
lock (_queueLock)
{
if (_logQueue.Count > 0)
strLog = _logQueue.Dequeue();
}
return strLog;
}
/// <summary>
/// <para>说明:当前队列条数</para>
/// <para>创建人:龚宇超</para>
/// <para>创建日期:2017-08-10 </para>
/// <para>修改人:</para>
/// <para>修改日期:</para>
/// <para>修改备注:</para>
/// <para>版本:1.0</para>
/// </summary>
/// <returns>System.Int32.</returns>
private int CurrentLogCount()
{
int count = 0;
lock (_queueLock)
{
count = _logQueue.Count;
}
return count;
}
#endregion
#region Method
/// <summary>
/// <para>说明:检查日志存放目录是否存在,如果不存在就创建</para>
/// <para>创建人:龚宇超</para>
/// <para>创建日期:2017-08-10 </para>
/// <para>修改人:</para>
/// <para>修改日期:</para>
/// <para>修改备注:</para>
/// <para>版本:1.0</para>
/// </summary>
/// <returns><c>true</c> if [is directory exist]; otherwise, <c>false</c>.</returns>
private bool IsDirectoryExist()
{
if(!Directory.Exists(_dicPath))
{
try
{
Directory.CreateDirectory(_dicPath);
}
catch(Exception)
{
return false;
}
}
return true;
}
/// <summary>
/// <para>说明:创建日志文件,如果已存在文件名就改变</para>
/// <para>创建人:龚宇超</para>
/// <para>创建日期:2017-08-10 </para>
/// <para>修改人:</para>
/// <para>修改日期:</para>
/// <para>修改备注:</para>
/// <para>版本:1.0</para>
/// </summary>
/// <param name="filePath">The file path.</param>
/// <returns><c>true</c> if [is create log file] [the specified file path]; otherwise, <c>false</c>.</returns>
private bool IsCreateLogFile(ref string filePath)
{
if(File.Exists(filePath))
{
string fileName = Path.GetFileNameWithoutExtension(filePath);
int number = 1;
string dateFileName = DateTime.Now.ToShortDateString().Replace('/', '_');
while(true)
{
string tempName = string.Format("{0}.{1}{2}", dateFileName, number, _pattern);
if (_fileList.Where(p => p == tempName).Count() == 0)
break;
number++;
}
filePath = _dicPath+"\\"+ string.Format("{0}.{1}{2}", dateFileName, number, _pattern);
}
try
{
FileStream fs = File.Create(filePath, _fileSize);
fs.Close();
_fileList.Add(Path.GetFileName(filePath));
}
catch(Exception)
{
return false;
}
return true;
}
/// <summary>
/// <para>说明:检查写入的内容是否超过文件的大小限制</para>
/// <para>创建人:龚宇超</para>
/// <para>创建日期:2017-08-10 </para>
/// <para>修改人:</para>
/// <para>修改日期:</para>
/// <para>修改备注:</para>
/// <para>版本:1.0</para>
/// </summary>
/// <param name="filePath">The file path.</param>
/// <param name="writeLog">The write log.</param>
/// <returns><c>true</c> if [is log content out of size] [the specified file path]; otherwise, <c>false</c>.</returns>
private bool IsLogContentOutOfSize(string filePath,string writeLog)
{
FileInfo fInfo = new FileInfo(filePath);
if(fInfo.Length + writeLog.Length < _fileSize)
{
return false;
}
return true;
}
/// <summary>
/// <para>说明:检查日志目录下有没有最新的日志文件,没有就创建新的日文件</para>
/// <para>创建人:龚宇超</para>
/// <para>创建日期:2017-08-10 </para>
/// <para>修改人:</para>
/// <para>修改日期:</para>
/// <para>修改备注:</para>
/// <para>版本:1.0</para>
/// </summary>
/// <returns><c>true</c> if [is last file exist]; otherwise, <c>false</c>.</returns>
private bool IsLastFileExist()
{
if(_fileList.Count == 0)
{
string filePath = _dicPath + "\\" + DateTime.Now.ToShortDateString().Replace('/','_')+_pattern;
try
{
FileStream fs = File.Create(filePath,_fileSize);
fs.Close();
_fileList.Add(Path.GetFileName(filePath));
}
catch(Exception)
{
return false;
}
}
return true;
}
/// <summary>
/// <para>说明:日志写入文件</para>
/// <para>创建人:龚宇超</para>
/// <para>创建日期:2017-08-10 </para>
/// <para>修改人:</para>
/// <para>修改日期:</para>
/// <para>修改备注:</para>
/// <para>版本:1.0</para>
/// </summary>
/// <param name="writeLog">The write log.</param>
private void WriteLogToFile(string writeLog)
{
if (!IsDirectoryExist())
return;
if (!IsLastFileExist())
return;
string writeFilePath = _dicPath + "\\" + _fileList.Last();
if (!File.Exists(_dicPath + "\\" + DateTime.Now.ToShortDateString().Replace('/', '_') + _pattern))
{
writeFilePath = _dicPath + "\\" + DateTime.Now.ToShortDateString().Replace('/', '_') + _pattern;
if (!IsCreateLogFile(ref writeFilePath))
{
return;
}
}
if(IsLogContentOutOfSize(writeFilePath,writeLog))
{
if(!IsCreateLogFile(ref writeFilePath))
{
return;
}
}
FileStream fstream = null;
StreamWriter streamWriter = null;
try
{
fstream = new FileStream(writeFilePath,FileMode.Append,FileAccess.Write,FileShare.ReadWrite);
streamWriter = new StreamWriter(fstream,Encoding.UTF8);
streamWriter.WriteLine(writeLog);
streamWriter.Flush();
}
catch(Exception)
{
}
finally
{
streamWriter.Close();
fstream.Close();
}
}
/// <summary>
/// <para>说明:写入日志</para>
/// <para>创建人:龚宇超</para>
/// <para>创建日期:2017-08-10 </para>
/// <para>修改人:</para>
/// <para>修改日期:</para>
/// <para>修改备注:</para>
/// <para>版本:1.0</para>
/// </summary>
/// <param name="obj">The object.</param>
/// <param name="logType">Type of the log.</param>
public void WriteLog(object obj,LogType logType= LogType.Notice)
{
string strLog = "";
lock(_objLock)
{
strLog = obj.ToString();
}
if (string.IsNullOrEmpty(strLog))
return;
string strWriteLog = string.Format("{0:yyyy-MM-dd HH:mm:ss:fff}", DateTime.Now) + " " +string.Format("[{0}]",logType)+ strLog + Environment.NewLine;
AddLog(strWriteLog);
}
/// <summary>
/// <para>说明:写入日志</para>
/// <para>创建人:龚宇超</para>
/// <para>创建日期:2017-08-12 </para>
/// <para>修改人:</para>
/// <para>修改日期:</para>
/// <para>修改备注:</para>
/// <para>版本:1.0</para>
/// </summary>
/// <param name="obj">The object.</param>
/// <param name="title">The title.</param>
/// <param name="logType">Type of the log.</param>
public void WriteLog(object obj, string title, LogType logType = LogType.Notice)
{
string strLog = "";
lock (_objLock)
{
strLog = obj.ToString();
}
if (string.IsNullOrEmpty(strLog))
return;
string strWriteLog = string.Format("{0:yyyy-MM-dd HH:mm:ss:fff}", DateTime.Now) + " " + string.Format("[{0}]", logType) + " " + string.Format("[{0}]", title) + strLog + Environment.NewLine;
AddLog(strWriteLog);
}
/// <summary>
/// <para>说明:写入异常</para>
/// <para>创建人:龚宇超</para>
/// <para>创建日期:2017-08-12 </para>
/// <para>修改人:</para>
/// <para>修改日期:</para>
/// <para>修改备注:</para>
/// <para>版本:1.0</para>
/// </summary>
/// <param name="obj">The object.</param>
/// <param name="logType">Type of the log.</param>
public void WriteError(Exception exception, LogType logType = LogType.Error)
{
ObserveDiagnosticException(exception);
string strLog = "";
lock (_objLock)
{
strLog = exception.Message + "\r\n" + exception.StackTrace;
}
if (string.IsNullOrEmpty(strLog))
return;
string strWriteLog = string.Format("{0:yyyy-MM-dd HH:mm:ss:fff}", DateTime.Now) + " " + string.Format("[{0}]", logType) + strLog + Environment.NewLine;
AddLog(strWriteLog);
}
/// <summary>
/// <para>说明:写入异常</para>
/// <para>创建人:龚宇超</para>
/// <para>创建日期:2017-08-12 </para>
/// <para>修改人:</para>
/// <para>修改日期:</para>
/// <para>修改备注:</para>
/// <para>版本:1.0</para>
/// </summary>
/// <param name="exception">The exception.</param>
/// <param name="title">The title.</param>
/// <param name="logType">Type of the log.</param>
public void WriteError(Exception exception, string title, LogType logType = LogType.Error)
{
ObserveDiagnosticException(exception);
string strLog = "";
lock (_objLock)
{
strLog = exception.Message + "\r\n" + exception.StackTrace;
}
if (string.IsNullOrEmpty(strLog))
return;
string strWriteLog = string.Format("{0:yyyy-MM-dd HH:mm:ss:fff}", DateTime.Now) + " " + string.Format("[{0}]", logType) + " " + string.Format("[{0}]", title) + strLog + Environment.NewLine;
AddLog(strWriteLog);
}
#endregion
}
}