123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 |
- using log4net;
- using log4net.Config;
- using log4net.Repository;
- using System.Text;
- using System.Timers;
- using System.Xml;
- namespace LogHelper
- {
- /// <summary>
- /// 日志帮助类
- /// </summary>
- public static class LogHub
- {
- /// <summary>
- /// 日志仓库
- /// </summary>
- public static ILoggerRepository? LoggerRepository { get; set; }
- #region 写入日志
- private static ILog? GetLog(ILogType type, string flagKey)
- {
- if (LoggerRepository == null)
- return null;
- if (type.SubLogNames.ContainsKey(flagKey))
- return LogManager.GetLogger(LoggerRepository.Name, type.SubLogNames[flagKey]);
- var defaultKey = string.Empty;
- foreach (var key in type.SubLogNames.Keys)
- {
- defaultKey = key;
- break;
- }
- return LogManager.GetLogger(LoggerRepository.Name, type.SubLogNames[defaultKey]);
- }
- #region Info
- /// <summary>
- /// 运行记录
- /// </summary>
- /// <param name="type">日志类型</param>
- /// <param name="message">消息</param>
- /// <param name="ex">异常</param>
- /// <param name="flagKey">日志子项索引Key</param>
- public static void Info(this ILogType type, string message, Exception ex, string flagKey) => GetLog(type, flagKey.ToUpper())?.Info(GetLogMessage(message, ex));
- /// <summary>
- /// 运行记录
- /// </summary>
- /// <param name="type">日志类型</param>
- /// <param name="message">消息</param>
- /// <param name="flagKey">日志子项索引Key</param>
- public static void Info(this ILogType type, string message, string flagKey) => type.Info(message, null!, flagKey);
- /// <summary>
- /// 运行记录
- /// </summary>
- /// <param name="type">日志类型</param>
- /// <param name="ex">异常</param>
- /// <param name="flagKey">日志子项索引Key</param>
- public static void Info(this ILogType type, Exception ex, string flagKey) => type.Info(null!, ex, flagKey);
- #endregion Info
- #region Error
- /// <summary>
- /// 错误记录
- /// </summary>
- /// <param name="type">日志类型</param>
- /// <param name="message">消息</param>
- /// <param name="ex">异常</param>
- /// <param name="flagKey">日志子项索引Key</param>
- public static void Error(this ILogType type, string message, Exception ex, string flagKey) => GetLog(type, flagKey.ToUpper())?.Error(GetLogMessage(message, ex));
- /// <summary>
- /// 错误记录
- /// </summary>
- /// <param name="type">日志类型</param>
- /// <param name="message">消息</param>
- /// <param name="flagKey">日志子项索引Key</param>
- public static void Error(this ILogType type, string message, string flagKey) => type.Error(message, null!, flagKey);
- /// <summary>
- /// 错误记录
- /// </summary>
- /// <param name="type">日志类型</param>
- /// <param name="ex">异常</param>
- /// <param name="flagKey">日志子项索引Key</param>
- public static void Error(this ILogType type, Exception ex, string flagKey) => type.Error(null!, ex, flagKey);
- #endregion Error
- #region Warn
- /// <summary>
- /// 警告
- /// </summary>
- /// <param name="type">日志类型</param>
- /// <param name="message">消息</param>
- /// <param name="ex">异常</param>
- /// <param name="flagKey">日志子项索引Key</param>
- public static void Warn(this ILogType type, string message, Exception ex, string flagKey) => GetLog(type, flagKey.ToUpper())?.Warn(GetLogMessage(message, ex));
- /// <summary>
- /// 警告
- /// </summary>
- /// <param name="type">日志类型</param>
- /// <param name="message">消息</param>
- /// <param name="flagKey">日志子项索引Key</param>
- public static void Warn(this ILogType type, string message, string flagKey) => type.Warn(message, null!, flagKey);
- /// <summary>
- /// 警告
- /// </summary>
- /// <param name="type">日志类型</param>
- /// <param name="ex">异常</param>
- /// <param name="flagKey">日志子项索引Key</param>
- public static void Warn(this ILogType type, Exception ex, string flagKey) => type.Warn(null!, ex, flagKey);
- #endregion Warn
- /// <summary>
- /// 获取详细日志信息
- /// </summary>
- /// <param name="message">信息</param>
- /// <param name="ex">异常</param>
- /// <returns>详细信息</returns>
- private static string GetLogMessage(string message, Exception ex)
- {
- if (string.IsNullOrEmpty(message) && ex == null)
- return "Unknown error.";
- if (string.IsNullOrEmpty(message) && ex != null)
- return $"[Type:{ex.GetType().Name}][StackTrace:{ex.StackTrace}][Message:{ex.Message.Replace("\r\n", " ")}]";
- if (!string.IsNullOrEmpty(message) && ex == null)
- return message;
- return $"[Message:{message}][Type:{ex!.GetType().Name}][StackTrace:{ex.StackTrace}][Ex Message:{ex.Message.Replace("\r\n", " ")}]";
- }
- #endregion 写入日志
- #region 初始化日志
- private static string? _configPath = "Log";
- private static int _fileSize = 500;
- private static readonly List<ILogType> InitList = new List<ILogType>();
- private static readonly LogConfig ConfigModel = new LogConfig();
- private static bool _cleanSet = false;
- private static string? _previousCleanDay = null;
- private static int _cleanDays = 30;
- private static System.Timers.Timer? _logCleanTimer;
- /// <summary>
- /// 设置配置信息
- /// </summary>
- /// <param name="logConfig"></param>
- public static void SetConfigInfo(LogConfig logConfig)
- {
- SetConfigPath(logConfig.LogPath);
- SetLogFileSize(logConfig.LogSize);
- SetLogCleanDays(logConfig.LogDays);
- SetConfigInfo(logConfig.Logs!);
- }
- /// <summary>
- /// 日志配置
- /// </summary>
- /// <param name="path"></param>
- public static void SetConfigPath(string path)
- {
- _configPath = path;
- }
- /// <summary>
- /// 设置日志层级关系
- /// </summary>
- /// <param name="logConfigs">配置信息</param>
- public static void SetConfigInfo(List<LogConfigModel> logConfigs)
- {
- ConfigModel.Logs = logConfigs;
- }
- /// <summary>
- /// 设置日志项目文件数量和大小
- /// </summary>
- /// <param name="size">单文件大小(单位MB,最小10)</param>
- public static void SetLogFileSize(int size)
- {
- if (size < 10)
- return;
- _fileSize = size;
- }
- /// <summary>
- /// 设置日志清理周期
- /// </summary>
- /// <param name="days">清理周期</param>
- public static void SetLogCleanDays(int days)
- {
- if (days < 7)
- return;
- _cleanDays = days;
- }
- /// <summary>
- /// 初始化Log组件
- /// </summary>
- /// <param name="types">日志类型数组</param>
- public static void Init(params ILogType[] types)
- {
- var addedTypes = types.Where(p => !InitList.Contains(p)).ToList();
- if (addedTypes.Count == 0)
- return;
- if (ConfigModel.Logs == null || ConfigModel.Logs.Count == 0)
- throw new Exception("Log init, config is null.");
- _configPath = ConfigModel.Logs.FirstOrDefault(p => !string.IsNullOrEmpty(p.FileName))!.FileName;
- var xmlDoc = new XmlDocument();
- xmlDoc.AppendChild(xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", null));
- var configuration = xmlDoc.CreateElement("configuration");
- var root = xmlDoc.CreateElement("log4net");
- foreach (var item in addedTypes)
- {
- InitList.Add(item);
- var config = ConfigModel.Logs.FirstOrDefault(p => p.Name == item.LogName);
- if (config is null)
- {
- config = new LogConfigModel
- {
- Name = item.LogName,
- FileName = _configPath,
- SubLogNames = item.SubLogNames
- };
- }
- else
- {
- config.SubLogNames ??= new Dictionary<string, string>();
- foreach (var key in config.SubLogNames.Keys.Where(key => item.SubLogNames == null || !item.SubLogNames.ContainsKey(key)))
- {
- item.SubLogNames?.Add(key, config.SubLogNames[key]);
- }
- foreach (var key in item.SubLogNames!.Keys.Where(key => !config.SubLogNames.ContainsKey(key)))
- {
- config.SubLogNames.Add(key, item.SubLogNames[key]);
- }
- }
- if (item.SubLogNames == null || item.SubLogNames.Count == 0)
- continue;
- CreateXml(xmlDoc, root, config);
- }
- configuration.AppendChild(root);
- xmlDoc.AppendChild(configuration);
- //InitRepository.LoggerRepository ??= LogManager.CreateRepository("NETCoreRepository");
- LoggerRepository ??= LogManager.CreateRepository("NETCoreRepository");
- XmlConfigurator.Configure(LoggerRepository, new StreamReader(new MemoryStream(Encoding.ASCII.GetBytes(xmlDoc.OuterXml))).BaseStream);
- xmlDoc.Save("./log4net.config");
- if (_cleanSet) return;
- _cleanSet = true;
- _previousCleanDay = DateTime.Now.ToString("yyyyMMdd");
- // clean log
- _logCleanTimer = new System.Timers.Timer(1000 * 60);
- _logCleanTimer.Elapsed += LogCleanTimer_Elapsed;
- _logCleanTimer.Enabled = true;
- }
- /// <summary>
- /// 创建XML节点
- /// </summary>
- /// <param name="xmlDoc">XML文档</param>
- /// <param name="root"></param>
- /// <param name="config"></param>
- private static void CreateXml(XmlDocument xmlDoc, XmlElement root, LogConfigModel config)
- {
- foreach (var key in config.SubLogNames!.Keys)
- {
- // 创建 Logger
- var logger = xmlDoc.CreateElement("logger");
- logger.SetAttribute("name", config.SubLogNames[key]);
- var level = xmlDoc.CreateElement("level");
- level.SetAttribute("value", "ALL");
- var appenderRef = xmlDoc.CreateElement("appender-ref");
- appenderRef.SetAttribute("ref", $"{config.SubLogNames[key]}Appender");
- logger.AppendChild(level);
- logger.AppendChild(appenderRef);
- // 创建 Appender
- var appender = xmlDoc.CreateElement("appender");
- appender.SetAttribute("name", $"{config.SubLogNames[key]}Appender");
- appender.SetAttribute("type", "log4net.Appender.RollingFileAppender");
- var param = xmlDoc.CreateElement("param");
- param.SetAttribute("name", "Encoding");
- param.SetAttribute("value", "utf-8");
- appender.AppendChild(param);
- var file = xmlDoc.CreateElement("file");
- file.SetAttribute("value", Path.Combine(config.FileName!, config.Name!));
- appender.AppendChild(file);
- var appendToFile = xmlDoc.CreateElement("appendToFile");
- appendToFile.SetAttribute("value", "true");
- appender.AppendChild(appendToFile);
- var rollingStyle = xmlDoc.CreateElement("rollingStyle");
- rollingStyle.SetAttribute("value", "Composite");
- appender.AppendChild(rollingStyle);
- var maxSizeRollBackups = xmlDoc.CreateElement("maxSizeRollBackups");
- maxSizeRollBackups.SetAttribute("value", "-1");
- appender.AppendChild(maxSizeRollBackups);
- var maximumFileSize = xmlDoc.CreateElement("maximumFileSize");
- maximumFileSize.SetAttribute("value", $"{_fileSize}MB");
- appender.AppendChild(maximumFileSize);
- var lockingModel = xmlDoc.CreateElement("lockingModel");
- lockingModel.SetAttribute("type", "log4net.Appender.FileAppender+MinimalLock");
- appender.AppendChild(lockingModel);
- var staticLogFileName = xmlDoc.CreateElement("staticLogFileName");
- staticLogFileName.SetAttribute("value", "false");
- appender.AppendChild(staticLogFileName);
- var datePattern = xmlDoc.CreateElement("DatePattern");
- datePattern.SetAttribute("value", $"/yyyyMMdd/'{config.SubLogNames[key]}.log'");
- appender.AppendChild(datePattern);
- var layout = xmlDoc.CreateElement("layout");
- layout.SetAttribute("type", "log4net.Layout.PatternLayout");
- var conversionPattern = xmlDoc.CreateElement("conversionPattern");
- conversionPattern.SetAttribute("value", "%date || %5level || %logger || %message || %exception || end %newline");
- layout.AppendChild(conversionPattern);
- appender.AppendChild(layout);
- root.AppendChild(appender);
- root.AppendChild(logger);
- }
- }
- private static void LogCleanTimer_Elapsed(object? sender, ElapsedEventArgs e)
- {
- try
- {
- if (_previousCleanDay!.Equals(DateTime.Now.ToString("yyyyMMdd")))
- return;
- _previousCleanDay = DateTime.Now.ToString("yyyyMMdd");
- if (!Directory.Exists(_configPath))
- return;
- string[] typeDirs = Directory.GetDirectories(_configPath);
- foreach (var t in typeDirs)
- {
- string[] dateDirs = Directory.GetDirectories(t);
- foreach (var t1 in dateDirs)
- {
- var dirName = t1[(t1.LastIndexOf('\\') + 1)..];
- if (Convert.ToInt32(dirName) < Convert.ToInt32(DateTime.Now.AddDays(_cleanDays * -1).ToString("yyyyMMdd")))
- Directory.Delete(t1, true);
- }
- }
- }
- catch (Exception)
- {
- //TODO:增加日志
- }
- }
- #endregion 初始化日志
- }
- }
|