527 lines
18 KiB
C#
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
|
|
}
|
|
}
|