LogWriter.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics.CodeAnalysis;
  4. namespace Wayne.Lib.Log
  5. {
  6. /// <summary>
  7. /// The abstract base class for a LogWriter.
  8. /// </summary>
  9. internal abstract class LogWriter : IDisposable
  10. {
  11. #region Fields
  12. private string logName;
  13. private object dataLock = new object();
  14. private Dictionary<EntityCategory, DebugLogLevel> debugLogLevelDict = new Dictionary<EntityCategory, DebugLogLevel>();
  15. private bool disposed;
  16. #endregion
  17. #region Construction
  18. /// <summary>
  19. /// Protected constructor.
  20. /// </summary>
  21. /// <param name="logName"></param>
  22. protected LogWriter(string logName)
  23. {
  24. this.logName = logName;
  25. }
  26. /// <summary>
  27. /// Finalizer.
  28. /// </summary>
  29. ~LogWriter()
  30. {
  31. Dispose(false, "Shutting down.");
  32. }
  33. #endregion
  34. #region IDisposable Members
  35. /// <summary>
  36. /// Disposes the instance of LogWriter.
  37. /// </summary>
  38. [SuppressMessage("Microsoft.Usage", "CA1816:CallGCSuppressFinalizeCorrectly")]
  39. public void Dispose()
  40. {
  41. Dispose("Shutting down.");
  42. }
  43. /// <summary>
  44. /// Disposes the instance of LogWriter.
  45. /// </summary>
  46. [SuppressMessage("Microsoft.Usage", "CA1816:CallGCSuppressFinalizeCorrectly")]
  47. public void Dispose(string reason)
  48. {
  49. Dispose(true, reason);
  50. GC.SuppressFinalize(this);
  51. disposed = true;
  52. }
  53. /// <summary>
  54. /// Internal dispose method that is called either by the public Dispose method or the finalizer.
  55. /// </summary>
  56. /// <param name="disposing"></param>
  57. /// <param name="reason"></param>
  58. protected abstract void Dispose(bool disposing, string reason);
  59. #endregion
  60. #region Properties
  61. /// <summary>
  62. /// Log name that identifies this log writer.
  63. /// </summary>
  64. [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
  65. public string LogName
  66. {
  67. get { return logName; }
  68. }
  69. ///// <summary>
  70. ///// The number of character each lines is indented with as default.
  71. ///// </summary>
  72. //public abstract int IndentLength { get;}
  73. #endregion
  74. #region Virtual Methods
  75. public abstract void PerformWrite(LogEntry logEntry);
  76. #endregion
  77. #region Internal Methods
  78. /// <summary>
  79. /// Writes the LogEntry to the log.
  80. /// </summary>
  81. /// <param name="logEntry"></param>
  82. internal void Write(LogEntry logEntry)
  83. {
  84. if (disposed)
  85. return;
  86. bool doPerformWrite;
  87. DebugLogEntry debugLogEntry = logEntry as DebugLogEntry;
  88. EventLogEntry eventLogEntry = logEntry as EventLogEntry;
  89. if (debugLogEntry != null)
  90. {
  91. if (debugLogEntry.LogLevel == DebugLogLevel.Excluded)
  92. return;
  93. DebugLogLevel level = GetDebugLogLevel(debugLogEntry.EntityCategory);
  94. doPerformWrite = (level >= debugLogEntry.LogLevel);
  95. }
  96. else if (eventLogEntry != null)
  97. {
  98. if (eventLogEntry.LogLevel == DebugLogLevel.Excluded)
  99. return;
  100. DebugLogLevel level = GetDebugLogLevel(eventLogEntry.EntityCategory);
  101. doPerformWrite = (level >= eventLogEntry.LogLevel);
  102. }
  103. else
  104. doPerformWrite = true;
  105. if (doPerformWrite)
  106. {
  107. // Call the abstract method that is overriden by the descendant classes.
  108. PerformWrite(logEntry);
  109. }
  110. }
  111. /// <summary>
  112. /// Cache the filter data for the given EntityCategory.
  113. /// </summary>
  114. /// <param name="entityCategory"></param>
  115. /// <param name="logLevel"></param>
  116. internal void CacheFilterData(EntityCategory entityCategory,
  117. DebugLogLevel logLevel)
  118. {
  119. // Cache the log level.
  120. lock (dataLock)
  121. {
  122. DebugLogLevel currentDebugLogLevel;
  123. if (debugLogLevelDict.TryGetValue(entityCategory, out currentDebugLogLevel))
  124. debugLogLevelDict[entityCategory] = DebugLogger.MaxDebugLogLevel(currentDebugLogLevel, logLevel);
  125. else
  126. debugLogLevelDict.Add(entityCategory, logLevel);
  127. }
  128. }
  129. internal virtual void PerformListCleaning(DateTime oldestAllowedTouch)
  130. {
  131. #region Clean the logwriterPreparedDict.
  132. lock (dataLock)
  133. {
  134. List<EntityCategory> entityCategoriesToRemove = new List<EntityCategory>();
  135. foreach (EntityCategory entityCategory in debugLogLevelDict.Keys)
  136. {
  137. if (entityCategory.LastTouched < oldestAllowedTouch)
  138. entityCategoriesToRemove.Add(entityCategory);
  139. }
  140. //Remove from the list.
  141. foreach (EntityCategory entityCategoryToRemove in entityCategoriesToRemove)
  142. {
  143. debugLogLevelDict.Remove(entityCategoryToRemove);
  144. }
  145. }
  146. #endregion
  147. }
  148. internal void RemoveEntity(IIdentifiableEntity entity)
  149. {
  150. lock (dataLock)
  151. {
  152. List<EntityCategory> entityCategoriesToRemove = new List<EntityCategory>();
  153. foreach (EntityCategory entityCategory in debugLogLevelDict.Keys)
  154. {
  155. if (IdentifiableEntity.Equals(entityCategory.Entity, entity))
  156. entityCategoriesToRemove.Add(entityCategory);
  157. }
  158. //Remove from the list.
  159. foreach (EntityCategory entityCategoryToRemove in entityCategoriesToRemove)
  160. {
  161. debugLogLevelDict.Remove(entityCategoryToRemove);
  162. }
  163. }
  164. }
  165. #endregion
  166. #region Protected Methods
  167. /// <summary>
  168. /// Get the debug level for the given EntityCategory.
  169. /// </summary>
  170. /// <param name="entityCategory"></param>
  171. /// <returns></returns>
  172. public DebugLogLevel GetDebugLogLevel(EntityCategory entityCategory)
  173. {
  174. if (disposed)
  175. return DebugLogLevel.Excluded;
  176. else if (entityCategory != null)
  177. {
  178. lock (dataLock)
  179. {
  180. DebugLogLevel debugLevel;
  181. if (debugLogLevelDict.TryGetValue(entityCategory, out debugLevel))
  182. return debugLevel;
  183. }
  184. }
  185. return DebugLogLevel.Normal;
  186. }
  187. #endregion
  188. }
  189. }