using DH.Commons.Helper; using System; using System.Collections.Concurrent; using System.IO; using System.Threading; using System.Threading.Tasks; using static DH.Commons.Enums.EnumHelper; namespace DH.Commons.Enums { public interface ILogOutput { event Action OnLogMsgOutput; void LogDisplay(LogMsg msg); } public interface ILogger { event Action OnLog; LoggerHelper LoggerHelper { get; set; } //void LogAsync(DateTime dt, LogLevel loglevel, string msg); void LogAsync(LogMsg msg); } public class LoggerHelper { public event Action OnLogExceptionRaised; public string LogPath { get; set; } public string LogPrefix { get; set; } LogLevel LogLevel = LogLevel.Information; public LoggerHelper() { } public LoggerHelper(string logPath, string logPrefix, LogLevel logLevel = LogLevel.Information) { LogPath = logPath; LogPrefix = logPrefix; LogLevel = logLevel; } public void SetLogLevel(LogLevel logLevel) { if (LogLevel != logLevel) LogLevel = logLevel; } ////耗时操作从 _taskFactory分配线程 //public TaskFactory _taskFactory = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.LongRunning); readonly ConcurrentQueue _logQueue = new ConcurrentQueue(); Task _logTask = null; readonly object _logLock = new object(); public async void LogAsync(LogMsg msg) { await Task.Run(() => { _logQueue.Enqueue(msg); lock (_logLock) { if (_logTask == null) { _logTask = Task.Run(async () => { string filePath = Path.Combine(LogPath, $"{(string.IsNullOrWhiteSpace(LogPrefix) ? "Log_" : ("Log_" + LogPrefix + "_"))}{DateTime.Now.ToString("yyyyMMdd")}.txt"); try { if (!StaticHelper.CheckFilesCanUse(filePath)) { OnLogExceptionRaised?.Invoke(DateTime.Now, $"日志文件{filePath}被占用,无法写入"); return; } using (StreamWriter writer = new StreamWriter(filePath, true, System.Text.Encoding.UTF8)) { while (true) { if (!Directory.Exists(LogPath)) { Directory.CreateDirectory(LogPath); } while (_logQueue.Count > 0) { if (_logQueue.TryDequeue(out LogMsg log)) { if (log.LogLevel >= LogLevel) { writer.WriteLine($"{log.LogTime.ToString("yyyy-MM-dd HH:mm:ss.fff")}[{log.ThreadId}]\t{log.LogLevel.GetEnumDescription()}\t{log.Msg}"); } } } writer.Flush(); await Task.Delay(2000); } } } catch (Exception ex) { //OnLogExceptionRaised?.Invoke(DateTime.Now, $"日志文件{filePath}写入异常:/*{ex.GetExceptionMessage()*/}"); OnLogExceptionRaised?.Invoke(DateTime.Now, $"日志文件{filePath}写入异常"); } }); } } }); } public void LogAsync(DateTime dt, LogLevel logLevel, string msg) { LogAsync(new LogMsg(dt, logLevel, msg)); } } public class LogMsg { public DateTime LogTime { get; set; } public LogLevel LogLevel { get; set; } //public string Prefix { get; set; } public string Msg { get; set; } public string MsgSource { get; set; } public int ThreadId { get; set; } public LogMsg() { } public LogMsg(DateTime dt, LogLevel logLevel, string msg) { LogTime = dt; LogLevel = logLevel; Msg = msg; } public override string ToString() { return $"{LogTime.ToString("HH:mm:ss.fff")}\t{MsgSource}\t{Msg}"; } } }