日志记录器

项目名称 : 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.提供源代码下载

源代码下载

  

    

  

 

 

 

 

posted @ 2015-05-04 20:36  刘小吉  阅读(1294)  评论(0编辑  收藏  举报