//======================================================================
//
// Copyright (C) 2013 仙剑
// All rights reserved
// guid1: 4323ea5b-c739-4c99-add9-8739f89d0ab9
// CLR Version: 2.0.50727.5420
// Name: LogOperator
// Computer: CHARLEY-PC
// Organization: VoiceCyber
// Namespace: VCLogWebSDK
// File Name: LogOperator
//
// created by Charley at 2013/6/9 12:01:11
// http://www.baidu.com/p/仙剑200801
//
//======================================================================
using System;
using System.Linq;
using System.Text;
using System.Security.AccessControl;
using System.IO;
using System.Threading;
namespace Core.StlMes.Client.PlnSaleOrd
{
///
/// 日志操作,实现写日志、备份与回删日志
///
/// 使用实例:
/// LogOperator logOperator=new LogOperator();
/// logOperator.WriteOperationLog(mode,category,msg);
///
/// 可以对日志文件大小、日志文件夹大小、日志文件名、日志保存路径进行设置
/// 自动备份、自动回删日志文件
/// 支持无阻塞的异步方式写操作日志(logOperator.WriteOperationLogAsync(int level,category,msg))
///
/// Charley
/// 2013/11/5
///
public class LogOperator
{
private const int LOG_FILE_SIZE = 1000; //log file size 1000(KB)
private const int LOG_DIR_SIZE = 10; //log directory size 10(M)
private const string LOG_FILE_NAME = "log";
private const string LOG_PATH = "log";
private const string LOG_NAME = "XJLogOperator";
private const int LOG_SAVE_DAYS = 31;
private delegate void WriteLogDelegate(LogMode level, string category, string msg); //利用委托异步写操作日志
private WriteLogDelegate mWriteLogDelegate;
private StreamWriter mLogWriter;
private object mLogWriterLocker;
private DateTime mLastDate;
private Thread mThreadDelete;
private bool m_bStart = false;
#region Properties
private int mLogFileMaxSize;
///
/// 单个日志文件的大小,单位KB
///
public int LogFileMaxSize
{
set { mLogFileMaxSize = value; }
}
private int mLogDirMaxSize;
///
/// 日志文件夹总大小,单位MB,(暂未实现)
///
public int LogDirMaxSize
{
set { mLogDirMaxSize = value; }
}
private string mLogFileName;
///
/// 日志文件名
///
public string LogFileName
{
get { return mLogFileName; }
set { mLogFileName = value; }
}
private string mLogPath;
private string m_LogPathDate;//包含日期的路径
///
/// 日志路径(相对路径或绝对路径)
///
public string LogPath
{
get { return mLogPath; }
set
{
mLogPath = string.IsNullOrEmpty(value) ? LOG_PATH : value;
if (!Path.IsPathRooted(mLogPath))
{
m_LogPathDate = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, string.Format("{0}{1}", mLogPath, "\\" + DateTime.Now.ToString("yyyyMMdd")));
}
if (mLogWriter != null)
{
try
{
mLogWriter.Dispose();
//mLogWriter.Close();
mLogWriter = null;
}
catch { }
string path = Path.Combine(m_LogPathDate, m_LogPathDate);
mLogWriter = new StreamWriter(path, true, Encoding.Default);
}
}
}
private string mErrorMsg;
///
/// 操作错误消息
///
public string ErrorMsg
{
get { return mErrorMsg; }
}
private string mLogName;
///
/// 日志名称
///
public string LogName
{
set { mLogName = value; }
}
private LogMode mLogMode;
///
/// 日志级别
///
public LogMode LogMode
{
get { return mLogMode; }
set { mLogMode = value; }
}
public int mLogSaveDays;
///
/// 日志保留天数
///
// public int LogSaveDays
// {
// get { return mLogSaveDays; }
// set { mLogSaveDays = value; }
// }
#endregion
///
/// 使用默认值创建日志实例
///
public LogOperator()
{
mWriteLogDelegate = WriteOperationLogWithoutReturn;
mLogWriterLocker = new object();
mLogMode = LogMode.General;
mLogName = LOG_NAME;
mLogFileMaxSize = LOG_FILE_SIZE;
mLogDirMaxSize = LOG_DIR_SIZE;
mLogFileName = LOG_FILE_NAME;
mLogPath = LOG_PATH;
mLastDate = DateTime.Now;
mLogSaveDays = -1;
if (!Path.IsPathRooted(mLogPath))
{
m_LogPathDate = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, string.Format("{0}{1}", mLogPath, "\\" + DateTime.Now.ToString("yyyyMMdd")));
}
}
///
/// 指定日志名称
///
///
public LogOperator(string logName)
: this()
{
mLogName = logName;
}
///
/// 启动日志写入器
///
///
public bool Start()
{
if (string.IsNullOrEmpty(mLogPath) || string.IsNullOrEmpty(mLogFileName))
{
mErrorMsg = "Log file name or log file path is empty.";
return false;
}
try
{
DateTime now = DateTime.Now;
mLastDate = now;
m_LogPathDate = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, string.Format("{0}{1}", mLogPath, "\\" + DateTime.Now.ToString("yyyyMMdd")));
string dir = Path.IsPathRooted(mLogPath) ? mLogPath : Path.Combine(AppDomain.CurrentDomain.BaseDirectory, string.Format("{0}{1}", mLogPath, "\\" + DateTime.Now.ToString("yyyyMMdd")));
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
addDirPower(dir, "Everyone", "FullControl");
}
string path = Path.Combine(dir, string.Format("{0}{1}.txt", mLogFileName, now.ToString("yyyMMdd")));
lock (mLogWriterLocker)
{
if (mLogWriter != null)
{
try
{
mLogWriter.Dispose();
mLogWriter.Close();
mLogWriter = null;
}
catch { }
}
mLogWriter = new StreamWriter(path, true, Encoding.Default);
}
mLogWriter.WriteLine("{0}\tLog Started.{1}", LogMode.Info, mLastDate.ToString("yyyy/MM/dd"));
mLogWriter.Flush();
if (!m_bStart)
{
StartDeleteLogThread();
m_bStart = true;
}
return true;
}
catch (Exception ex)
{
mErrorMsg = ex.Message;
return false;
}
}
///
/// 停止并关闭日志写入器
///
public void Stop()
{
StopDeleteThread();
if (mLogWriter != null)
{
try
{
mLogWriter.Dispose();
mLogWriter.Close();
mLogWriter = null;
}
catch { }
}
}
///
/// 写操作日志
///
/// 日志级别
/// 类别
/// 消息
///
public bool WriteOperationLog(LogMode mode, string category, string msg)
{
try
{
if ((mode & mLogMode) == 0) { return true; }
DateTime now = DateTime.Now;
if (mLastDate.Date != now.Date)
{
if (!Start())
{
return false;
}
}
if (mLogWriter == null)
{
Start();
}
if (category.Length <= 8)
{
category = category + "\t";
}
string formatstr = string.Format("{0}\t{1}\t{2}\t{3}", mode, DateTime.Now.ToString("HH:mm:ss.fff"), category, msg);
lock (mLogWriterLocker)
{
if (mLogWriter != null)
{
mLogWriter.WriteLine(formatstr);
mLogWriter.Flush();
}
}
if (!BackupLog())
{
return false;
}
return true;
}
catch (Exception ex)
{
mErrorMsg = ex.ToString();
return false;
}
}
///
/// 写操作日志
///
///
///
///
public bool WriteOperationLog(LogMode mode, string msg)
{
return WriteOperationLog(mode, mLogName, msg);
}
///
/// 以无阻塞的异步方式写操作日志
///
/// 日志级别
///
///
public void WriteOperationAsync(LogMode mode, string category, string msg)
{
mWriteLogDelegate.BeginInvoke(mode, category, msg, null, null);
}
///
/// 记录Debug日志
///
/// 类别
/// 消息
///
public bool LogDebug(string category, string msg)
{
return WriteOperationLog(LogMode.Debug, category, msg);
}
///
/// 记录Info日志
///
/// 类别
/// 消息
///
public bool LogInfo(string category, string msg)
{
return WriteOperationLog(LogMode.Info, category, msg);
}
///
/// 记录Warn日志
///
/// 类别
/// 消息
///
public bool LogWarn(string category, string msg)
{
return WriteOperationLog(LogMode.Warn, category, msg);
}
///
/// 记录Error日志
///
/// 类别
/// 消息
///
public bool LogError(string category, string msg)
{
return WriteOperationLog(LogMode.Error, category, msg);
}
///
/// 记录Fatal日志
///
/// 类别
/// 消息
///
public bool LogFatal(string category, string msg)
{
return WriteOperationLog(LogMode.Fatal, category, msg);
}
#region BackupLog
///
/// 备份日志文件
///
///
private bool BackupLog()
{
string filePath = Path.Combine(m_LogPathDate, string.Format("{0}{1}.txt", mLogFileName, mLastDate.ToString("yyyyMMdd")));
if (!File.Exists(filePath))
{
mErrorMsg = string.Format("File not exist.\t{0}", filePath);
return false;
}
lock (mLogWriterLocker)
{
var file = new FileInfo(filePath);
long size = file.Length;
if (size > mLogFileMaxSize * 1024)
{
string path = string.Empty;
path = Path.Combine(m_LogPathDate, string.Format("{0}{1}.txt", mLogFileName, DateTime.Now.ToString("yyyyMMddhhmmssfff")));
mLogWriter.Dispose();
mLogWriter.Close();
try
{
file.MoveTo(path);
}
catch { }
mLogWriter = new StreamWriter(filePath, true, Encoding.Default);
WriteOperationLog(LogMode.Info, "BackupLog", string.Format("Backup log {0} successful.", path));
}
}
return true;
}
#endregion
#region Other
private void WriteOperationLogWithoutReturn(LogMode mode, string category, string msg)
{
WriteOperationLog(mode, category, msg);
}
private void addDirPower(string dirName, string username, string power)
{
DirectoryInfo dirInfo = new DirectoryInfo(dirName);
if ((dirInfo.Attributes & FileAttributes.ReadOnly) != 0)
{
dirInfo.Attributes = FileAttributes.Normal;
}
//取得访问控制列表
DirectorySecurity dirSecurity = dirInfo.GetAccessControl();
switch (power)
{
case "FullControl":
dirSecurity.AddAccessRule(new FileSystemAccessRule(username, FileSystemRights.FullControl, InheritanceFlags.ContainerInherit, PropagationFlags.InheritOnly, AccessControlType.Allow));
break;
case "ReadOnly":
dirSecurity.AddAccessRule(new FileSystemAccessRule(username, FileSystemRights.Read, AccessControlType.Allow));
break;
case "Write":
dirSecurity.AddAccessRule(new FileSystemAccessRule(username, FileSystemRights.Write, AccessControlType.Allow));
break;
case "Modify":
dirSecurity.AddAccessRule(new FileSystemAccessRule(username, FileSystemRights.Modify, AccessControlType.Allow));
break;
}
dirInfo.SetAccessControl(dirSecurity);
}
#endregion
#region DeleteLog
private void StartDeleteLogThread()
{
if (mThreadDelete != null)
{
try
{
mThreadDelete.Abort();
mThreadDelete = null;
}
catch
{
}
}
try
{
mThreadDelete = new Thread(DeleteLogWorker);
mThreadDelete.Start();
}
catch
{
//WriteOperationLog(LogMode.Error, "StartDeleteThread",string.Format("Start delete thread fail.\t{0}", ex.Message));
}
}
private void StopDeleteThread()
{
if (mThreadDelete != null)
{
try
{
mThreadDelete.Abort();
mThreadDelete = null;
}
catch { }
}
}
public void SleepSeconds(int nSecond)
{
for (int i = 0; i < nSecond; i++)
{
Thread.Sleep(1000);
}
}
private void DeleteLogWorker()
{
while (true)
{
SleepSeconds(5);
if (mLogSaveDays < 0)
{
continue;
}
DeleteLog();
SleepSeconds(3600);
}
}
///
/// 回删日志文件
///
///
private void DeleteLog()
{
string dir = Path.IsPathRooted(mLogPath) ? mLogPath : Path.Combine(AppDomain.CurrentDomain.BaseDirectory, mLogPath);
DirectoryInfo logdir = new DirectoryInfo(dir);
var ListFiles = logdir.GetDirectories("*").OrderByDescending(f => f.LastWriteTime).ToList();
DateTime now = DateTime.Now;
for (int i = ListFiles.Count - 1; i >= 0; i--)
{
if ((now - ListFiles[i].LastWriteTime).TotalDays > mLogSaveDays)
{
try
{
WriteOperationLog(LogMode.Warn, "DeleteLogFile", string.Format("Delete log file {0}", ListFiles[i].Name));
ListFiles[i].Delete(true);
}
catch (Exception ex)
{
WriteOperationLog(LogMode.Warn, "DeleteLogFile", string.Format("Delete log file fail!\t{0}", ex.Message));
}
}
}
}
#endregion
}
///
/// 日志级别,可任意组合
///
[Flags]
public enum LogMode
{
///
/// 调试
///
Debug = 1,
///
/// 信息(默认)
///
Info = 2,
///
/// 警告
///
Warn = 4,
///
/// 错误
///
Error = 8,
///
/// 致命
///
Fatal = 16,
///
/// 所有消息
///
All = Debug | Info | Warn | Error | Fatal,
///
/// 一般
///
General = Info | Warn | Error | Fatal,
///
/// 自定义info 消息
///
Infomsg = Info | Warn | Error,
///
/// 自定义debug 消息
///
Debugmsg = Debug | Warn | Error,
///
/// 自定义默认 消息
///
Defaultmsg = Warn | Error
}
}