zoukankan      html  css  js  c++  java
  • 日志记录器

    项目名称 : Logger

    项目介绍

      适用范围:异常日志,操作日志,交互日志等等 各种日志

      日志存储方式:SqlServer , MySql, Oracle, Text(即文本文件)

      日志写入类型 :Immediate(即时)  Queue(队列)

      日志配置文件:LogConfig.xml

    1.配置文件介绍

      

     1 <?xml version="1.0" encoding="utf-8" ?>
     2 <configurations>
     3   <setting model="immediate" writer="sqlserver" connectionstring="server=.;database=Log;uid=sa;password=sqlpass;"></setting>
     4   <sections>
     5     <section type="LogService.Domain.ExceptionLog" catalog="ExceptionLog">
     6       <setting model="queue" writer="sqlserver" maxcount="1" interval="2" connectionstring="server=.;database=Log;uid=sa;password=sqlpass;"></setting>
     7       <mapping property="Message"></mapping>
     8       <mapping property="Source"></mapping>
     9       <mapping property="TargetSite"></mapping>
    10       <mapping property="StackTrace"></mapping>
    11       <mapping property="ErrorTime"></mapping>
    12       <mapping property="Remark"></mapping>
    13     </section>
    14   </sections>
    15 </configurations>
    LogConfig.xml

     文件介绍:

      sections节点:主要起到分类的作用,比如一个异常日志就需要一个sections

      section节点:日志分类属性节点

          type:日志实体类型的命名空间

          catalog:写入数据的表名

      setting节点: 主要设置写入类型,写入方式以及写入数据链接(这个节点在sections下面如果则节点不存在则采购最跟节点下面做为默认值)

            model(写入类型):queue(队列的方式写入)

          如果model为queue类型 则需要设置2个额外的属性 

          maxcount  :当内存存储日志条数到达maxcount条时则写入数据库或者文件

          interval:如果内存存储日志条数没有到达maxcount时间 但是时间间隔为interval秒时也会写入数据库或文件

        writer(写入方式):SqlServer , MySql, Oracle

        connectionstring(数据库链接):如果是写入数据则需要配置这个数据

        mapping : 日志实体对应字段描述

          property:字段名称

        

    2.服务层介绍(LogService)

      服务层即指日志组件提供给外界写入日志的方法

      该类只公布1个方法,WriteLog  写入类型

      该方法提供3个重置

       WriteLog(object item) 此方法会根据Objcet类型的命名空间去读取配置 并且解析出日志实体对象

       WriteLog(string content)  写入文本日志

       WriteLog(string content, string path)  写入文本日志并指定日志路径

     1     /// <summary>
     2     /// 日志记录器
     3     /// </summary>
     4     public class LogService
     5     {
     6         /// <summary>
     7         /// 添加日志
     8         /// </summary>
     9         /// <param name="item">日志内容</param>
    10         /// <returns>返回记录结果 成功?true:false</returns>
    11         public static bool WriteLog(object item)
    12         {
    13             return item != null && Allocator.Intance.Execute(item);
    14         }
    15 
    16         /// <summary>
    17         /// 记录文本日志
    18         /// </summary>
    19         /// <param name="content">日志内容</param>
    20         /// <returns>返回记录结果 成功?true:false</returns>
    21         public static bool WriteLog(string content) 
    22         {
    23             return WriteLog(content, Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs"));
    24         }
    25         /// <summary>
    26         /// 记录文本日志
    27         /// </summary>
    28         /// <param name="content">日志内容</param>
    29         /// <param name="path">日志路径</param>
    30         /// <returns>返回记录结果 成功?true:false</returns>
    31         public static bool WriteLog(string content, string path) 
    32         {
    33             return Factory.GetTextWriter(path).WriteLog(DateTime.Now.ToString("日志时间:yyyy-MM-dd HH:mm:ss fff  ") + content + Environment.NewLine);
    34         }
    35 
    36         internal static void WirteLogError(Exception exception) 
    37         {
    38             string content = string.Format("记录日志失败...消息:{0} 地址:{1} 堆栈:{2}", exception.Message, exception.TargetSite, exception.StackTrace);
    39             WriteLog(content);
    40         }
    41     }
    View Code

     2.解析配置文件介绍(Config)

      主要是把刚刚介绍的那几个属性解析出来 

      解析成Dictionary<string, ConfigSection>联系 key就是对象 type 即一个分类(列如一个异常日志)

      ConfigSection : 该日志的基本信息

         TypeName : 类型名称

         Catalog:表名

         Setting : 设置信息(数据库链接,写入数据库类型, 写入时间间隔 ,写入最大条数)      

         Mapping : 日志实体信息 

      

     1     internal class ConfigSection
     2     {
     3         internal ConfigSection(string typeName,string catalog,Setting setting,List<Mapping> mappings) 
     4         {
     5             TypeName = typeName;
     6             Catalog = catalog;
     7             Setting = setting;
     8             Mappings = mappings;
     9         }
    10         internal string TypeName { get; private set; }
    11         internal string Catalog { get; private set; }
    12         internal Setting Setting { get; private set; }
    13         internal List<Mapping> Mappings { get; private set; }
    14     }
    ConfigSection
     1     internal class ConfigSection
     2     {
     3         internal ConfigSection(string typeName,string catalog,Setting setting,List<Mapping> mappings) 
     4         {
     5             TypeName = typeName;
     6             Catalog = catalog;
     7             Setting = setting;
     8             Mappings = mappings;
     9         }
    10         internal string TypeName { get; private set; }
    11         internal string Catalog { get; private set; }
    12         internal Setting Setting { get; private set; }
    13         internal List<Mapping> Mappings { get; private set; }
    14     }
    Setting
    1 Mapping
    View Code

         解析代码LocalXMLLoader

     1     internal class LocalXMLLoader:Loader
     2     {
     3         private readonly string _path;
     4         internal LocalXMLLoader(string path) 
     5         {
     6             _path = path;
     7         }
     8 
     9         internal override Dictionary<string, ConfigSection> Execute()
    10         {
    11             Dictionary<string, ConfigSection> result = new Dictionary<string, ConfigSection>();
    12             XmlDocument doc = new XmlDocument();
    13             doc.Load(this._path);
    14             XmlNode defaultSettingNode = doc.SelectSingleNode("configurations/setting");
    15             Setting defaultSetting = ParseSetting(defaultSettingNode);
    16             XmlNodeList sectionNodes = doc.SelectNodes("configurations/sections/section");
    17             if (sectionNodes == null) return result;
    18             foreach (XmlNode sectionNode in sectionNodes)
    19             {
    20                 if (sectionNode.Attributes == null) continue;
    21                 string typeName = GetAttribute(sectionNode.Attributes["type"]);
    22                 string catalog = GetAttribute(sectionNode.Attributes["catalog"]);
    23                 Setting setting = ParseSetting(sectionNode.SelectSingleNode("setting"),defaultSetting);
    24                 List<Mapping> mappings = ParseMappings(sectionNode.SelectNodes("mapping"));
    25                 ConfigSection section = new ConfigSection(typeName, catalog, setting, mappings);
    26                 result.Add(section.TypeName, section);
    27             }
    28             return result;
    29         }
    30         private static Setting ParseSetting(XmlNode node) 
    31         {
    32             if (node == null || node.Attributes == null) return null;
    33             string model = GetAttribute(node.Attributes["model"]);
    34             //当在maxcount分钟内有大于等于interval条数据的时候才去写入数据库
    35             string maxCount = GetAttribute(node.Attributes["maxcount"]);
    36             string interval = GetAttribute(node.Attributes["interval"]);
    37             string writer = GetAttribute(node.Attributes["writer"]);
    38             string connectionString = GetAttribute(node.Attributes["connectionstring"]);
    39             return new Setting(model, maxCount, interval, writer, connectionString);
    40         }
    41         private static Setting ParseSetting(XmlNode node, Setting defaultSetting) 
    42         {
    43             Setting setting = ParseSetting(node);
    44             if (setting != null)
    45             {
    46                 return new Setting(
    47                     string.IsNullOrWhiteSpace(setting.Model) ? defaultSetting.Model : setting.Model,
    48                     string.IsNullOrWhiteSpace(setting.MaxCount) ? defaultSetting.MaxCount : setting.MaxCount,
    49                     string.IsNullOrWhiteSpace(setting.Interval) ? defaultSetting.Interval : setting.Interval,
    50                     string.IsNullOrWhiteSpace(setting.Writer) ? defaultSetting.Writer : setting.Writer,
    51                     string.IsNullOrWhiteSpace(setting.ConnectionString) ? defaultSetting.ConnectionString : setting.ConnectionString);
    52             }
    53             return defaultSetting;
    54         }
    55         private static List<Mapping> ParseMappings(XmlNodeList nodes) 
    56         {
    57             List<Mapping> result = new List<Mapping>();
    58             if (nodes != null)
    59             {
    60                 foreach (XmlNode node in nodes)
    61                 {
    62                     if (node.Attributes == null) continue;
    63                     string property = GetAttribute(node.Attributes["property"]);
    64                     string name = GetAttribute(node.Attributes["name"]);
    65                     string format = GetAttribute(node.Attributes["format"]);
    66                     result.Add(new Mapping(property, name, format));
    67                 }
    68             }
    69             return result;
    70         }
    71         private static string GetAttribute(XmlAttribute attr) 
    72         {
    73             return GetAttribute(attr, string.Empty);
    74         }
    75         private static string GetAttribute(XmlAttribute attr, string defaultValue)
    76         {
    77             return attr == null ? defaultValue : attr.Value;
    78         }
    79     }
    LocalXMLLoader

     3.写入存储方式(Writer)

      这里先暂时不考虑Context这个类型后面会讲解这个类型怎么来

      写入抽象一个类型出来提供2个写入方法

      单条写入

      internal abstract void Execute(Context log);

      批量写入
      internal abstract void Execute(List<Context> logs);

      DBWriter数据库写入方式

     1     internal abstract class DBWriter : Writer
     2     {
     3         private readonly string _connectionString = string.Empty;
     4         private readonly string _provider = string.Empty;
     5         protected readonly string Catalog = string.Empty;
     6         protected DBWriter(string provider, string connectionString, string cataLog)
     7         {
     8             _provider = provider;
     9             _connectionString = connectionString;
    10             Catalog = cataLog;
    11         }
    12         internal override void Execute(Context log)
    13         {
    14             if (log == null || log.Content == null || log.Content.Count == 0) return;
    15             try
    16             {
    17                 using (DbConnection conn = GetConnection())
    18                 {
    19                     using (DbCommand cmd = conn.CreateCommand())
    20                     {
    21                         PrepareInsert(cmd, log);
    22                         cmd.ExecuteNonQuery();
    23                     }
    24                 }
    25             }
    26             catch (Exception ex)
    27             {
    28                 LogService.WirteLogError(ex);
    29             }
    30         }
    31 
    32         internal override void Execute(List<Context> logs)
    33         {
    34             try
    35             {
    36                 using (DbConnection conn = GetConnection())
    37                 {
    38                     using (DbCommand cmd = conn.CreateCommand())
    39                     {
    40                         PrepareInsert(cmd, logs);
    41                         cmd.ExecuteNonQuery();
    42                     }
    43                 }
    44             }
    45             catch (Exception ex)
    46             {
    47                 LogService.WirteLogError(ex);
    48             }
    49         }
    50 
    51         private DbConnection GetConnection()
    52         {
    53             DbProviderFactory dbf = DbProviderFactories.GetFactory(_provider);
    54             DbConnection conn = dbf.CreateConnection();
    55             if (conn == null) return null;
    56             conn.ConnectionString = _connectionString;
    57             if (conn.State != ConnectionState.Open)
    58             {
    59                 conn.Open();
    60             }
    61             return conn;
    62         }
    63         protected abstract void PrepareInsert(DbCommand cmd, Context log);
    64         protected abstract void PrepareInsert(DbCommand cmd, List<Context> logs);
    65     }
    DBWriter

      Oracle数据库写入

     1     internal class OracleWriter:DBWriter
     2     {
     3         internal OracleWriter(string connectionString, string catalog) : base("System.Data.OracleClient", connectionString, catalog) { }
     4         protected override void PrepareInsert(DbCommand cmd, Context log)
     5         {
     6             const string sqlFormat = "INSERT INTO {0} ({1}) VALUES ({2})";
     7             var fields = new StringBuilder();
     8             var parameters = new StringBuilder();
     9 
    10             foreach (DataItem di in log.Content)
    11             {
    12                 fields.AppendFormat("{0},", di.Name);
    13                 parameters.AppendFormat(":{0},", di.Name);
    14                 var p = cmd.CreateParameter();
    15                 p.ParameterName = di.Name;
    16                 if (di.Value == null)
    17                 {
    18                     p.Value = System.DBNull.Value;
    19                 }
    20                 else if (di.Value is System.Enum)
    21                 {
    22                     p.Value = di.Value.GetHashCode();
    23                 }
    24                 else
    25                 {
    26                     p.Value = di.Value;
    27                 }
    28                 cmd.Parameters.Add(p);
    29             }
    30             cmd.CommandText = string.Format(sqlFormat,
    31                 Catalog,
    32                 fields.Remove(fields.Length - 1, 1),
    33                 parameters.Remove(parameters.Length - 1, 1));
    34         }
    35 
    36         protected override void PrepareInsert(DbCommand cmd, List<Context> logs)
    37         {
    38             const string sqlFormat = "INSERT INTO {0} ({1}) ({2})";
    39             const string fieldFormat = " SELECT {0} FROM DUAL UNION ALL";
    40             var fields = new StringBuilder();
    41             var parameters = new StringBuilder();
    42             int index = 1;
    43             foreach (Context log in logs)
    44             {
    45                 if (log.Content == null) continue;
    46                 var tempParam = new StringBuilder();
    47                 foreach (var di in log.Content)
    48                 {
    49                     tempParam.AppendFormat(":{0}{1},", di.Name, index);
    50                     var p = cmd.CreateParameter();
    51                     p.ParameterName = di.Name + index;
    52                     if (di.Value == null)
    53                     {
    54                         p.Value = System.DBNull.Value;
    55                     }
    56                     else if (di.Value is System.Enum)
    57                     {
    58                         p.Value = di.Value.GetHashCode();
    59                     }
    60                     else
    61                     {
    62                         p.Value = di.Value;
    63                     }
    64                     cmd.Parameters.Add(p);
    65                 }
    66                 if (fields.Length == 0)
    67                 {
    68                     foreach (var di in log.Content)
    69                     {
    70                         fields.Append(di.Name + ",");
    71                     }
    72                 }
    73                 index++;
    74                 parameters.AppendFormat(fieldFormat, tempParam.Remove(tempParam.Length - 1, 1));
    75             }
    76             cmd.CommandText = string.Format(sqlFormat,
    77                 Catalog,
    78                 fields.Remove(fields.Length - 1, 1),
    79                 parameters.Remove(parameters.Length - 10, 10));
    80         }
    81     }
    OracleWriter

      SqlService数据写入

     1     internal class SqlServiceWriter:DBWriter
     2     {
     3         internal SqlServiceWriter(string connectionString, string cataLog) : base("System.Data.SqlClient", connectionString, cataLog) { }
     4         protected override void PrepareInsert(DbCommand cmd, Context log)
     5         {
     6             const string sqlFormat = "INSERT INTO {0} ({1}) VALUES ({2});";
     7             StringBuilder fields = new StringBuilder();
     8             StringBuilder parameters = new StringBuilder();
     9 
    10             foreach (DataItem di in log.Content)
    11             {
    12                 fields.AppendFormat("{0},", di.Name);
    13                 parameters.AppendFormat("@{0},", di.Name);
    14                 DbParameter p = cmd.CreateParameter();
    15                 p.ParameterName = di.Name;
    16                 if (di.Value == null)
    17                 {
    18                     p.Value = DBNull.Value;
    19                 }
    20                 else if (di.Value is Enum)
    21                 {
    22                     p.Value = di.Value.GetHashCode();
    23                 }
    24                 else 
    25                 {
    26                     p.Value = di.Value;
    27                 }
    28                 cmd.Parameters.Add(p);
    29             }
    30             cmd.CommandText = string.Format(sqlFormat,
    31                    Catalog,
    32                    fields.Remove(fields.Length - 1, 1),
    33                    parameters.Remove(parameters.Length - 1, 1));
    34         }
    35 
    36         protected override void PrepareInsert(DbCommand cmd, List<Context> logs)
    37         {
    38             const string sqlFormat = "INSERT INTO {0} ({1}) ({2});";
    39             const string fieldFormat = " SELECT {0} UNION ALL";
    40             StringBuilder fields = new StringBuilder();
    41             StringBuilder parameters = new StringBuilder();
    42             int index = 1;
    43             foreach (Context log in logs)
    44             {
    45                 if (log.Content == null) continue;
    46                 StringBuilder tempParam = new StringBuilder();
    47                 foreach (DataItem di in log.Content)
    48                 {
    49                     tempParam.AppendFormat("@{0}{1},", di.Name, index);
    50                     DbParameter p = cmd.CreateParameter();
    51                     p.ParameterName = di.Name + index;
    52                     if (di.Value == null)
    53                     {
    54                         p.Value = DBNull.Value;
    55                     }
    56                     else if (di.Value is Enum)
    57                     {
    58                         p.Value = di.Value.GetHashCode();
    59                     }
    60                     else 
    61                     {
    62                         p.Value = di.Value;
    63                     }
    64                     cmd.Parameters.Add(p);
    65                 }
    66                 if (fields.Length == 0)
    67                 {
    68                     foreach (DataItem di in log.Content)
    69                     {
    70                         fields.Append(di.Name + ",");
    71                     }
    72                     index++;
    73                     parameters.AppendFormat(fieldFormat, tempParam.Remove(tempParam.Length - 1, 1));
    74                 }
    75             }
    76             cmd.CommandText = string.Format(sqlFormat,
    77                 Catalog,
    78                 fields.Remove(fields.Length - 1, 1),
    79                 parameters.Remove(parameters.Length - 10, 10));
    80 
    81         }
    82     }
    83 }
    SqlServiceWriter

      文本文件方式写入

      1     internal class TextWriter:Writer
      2     {
      3         private const long LogFileMaxLength = 1024 * 1024 * 1;
      4         private readonly string _fileName = string.Empty;
      5         internal TextWriter(string fineName) 
      6         {
      7             _fileName = fineName;
      8         }
      9         internal override void Execute(Context log)
     10         {
     11             try
     12             {
     13                 WriteLog(GetLogContent(log) + Environment.NewLine);
     14             }
     15             catch (Exception ex)
     16             {
     17                 LogService.WirteLogError(ex);
     18             }
     19         }
     20         internal override void Execute(List<Context> logs)
     21         {
     22             try
     23             {
     24                 StringBuilder sbContent = new StringBuilder();
     25                 foreach (Context log in logs)
     26                 {
     27                     sbContent.AppendLine(GetLogContent(log));
     28                 }
     29                 WriteLog(sbContent.ToString());
     30             }
     31             catch (Exception ex)
     32             {
     33                 LogService.WirteLogError(ex);
     34             }
     35         }
     36         internal bool WriteLog(string logInfo) 
     37         {
     38             if (string.IsNullOrWhiteSpace(logInfo)) 
     39             {
     40                 return true;
     41             }
     42             DateTime timeStamp = DateTime.Now;
     43             string path = GetFileMainPath(timeStamp);
     44             FileInfo lastFile = GetLastAccessFile(path);
     45             FileStream fileStream = GetFileStream(lastFile, path, timeStamp);
     46             if (fileStream == null) 
     47             {
     48                 return false;
     49             }
     50             try
     51             {
     52                 StreamWriter sw = new StreamWriter(fileStream);
     53                 sw.BaseStream.Seek(0, SeekOrigin.End);
     54                 sw.Write(logInfo);
     55                 sw.Flush();
     56                 sw.Close();
     57             }
     58             catch 
     59             {
     60                 return false;
     61             }
     62             finally
     63             {
     64                 fileStream.Close();
     65                 fileStream.Dispose();
     66             }
     67             return true;
     68         }
     69         private static FileInfo GetLastAccessFile(string path) 
     70         {
     71             FileInfo result = null;
     72             DirectoryInfo direcInfo = new DirectoryInfo(path);
     73             //查找目录中最后的创建的文档
     74             if (direcInfo.Exists)
     75             {
     76                 FileInfo[] fileInfos = direcInfo.GetFiles();
     77                 foreach (FileInfo fileinfo in fileInfos)
     78                 {
     79                     if (result == null)
     80                     {
     81                         result = fileinfo;
     82                     }
     83                     else if (result.CreationTime < fileinfo.CreationTime) 
     84                     {
     85                         result = fileinfo;
     86                     }
     87                 }
     88             }
     89             else 
     90             {
     91                 direcInfo.Create();
     92             }
     93             return result;
     94         }
     95         private static FileStream GetFileStream(FileInfo fileInfo, string path, DateTime timeStamp) 
     96         {
     97             FileStream result = null;
     98             // 没找到则创建一个新日志文件
     99             // 如果文件大于100M,则新创建一个文件
    100             // 如果文件无法打开,则新创建一个文件
    101             if (fileInfo == null)
    102             {
    103                 try
    104                 {
    105                     result = CreateFile(path, GetFileMainName(timeStamp));
    106                 }
    107                 catch (Exception)
    108                 {
    109                     return null;
    110                 }
    111             }
    112             else if (IsOutOfFileMaxLength(fileInfo.Length))
    113             {
    114                 result = CreateFile(path, GetFileMainName(timeStamp));
    115             }
    116             else 
    117             {
    118                 try
    119                 {
    120                     result = fileInfo.OpenWrite();
    121                 }
    122                 catch
    123                 {
    124                     result = CreateFile(path, GetFileMainName(timeStamp));
    125                 }
    126             }
    127             return result;
    128         }
    129         private static bool IsOutOfFileMaxLength(long fileLength) 
    130         {
    131             return fileLength > LogFileMaxLength;   
    132         }
    133         private static string GetLogContent(Context log)
    134         {
    135             StringBuilder result = new StringBuilder();
    136             result.AppendFormat("日志时间:{0} ", log.Time.ToString("yyyy-MM-dd HH:mm:ss fff"));
    137             if (log.Content != null)
    138             {
    139                 foreach (DataItem di in log.Content)
    140                 {
    141                     string value;
    142                     if (di.Value is DateTime)
    143                     {
    144                         if (di.Format == null || di.Format.Trim().Length == 0)
    145                         {
    146                             value = ((DateTime)di.Value).ToString("yyyy-MM-dd HH:mm:ss fff");
    147                         }
    148                         else
    149                         {
    150                             value = ((DateTime)di.Value).ToString(di.Format);
    151                         }
    152                     }
    153                     else 
    154                     {
    155                         value = (di.Value ?? "").ToString();
    156                     }
    157                     result.AppendFormat("{0}:{1}  ", di.Name, value);
    158                 }
    159             }
    160             result.AppendLine();
    161             return result.ToString();
    162         }
    163         private static FileStream CreateFile(string path, string fileName) 
    164         {
    165             return File.Create(string.Format(@"{0}{1}.log",path,fileName));
    166         }
    167 
    168         private string GetFileMainPath(DateTime timeStamp) 
    169         {
    170             return Path.Combine(_fileName, timeStamp.ToString("yyyyMMdd"));
    171         }
    172         private static string GetFileMainName(DateTime timeStamp) 
    173         {
    174             return timeStamp.ToString("HHmmss");
    175         }
    176     }
    TextWriter

    4.写入类型(Processor)

      处理方式:Immediate(即时写入)则非常简单只需要直接调用写入方法即可

    1     internal class ImmediateProcessor:Processor
    2     {
    3         internal ImmediateProcessor(Writer.Writer writer) : base(writer) { }
    4         internal override void Inject(Context log)
    5         {
    6             LogWriter.Execute(log);
    7         }
    8     }
    ImmediateProcessor

          处理方式:Queue(队列写入) 队列写入实现原理 则是新开一条线程来存储即将写入的日志 当写入满足配置文件配置的 maxcount  或者 interval 2个属性的任意一个条件则写入数据库

     1     internal class QueueProcessor:Processor
     2     {
     3         private readonly uint _maxCount;
     4         private readonly uint _interval;
     5         private readonly Queue<Context> _logs;
     6         private readonly object _locker = new object();
     7         private bool _stoped = true;
     8         private DateTime _lastFlusTime = DateTime.Now;
     9         internal QueueProcessor(Writer.Writer write, uint maxCount, uint interval) 
    10             :base(write)
    11         {
    12             _maxCount = maxCount;
    13             _interval = interval;
    14             _logs = new Queue<Context>();
    15         }
    16         internal override void Inject(Context log)
    17         {
    18             lock (_locker)
    19             {
    20                 _logs.Enqueue(log);
    21                 SetThread();
    22             }
    23         }
    24 
    25         private void SetThread()
    26         {
    27             if (!_stoped) return;
    28             _stoped = false;
    29             ThreadPool.QueueUserWorkItem(Run);
    30         }
    31         private void Run(object state) 
    32         {
    33             while (!_stoped)
    34             {
    35                 if (RequireFlush())
    36                 {
    37                     FlushData();
    38                     SetFlushInfo();
    39                 }
    40                 Thread.Sleep(50);
    41             }
    42         }
    43         private bool RequireFlush()
    44         {
    45             return _logs.Count >= _maxCount || IsExpired();
    46         }
    47 
    48         private bool IsExpired()
    49         {
    50             return (DateTime.Now - _lastFlusTime).TotalMinutes >= _interval;
    51         }
    52 
    53         private void FlushData()
    54         {
    55             LogWriter.Execute(GetData());
    56         }
    57 
    58         private List<Context> GetData()
    59         {
    60             List<Context> result = new List<Context>();
    61             lock (_locker)
    62             {
    63                 while (result.Count < _maxCount && _logs.Count > 0)
    64                 {
    65                     result.Add(_logs.Dequeue());
    66                 }
    67             }
    68             return result;
    69         }
    70 
    71         private void SetFlushInfo()
    72         {
    73             _lastFlusTime = DateTime.Now;
    74             if (_logs.Count == 0)
    75             {
    76                 _stoped = true;
    77             }
    78         }
    79     }
    QueueProcessor

     5.服务层创建日志并调用

     Allocator类来联系当前上下文

     Intance属性:为单列模式 使用单列模式创建该类型对象

     bool Execute(object item) 执行方法根据 item 取出配置文件信息 并且创建Context对象

     Processor GetProcessor(ConfigSection section, string key) 方法根据配置文件信息创建出使用那种写入方式跟数据库

     创建方式通过Factory类(工厂方法实现)

    Factory

     1     internal class Factory
     2     {
     3         internal static Processor.Processor CreateProcessor(Writer.Writer writer, Setting setting) 
     4         {
     5             Processor.Processor result = null;
     6             if (setting == null) return null;
     7             switch ((setting.Model ?? "").ToLower())
     8             {
     9                 case "queue":
    10                     result = new QueueProcessor(writer, GetUnit(setting.MaxCount, 10), GetUnit(setting.Interval, 2));
    11                     break;
    12                 case "immediate":
    13                     result = new ImmediateProcessor(writer);
    14                     break;
    15                         
    16             }
    17             return result;
    18         }
    19         private static uint GetUnit(string value, uint defaultVaule) 
    20         {
    21             uint result;
    22             if (!uint.TryParse(value,out result))
    23             {
    24                 result = defaultVaule;
    25             }
    26             return result;
    27         }
    28         private static readonly Dictionary<string, Writer.Writer> Writers = new Dictionary<string, Writer.Writer>();
    29         internal static Writer.Writer CreateWriter(ConfigSection section) 
    30         {
    31             if (section == null) return null;
    32             if (section.Setting == null) return null;
    33             string key = section.Setting.Writer + section.Catalog;
    34             if (Writers.ContainsKey(key))
    35             {
    36                 return Writers[key];
    37             }
    38             Writer.Writer writer = null;
    39             switch ((section.Setting.Writer ?? "").ToLower())
    40             {
    41                 case "text":
    42                     writer = new TextWriter(section.Catalog);
    43                     break;
    44                 case "oracle":
    45                     writer = new OracleWriter(section.Setting.ConnectionString,section.Catalog);
    46                     break;
    47                 case "sqlserver":
    48                     writer = new SqlServiceWriter(section.Setting.ConnectionString, section.Catalog);
    49                     break;
    50             }
    51             Writers.Add(key, writer);
    52             return writer;
    53         }
    54         private static readonly Dictionary<string, TextWriter> TextWriters = new Dictionary<string, TextWriter>();
    55         internal static TextWriter GetTextWriter(string path) 
    56         {
    57             TextWriter writer;
    58             if (TextWriters.TryGetValue(path, out writer)) return writer;
    59             writer = new TextWriter(path);
    60             TextWriters.Add(path, writer);
    61             return writer;
    62         }
    63         internal static Loader CreateLoader() 
    64         {
    65             //return new LocalXMLLoader(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "LogConfig.xml"));
    66             return new LocalXMLLoader(System.Configuration.ConfigurationManager.AppSettings["LogConfig"]);
    67         }
    68     }
    Factory
     1     /// <summary>
     2     /// 日志处理分配器
     3     /// </summary>
     4     internal class Allocator
     5     {
     6         private static readonly object InstanceLocker = new object();
     7         private static Allocator _intance;
     8 
     9         /// <summary>
    10         /// 分配器实例
    11         /// </summary>
    12         internal static Allocator Intance 
    13         {
    14             get 
    15             {
    16                 if (_intance == null)
    17                 {
    18                     lock (InstanceLocker)
    19                     {
    20                         if (_intance == null)
    21                         {
    22                             _intance = new Allocator();
    23                         }
    24                     }
    25                 }
    26                 return _intance;
    27             }
    28         }
    29 
    30         private readonly Dictionary<string, Processor.Processor> _processors;
    31         private Allocator() {
    32             _processors = new Dictionary<string, Processor.Processor>();
    33         }
    34         /// <summary>
    35         /// 分配日志
    36         /// </summary>
    37         /// <param name="item">日志信息</param>
    38         /// <returns>成功?true:false</returns>
    39         internal bool Execute(object item) 
    40         {
    41             DateTime logTime = DateTime.Now;
    42             string key = item.GetType().FullName;
    43             ConfigSection section = ConfigCollections.Instance[key];
    44             if (section == null)
    45             {
    46                 LogService.WriteLog("未找到[" + key + "]的配置信息");
    47             }
    48             else {
    49                 Processor.Processor processor = GetProcessor(section, key);
    50                 if (processor == null)
    51                 {
    52                     LogService.WriteLog("未找到日志[" + key + "的处理器");
    53                 }
    54                 else 
    55                 {
    56                     try
    57                     {
    58                         Context context = new Context(logTime, Parser.Execute(item, section.Mappings));
    59                         processor.Inject(context);
    60                         return true;
    61                     }
    62                     catch (Exception ex)
    63                     {
    64                         LogService.WirteLogError(ex);   
    65                     }
    66                 }
    67             }
    68             return false;
    69         }
    70         private Processor.Processor GetProcessor(ConfigSection section, string key) 
    71         {
    72             Processor.Processor processor = null;
    73             if (_processors.ContainsKey(key))
    74             {
    75                 return _processors[key];
    76             }
    77             lock (_processors)
    78             {
    79                 if (_processors.ContainsKey(key))
    80                 {
    81                     return _processors[key];
    82                 }
    83                 var writer = Factory.CreateWriter(section);
    84                 if (writer != null)
    85                 {
    86                     processor = Factory.CreateProcessor(writer, section.Setting);
    87                 }
    88                 _processors.Add(key, processor);
    89             }
    90             return processor;
    91         }
    92     }
    Allocator

    6.DEMO

     记录异常日志类型为列子 配置文件 如1.

     异常实体类ExceptionLog

     1     public class ExceptionLog
     2     {
     3         public ExceptionLog(string message, string source, string targetSite, string stackTrace, DateTime errorTime, string remark) 
     4         {
     5             this.Message = message;
     6             this.Source = source;
     7             this.TargetSite = targetSite;
     8             this.StackTrace = stackTrace;
     9             this.ErrorTime = errorTime;
    10             this.Remark = remark;
    11         }
    12         /// <summary>
    13         /// 消息
    14         /// </summary>
    15         public string Message { get; private set; }
    16         /// <summary>
    17         /// 程序集或对象的名称
    18         /// </summary>
    19         public string Source { get; private set; }
    20         /// <summary>
    21         /// 引发异常的方法
    22         /// </summary>
    23         public string TargetSite { get; private set; }
    24         /// <summary>
    25         /// 堆栈信息
    26         /// </summary>
    27         public string StackTrace { get; private set; }
    28         /// <summary>
    29         /// 错误发生时间
    30         /// </summary>
    31         public DateTime ErrorTime { get; private set; }
    32         /// <summary>
    33         /// 备注
    34         /// </summary>
    35         public string Remark { get; private set; }
    36     }
    ExceptionLog

    写入异常日志

     1     /// <summary>
     2     /// 记录日志
     3     /// </summary>
     4     public static class LogService
     5     {
     6         /// <summary>
     7         /// 记录异常日志
     8         /// </summary>
     9         /// <param name="ex">异常信息</param>
    10         public static void SaveExceptionLog(Exception ex)
    11         {
    12             SaveExceptionLog(ex, DateTime.Now);
    13         }
    14         /// <summary>
    15         /// 记录异常日志
    16         /// </summary>
    17         /// <param name="ex">异常信息</param>
    18         /// <param name="errorTime">发生异常时间</param>
    19         public static void SaveExceptionLog(Exception ex, DateTime errorTime)
    20         {
    21             SaveExceptionLog(ex, errorTime, string.Empty);
    22         }
    23         /// <summary>
    24         /// 记录异常日志
    25         /// </summary>
    26         /// <param name="ex">异常信息</param>
    27         /// <param name="errorTime">发生异常时间</param>
    28         /// <param name="remark">备注信息</param>
    29         public static void SaveExceptionLog(Exception ex, DateTime errorTime, string remark)
    30         {
    31             try
    32             {
    33                 ExceptionLog log = new ExceptionLog(ex.Message,
    34                 ex.Message,
    35                 ex.TargetSite == null ? string.Empty : ex.TargetSite.ToString(),
    36                 ex.StackTrace,
    37                 errorTime,
    38                 remark);
    39                 Logger.LogService.WriteLog(log);
    40             }
    41             catch
    42             {
    43                 return;
    44             }
    45         }
    46         /// <summary>
    47         /// 记录操作日志
    48         /// </summary>
    49         /// <param name="log">日志详细内容</param>
    50         public static void SaveOpetationLog(OperationLog log)
    51         {
    52             try
    53             {
    54                 Logger.LogService.WriteLog(log);
    55             }
    56             catch
    57             {
    58 
    59             }
    60         }
    61     }
    LogService

    7.结语

      如果上面讲解中没有列出的类或者方法可以到下载下面的附件

      

    8.提供源代码下载

    源代码下载

      

        

      

     

     

  • 相关阅读:
    FFmpeg 播放 RTSP/Webcam 流
    Kafka的工作原理及过程
    Zookeeper--典型应用场景解决方案
    Zookeeper--理论及客户端
    使用jasypt加密配置的时候,报错:DecryptionException: Unable to decrypt
    kubebuilder实战之六:构建部署运行
    kubebuilder实战之五:operator编码
    kubebuilder实战之四:operator需求说明和设计
    kubebuilder实战之三:基础知识速览
    kubebuilder实战之二:初次体验kubebuilder
  • 原文地址:https://www.cnblogs.com/liuxiaoji/p/4475405.html
Copyright © 2011-2022 走看看