| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 | using log4net;using log4net.Config;using log4net.Repository;using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Text;using System.Timers;using System.Xml;namespace Logs{    /// <summary>    /// 日志帮助类    /// </summary>    public static class LogHelper    {        /// <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]);            string 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 Timer _logCleanTimer;        /// <summary>        /// 设置配置信息        /// </summary>        /// <param name="logConfigs">配置信息</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;            XmlDocument xmlDoc = new XmlDocument();            xmlDoc.AppendChild(xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", null));            XmlElement configuration = xmlDoc.CreateElement("configuration");            XmlElement root = xmlDoc.CreateElement("log4net");            foreach (var item in addedTypes)            {                _initList.Add(item);                LogConfigModel 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                {                    if (config.SubLogNames is null)                        config.SubLogNames = new Dictionary<string, string>();                    foreach (var key in config.SubLogNames.Keys)                    {                        if (item.SubLogNames != null && item.SubLogNames.ContainsKey(key))                            continue;                        item.SubLogNames?.Add(key, config.SubLogNames[key]);                    }                    foreach (var key in item.SubLogNames.Keys)                    {                        if (config.SubLogNames.ContainsKey(key))                            continue;                        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");            if (LoggerRepository == null)                LoggerRepository = LogManager.CreateRepository("NETCoreRepository");            XmlConfigurator.Configure(LoggerRepository, new StreamReader(new MemoryStream(Encoding.ASCII.GetBytes(xmlDoc.OuterXml))).BaseStream);            xmlDoc.Save("./log4net.config");            if (!_cleanSet)            {                _cleanSet = true;                _previousCleanDay = DateTime.Now.ToString("yyyyMMdd");                // clean log                _logCleanTimer = new 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                XmlElement logger = xmlDoc.CreateElement("logger");                logger.SetAttribute("name", config.SubLogNames[key]);                XmlElement level = xmlDoc.CreateElement("level");                level.SetAttribute("value", "ALL");                XmlElement appender_ref = xmlDoc.CreateElement("appender-ref");                appender_ref.SetAttribute("ref", $"{config.SubLogNames[key]}Appender");                logger.AppendChild(level);                logger.AppendChild(appender_ref);                // 创建 Appender                XmlElement appender = xmlDoc.CreateElement("appender");                appender.SetAttribute("name", $"{config.SubLogNames[key]}Appender");                appender.SetAttribute("type", "log4net.Appender.RollingFileAppender");                XmlElement param = xmlDoc.CreateElement("param");                param.SetAttribute("name", "Encoding");                param.SetAttribute("value", "utf-8");                appender.AppendChild(param);                XmlElement file = xmlDoc.CreateElement("file");                file.SetAttribute("value", Path.Combine(config.FileName, config.Name));                appender.AppendChild(file);                XmlElement appendToFile = xmlDoc.CreateElement("appendToFile");                appendToFile.SetAttribute("value", "true");                appender.AppendChild(appendToFile);                XmlElement rollingStyle = xmlDoc.CreateElement("rollingStyle");                rollingStyle.SetAttribute("value", "Composite");                appender.AppendChild(rollingStyle);                XmlElement maxSizeRollBackups = xmlDoc.CreateElement("maxSizeRollBackups");                maxSizeRollBackups.SetAttribute("value", "-1");                appender.AppendChild(maxSizeRollBackups);                XmlElement maximumFileSize = xmlDoc.CreateElement("maximumFileSize");                maximumFileSize.SetAttribute("value", $"{_fileSize}MB");                appender.AppendChild(maximumFileSize);                XmlElement lockingModel = xmlDoc.CreateElement("lockingModel");                lockingModel.SetAttribute("type", "log4net.Appender.FileAppender+MinimalLock");                appender.AppendChild(lockingModel);                XmlElement staticLogFileName = xmlDoc.CreateElement("staticLogFileName");                staticLogFileName.SetAttribute("value", "false");                appender.AppendChild(staticLogFileName);                XmlElement DatePattern = xmlDoc.CreateElement("DatePattern");                DatePattern.SetAttribute("value", $"/yyyyMMdd/'{config.SubLogNames[key]}.log'");                appender.AppendChild(DatePattern);                XmlElement layout = xmlDoc.CreateElement("layout");                layout.SetAttribute("type", "log4net.Layout.PatternLayout");                XmlElement 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);                for (int i = 0; i < typeDirs.Length; i++)                {                    string[] dateDirs = Directory.GetDirectories(typeDirs[i]);                    for (int j = 0; j < dateDirs.Length; j++)                    {                        string dirName = dateDirs[j].Substring(dateDirs[j].LastIndexOf('\\') + 1);                        if (Convert.ToInt32(dirName) < Convert.ToInt32(DateTime.Now.AddDays(_cleanDays * -1).ToString("yyyyMMdd")))                            Directory.Delete(dateDirs[j], true);                    }                }            }            catch (Exception ex)            {                //LogInfo.Log.Info(ex.Message, ex, "FATAL");            }        }        #endregion 初始化日志    }}
 |