using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using static System.DateTime;
namespace DownKyi.Core.Logging
{
///
/// 日志组件
///
public class LogManager
{
private static readonly ConcurrentQueue> LogQueue = new ConcurrentQueue>();
///
/// 自定义事件
///
public static event Action Event;
static LogManager()
{
var writeTask = new Task(obj =>
{
while (true)
{
Pause.WaitOne(1000, true);
List temp = new List();
foreach (var logItem in LogQueue)
{
string logPath = logItem.Item1;
string logMergeContent = string.Concat(logItem.Item2, Environment.NewLine, "----------------------------------------------------------------------------------------------------------------------", Environment.NewLine);
string[] logArr = temp.FirstOrDefault(d => d[0].Equals(logPath));
if (logArr != null)
{
logArr[1] = string.Concat(logArr[1], logMergeContent);
}
else
{
logArr = new[]
{
logPath,
logMergeContent
};
temp.Add(logArr);
}
LogQueue.TryDequeue(out Tuple _);
}
foreach (var item in temp)
{
WriteText(item[0], item[1]);
}
}
}, null, TaskCreationOptions.LongRunning);
writeTask.Start();
}
private static AutoResetEvent Pause => new AutoResetEvent(false);
private static string logDirectory;
///
/// 日志存放目录,默认日志放在当前应用程序运行目录下的logs文件夹中
///
public static string LogDirectory
{
get => logDirectory ?? (Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory).Any(s => s.Contains("Web.config")) ? AppDomain.CurrentDomain.BaseDirectory + @"App_Data\Logs\" : Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs"));
set
{
//自定义目录
if (!Directory.Exists(value))
{
Directory.CreateDirectory(value);
}
logDirectory = value;
}
}
///
/// 写入Info级别的日志
///
///
public static void Info(string info)
{
LogQueue.Enqueue(new Tuple(GetLogPath(), $"{Now} [{Thread.CurrentThread.ManagedThreadId}] {nameof(info).ToUpper()} {info}"));
var log = new LogInfo()
{
LogLevel = LogLevel.Info,
Message = info,
Time = Now,
ThreadId = Thread.CurrentThread.ManagedThreadId
};
Event?.Invoke(log);
}
///
/// 写入Info级别的日志
///
///
///
public static void Info(string source, string info)
{
LogQueue.Enqueue(new Tuple(GetLogPath(), $"{Now} [{Thread.CurrentThread.ManagedThreadId}] {nameof(info).ToUpper()} {source} {info}"));
LogInfo log = new LogInfo()
{
LogLevel = LogLevel.Info,
Message = info,
Time = Now,
ThreadId = Thread.CurrentThread.ManagedThreadId,
Source = source
};
Event?.Invoke(log);
}
///
/// 写入Info级别的日志
///
///
///
public static void Info(Type source, string info)
{
LogQueue.Enqueue(new Tuple(GetLogPath(), $"{Now} [{Thread.CurrentThread.ManagedThreadId}] {nameof(info).ToUpper()} {source.FullName} {info}"));
LogInfo log = new LogInfo()
{
LogLevel = LogLevel.Info,
Message = info,
Time = Now,
ThreadId = Thread.CurrentThread.ManagedThreadId,
Source = source.FullName
};
Event?.Invoke(log);
}
///
/// 写入debug级别日志
///
/// 异常对象
public static void Debug(string debug)
{
LogQueue.Enqueue(new Tuple(GetLogPath(), $"{Now} [{Thread.CurrentThread.ManagedThreadId}] {nameof(debug).ToUpper()} {debug}"));
LogInfo log = new LogInfo()
{
LogLevel = LogLevel.Debug,
Message = debug,
Time = Now,
ThreadId = Thread.CurrentThread.ManagedThreadId
};
Event?.Invoke(log);
}
///
/// 写入debug级别日志
///
/// 异常源的类型
/// 异常对象
public static void Debug(string source, string debug)
{
LogQueue.Enqueue(new Tuple(GetLogPath(), $"{Now} [{Thread.CurrentThread.ManagedThreadId}] {nameof(debug).ToUpper()} {source} {debug}"));
LogInfo log = new LogInfo()
{
LogLevel = LogLevel.Debug,
Message = debug,
Time = Now,
ThreadId = Thread.CurrentThread.ManagedThreadId,
Source = source
};
Event?.Invoke(log);
}
///
/// 写入debug级别日志
///
/// 异常源的类型
/// 异常对象
public static void Debug(Type source, string debug)
{
LogQueue.Enqueue(new Tuple(GetLogPath(), $"{Now} [{Thread.CurrentThread.ManagedThreadId}] {nameof(debug).ToUpper()} {source.FullName} {debug}"));
LogInfo log = new LogInfo()
{
LogLevel = LogLevel.Debug,
Message = debug,
Time = Now,
ThreadId = Thread.CurrentThread.ManagedThreadId,
Source = source.FullName
};
Event?.Invoke(log);
}
///
/// 写入error级别日志
///
/// 异常对象
public static void Error(Exception error)
{
LogQueue.Enqueue(new Tuple(GetLogPath(), $"{Now} [{Thread.CurrentThread.ManagedThreadId}] {nameof(error).ToUpper()} {error.Source} {error.Message}{Environment.NewLine}{error.StackTrace}"));
LogInfo log = new LogInfo()
{
LogLevel = LogLevel.Error,
Message = error.Message,
Time = Now,
ThreadId = Thread.CurrentThread.ManagedThreadId,
Source = error.Source,
Exception = error,
ExceptionType = error.GetType().Name
};
Event?.Invoke(log);
}
///
/// 写入error级别日志
///
/// 异常源的类型
/// 异常对象
public static void Error(Type source, Exception error)
{
LogQueue.Enqueue(new Tuple(GetLogPath(), $"{Now} [{Thread.CurrentThread.ManagedThreadId}] {nameof(error).ToUpper()} {source.FullName} {error.Message}{Environment.NewLine}{error.StackTrace}"));
LogInfo log = new LogInfo()
{
LogLevel = LogLevel.Error,
Message = error.Message,
Time = Now,
ThreadId = Thread.CurrentThread.ManagedThreadId,
Source = source.FullName,
Exception = error,
ExceptionType = error.GetType().Name
};
Event?.Invoke(log);
}
///
/// 写入error级别日志
///
/// 异常源的类型
/// 异常信息
public static void Error(Type source, string error)
{
LogQueue.Enqueue(new Tuple(GetLogPath(), $"{Now} [{Thread.CurrentThread.ManagedThreadId}] {nameof(error).ToUpper()} {source.FullName} {error}"));
LogInfo log = new LogInfo()
{
LogLevel = LogLevel.Error,
Message = error,
Time = Now,
ThreadId = Thread.CurrentThread.ManagedThreadId,
Source = source.FullName,
//Exception = error,
ExceptionType = error.GetType().Name
};
Event?.Invoke(log);
}
///
/// 写入error级别日志
///
/// 异常源的类型
/// 异常对象
public static void Error(string source, Exception error)
{
LogQueue.Enqueue(new Tuple(GetLogPath(), $"{Now} [{Thread.CurrentThread.ManagedThreadId}] {nameof(error).ToUpper()} {source} {error.Message}{Environment.NewLine}{error.StackTrace}"));
LogInfo log = new LogInfo()
{
LogLevel = LogLevel.Error,
Message = error.Message,
Time = Now,
ThreadId = Thread.CurrentThread.ManagedThreadId,
Source = source,
Exception = error,
ExceptionType = error.GetType().Name
};
Event?.Invoke(log);
}
///
/// 写入error级别日志
///
/// 异常源的类型
/// 异常信息
public static void Error(string source, string error)
{
LogQueue.Enqueue(new Tuple(GetLogPath(), $"{Now} [{Thread.CurrentThread.ManagedThreadId}] {nameof(error).ToUpper()} {source} {error}"));
LogInfo log = new LogInfo()
{
LogLevel = LogLevel.Error,
Message = error,
Time = Now,
ThreadId = Thread.CurrentThread.ManagedThreadId,
Source = source,
//Exception = error,
ExceptionType = error.GetType().Name
};
Event?.Invoke(log);
}
///
/// 写入fatal级别日志
///
/// 异常对象
public static void Fatal(Exception fatal)
{
LogQueue.Enqueue(new Tuple(GetLogPath(), $"{Now} [{Thread.CurrentThread.ManagedThreadId}] {nameof(fatal).ToUpper()} {fatal.Source} {fatal.Message}{Environment.NewLine}{fatal.StackTrace}"));
LogInfo log = new LogInfo()
{
LogLevel = LogLevel.Fatal,
Message = fatal.Message,
Time = Now,
ThreadId = Thread.CurrentThread.ManagedThreadId,
Source = fatal.Source,
Exception = fatal,
ExceptionType = fatal.GetType().Name
};
Event?.Invoke(log);
}
///
/// 写入fatal级别日志
///
/// 异常源的类型
/// 异常对象
public static void Fatal(Type source, Exception fatal)
{
LogQueue.Enqueue(new Tuple(GetLogPath(), $"{Now} [{Thread.CurrentThread.ManagedThreadId}] {nameof(fatal).ToUpper()} {source.FullName} {fatal.Message}{Environment.NewLine}{fatal.StackTrace}"));
LogInfo log = new LogInfo()
{
LogLevel = LogLevel.Fatal,
Message = fatal.Message,
Time = Now,
ThreadId = Thread.CurrentThread.ManagedThreadId,
Source = source.FullName,
Exception = fatal,
ExceptionType = fatal.GetType().Name
};
Event?.Invoke(log);
}
///
/// 写入fatal级别日志
///
/// 异常源的类型
/// 异常对象
public static void Fatal(Type source, string fatal)
{
LogQueue.Enqueue(new Tuple(GetLogPath(), $"{Now} [{Thread.CurrentThread.ManagedThreadId}] {nameof(fatal).ToUpper()} {source.FullName} {fatal}"));
LogInfo log = new LogInfo()
{
LogLevel = LogLevel.Fatal,
Message = fatal,
Time = Now,
ThreadId = Thread.CurrentThread.ManagedThreadId,
Source = source.FullName,
//Exception = fatal,
ExceptionType = fatal.GetType().Name
};
Event?.Invoke(log);
}
///
/// 写入fatal级别日志
///
/// 异常源的类型
/// 异常对象
public static void Fatal(string source, Exception fatal)
{
LogQueue.Enqueue(new Tuple(GetLogPath(), $"{Now} [{Thread.CurrentThread.ManagedThreadId}] {nameof(fatal).ToUpper()} {source} {fatal.Message}{Environment.NewLine}{fatal.StackTrace}"));
LogInfo log = new LogInfo()
{
LogLevel = LogLevel.Fatal,
Message = fatal.Message,
Time = Now,
ThreadId = Thread.CurrentThread.ManagedThreadId,
Source = source,
Exception = fatal,
ExceptionType = fatal.GetType().Name
};
Event?.Invoke(log);
}
///
/// 写入fatal级别日志
///
/// 异常源的类型
/// 异常对象
public static void Fatal(string source, string fatal)
{
LogQueue.Enqueue(new Tuple(GetLogPath(), $"{Now} [{Thread.CurrentThread.ManagedThreadId}] {nameof(fatal).ToUpper()} {source} {fatal}"));
LogInfo log = new LogInfo()
{
LogLevel = LogLevel.Fatal,
Message = fatal,
Time = Now,
ThreadId = Thread.CurrentThread.ManagedThreadId,
Source = source,
ExceptionType = fatal.GetType().Name
};
Event?.Invoke(log);
}
private static string GetLogPath()
{
string newFilePath;
var logDir = string.IsNullOrEmpty(LogDirectory) ? Path.Combine(Environment.CurrentDirectory, "logs") : LogDirectory;
Directory.CreateDirectory(logDir);
string extension = ".log";
string fileNameNotExt = Now.ToString("yyyyMMdd");
string fileNamePattern = string.Concat(fileNameNotExt, "(*)", extension);
List filePaths = Directory.GetFiles(logDir, fileNamePattern, SearchOption.TopDirectoryOnly).ToList();
if (filePaths.Count > 0)
{
int fileMaxLen = filePaths.Max(d => d.Length);
string lastFilePath = filePaths.Where(d => d.Length == fileMaxLen).OrderByDescending(d => d).FirstOrDefault();
if (new FileInfo(lastFilePath).Length > 1 * 1024 * 1024)
{
var no = new Regex(@"(?is)(?<=\()(.*)(?=\))").Match(Path.GetFileName(lastFilePath)).Value;
var parse = int.TryParse(no, out int tempno);
var formatno = $"({(parse ? (tempno + 1) : tempno)})";
var newFileName = String.Concat(fileNameNotExt, formatno, extension);
newFilePath = Path.Combine(logDir, newFileName);
}
else
{
newFilePath = lastFilePath;
}
}
else
{
var newFileName = string.Concat(fileNameNotExt, $"({0})", extension);
newFilePath = Path.Combine(logDir, newFileName);
}
return newFilePath;
}
private static void WriteText(string logPath, string logContent)
{
try
{
if (!File.Exists(logPath))
{
File.CreateText(logPath).Close();
}
using (var sw = File.AppendText(logPath))
{
sw.Write(logContent);
}
}
catch (Exception)
{
// ignored
}
}
}
}