//====================================================================== // // 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 } }