AppenderAttachedImpl.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. #region Apache License
  2. //
  3. // Licensed to the Apache Software Foundation (ASF) under one or more
  4. // contributor license agreements. See the NOTICE file distributed with
  5. // this work for additional information regarding copyright ownership.
  6. // The ASF licenses this file to you under the Apache License, Version 2.0
  7. // (the "License"); you may not use this file except in compliance with
  8. // the License. You may obtain a copy of the License at
  9. //
  10. // http://www.apache.org/licenses/LICENSE-2.0
  11. //
  12. // Unless required by applicable law or agreed to in writing, software
  13. // distributed under the License is distributed on an "AS IS" BASIS,
  14. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. // See the License for the specific language governing permissions and
  16. // limitations under the License.
  17. //
  18. #endregion
  19. using System;
  20. using log4net.Core;
  21. using log4net.Appender;
  22. namespace log4net.Util
  23. {
  24. /// <summary>
  25. /// A straightforward implementation of the <see cref="IAppenderAttachable"/> interface.
  26. /// </summary>
  27. /// <remarks>
  28. /// <para>
  29. /// This is the default implementation of the <see cref="IAppenderAttachable"/>
  30. /// interface. Implementors of the <see cref="IAppenderAttachable"/> interface
  31. /// should aggregate an instance of this type.
  32. /// </para>
  33. /// </remarks>
  34. /// <author>Nicko Cadell</author>
  35. /// <author>Gert Driesen</author>
  36. public class AppenderAttachedImpl : IAppenderAttachable
  37. {
  38. #region Public Instance Constructors
  39. /// <summary>
  40. /// Constructor
  41. /// </summary>
  42. /// <remarks>
  43. /// <para>
  44. /// Initializes a new instance of the <see cref="AppenderAttachedImpl"/> class.
  45. /// </para>
  46. /// </remarks>
  47. public AppenderAttachedImpl()
  48. {
  49. }
  50. #endregion Public Instance Constructors
  51. #region Public Instance Methods
  52. /// <summary>
  53. /// Append on on all attached appenders.
  54. /// </summary>
  55. /// <param name="loggingEvent">The event being logged.</param>
  56. /// <returns>The number of appenders called.</returns>
  57. /// <remarks>
  58. /// <para>
  59. /// Calls the <see cref="IAppender.DoAppend" /> method on all
  60. /// attached appenders.
  61. /// </para>
  62. /// </remarks>
  63. public int AppendLoopOnAppenders(LoggingEvent loggingEvent)
  64. {
  65. if (loggingEvent == null)
  66. {
  67. throw new ArgumentNullException("loggingEvent");
  68. }
  69. // m_appenderList is null when empty
  70. if (m_appenderList == null)
  71. {
  72. return 0;
  73. }
  74. if (m_appenderArray == null)
  75. {
  76. m_appenderArray = m_appenderList.ToArray();
  77. }
  78. foreach(IAppender appender in m_appenderArray)
  79. {
  80. try
  81. {
  82. appender.DoAppend(loggingEvent);
  83. }
  84. catch(Exception ex)
  85. {
  86. LogLog.Error(declaringType, "Failed to append to appender [" + appender.Name + "]", ex);
  87. }
  88. }
  89. return m_appenderList.Count;
  90. }
  91. /// <summary>
  92. /// Append on on all attached appenders.
  93. /// </summary>
  94. /// <param name="loggingEvents">The array of events being logged.</param>
  95. /// <returns>The number of appenders called.</returns>
  96. /// <remarks>
  97. /// <para>
  98. /// Calls the <see cref="IAppender.DoAppend" /> method on all
  99. /// attached appenders.
  100. /// </para>
  101. /// </remarks>
  102. public int AppendLoopOnAppenders(LoggingEvent[] loggingEvents)
  103. {
  104. if (loggingEvents == null)
  105. {
  106. throw new ArgumentNullException("loggingEvents");
  107. }
  108. if (loggingEvents.Length == 0)
  109. {
  110. throw new ArgumentException("loggingEvents array must not be empty", "loggingEvents");
  111. }
  112. if (loggingEvents.Length == 1)
  113. {
  114. // Fall back to single event path
  115. return AppendLoopOnAppenders(loggingEvents[0]);
  116. }
  117. // m_appenderList is null when empty
  118. if (m_appenderList == null)
  119. {
  120. return 0;
  121. }
  122. if (m_appenderArray == null)
  123. {
  124. m_appenderArray = m_appenderList.ToArray();
  125. }
  126. foreach(IAppender appender in m_appenderArray)
  127. {
  128. try
  129. {
  130. CallAppend(appender, loggingEvents);
  131. }
  132. catch(Exception ex)
  133. {
  134. LogLog.Error(declaringType, "Failed to append to appender [" + appender.Name + "]", ex);
  135. }
  136. }
  137. return m_appenderList.Count;
  138. }
  139. #endregion Public Instance Methods
  140. #region Private Static Methods
  141. /// <summary>
  142. /// Calls the DoAppende method on the <see cref="IAppender"/> with
  143. /// the <see cref="LoggingEvent"/> objects supplied.
  144. /// </summary>
  145. /// <param name="appender">The appender</param>
  146. /// <param name="loggingEvents">The events</param>
  147. /// <remarks>
  148. /// <para>
  149. /// If the <paramref name="appender" /> supports the <see cref="IBulkAppender"/>
  150. /// interface then the <paramref name="loggingEvents" /> will be passed
  151. /// through using that interface. Otherwise the <see cref="LoggingEvent"/>
  152. /// objects in the array will be passed one at a time.
  153. /// </para>
  154. /// </remarks>
  155. private static void CallAppend(IAppender appender, LoggingEvent[] loggingEvents)
  156. {
  157. IBulkAppender bulkAppender = appender as IBulkAppender;
  158. if (bulkAppender != null)
  159. {
  160. bulkAppender.DoAppend(loggingEvents);
  161. }
  162. else
  163. {
  164. foreach(LoggingEvent loggingEvent in loggingEvents)
  165. {
  166. appender.DoAppend(loggingEvent);
  167. }
  168. }
  169. }
  170. #endregion
  171. #region Implementation of IAppenderAttachable
  172. /// <summary>
  173. /// Attaches an appender.
  174. /// </summary>
  175. /// <param name="newAppender">The appender to add.</param>
  176. /// <remarks>
  177. /// <para>
  178. /// If the appender is already in the list it won't be added again.
  179. /// </para>
  180. /// </remarks>
  181. public void AddAppender(IAppender newAppender)
  182. {
  183. // Null values for newAppender parameter are strictly forbidden.
  184. if (newAppender == null)
  185. {
  186. throw new ArgumentNullException("newAppender");
  187. }
  188. m_appenderArray = null;
  189. if (m_appenderList == null)
  190. {
  191. m_appenderList = new AppenderCollection(1);
  192. }
  193. if (!m_appenderList.Contains(newAppender))
  194. {
  195. m_appenderList.Add(newAppender);
  196. }
  197. }
  198. /// <summary>
  199. /// Gets all attached appenders.
  200. /// </summary>
  201. /// <returns>
  202. /// A collection of attached appenders, or <c>null</c> if there
  203. /// are no attached appenders.
  204. /// </returns>
  205. /// <remarks>
  206. /// <para>
  207. /// The read only collection of all currently attached appenders.
  208. /// </para>
  209. /// </remarks>
  210. public AppenderCollection Appenders
  211. {
  212. get
  213. {
  214. if (m_appenderList == null)
  215. {
  216. // We must always return a valid collection
  217. return AppenderCollection.EmptyCollection;
  218. }
  219. else
  220. {
  221. return AppenderCollection.ReadOnly(m_appenderList);
  222. }
  223. }
  224. }
  225. /// <summary>
  226. /// Gets an attached appender with the specified name.
  227. /// </summary>
  228. /// <param name="name">The name of the appender to get.</param>
  229. /// <returns>
  230. /// The appender with the name specified, or <c>null</c> if no appender with the
  231. /// specified name is found.
  232. /// </returns>
  233. /// <remarks>
  234. /// <para>
  235. /// Lookup an attached appender by name.
  236. /// </para>
  237. /// </remarks>
  238. public IAppender GetAppender(string name)
  239. {
  240. if (m_appenderList != null && name != null)
  241. {
  242. foreach(IAppender appender in m_appenderList)
  243. {
  244. if (name == appender.Name)
  245. {
  246. return appender;
  247. }
  248. }
  249. }
  250. return null;
  251. }
  252. /// <summary>
  253. /// Removes all attached appenders.
  254. /// </summary>
  255. /// <remarks>
  256. /// <para>
  257. /// Removes and closes all attached appenders
  258. /// </para>
  259. /// </remarks>
  260. public void RemoveAllAppenders()
  261. {
  262. if (m_appenderList != null)
  263. {
  264. foreach(IAppender appender in m_appenderList)
  265. {
  266. try
  267. {
  268. appender.Close();
  269. }
  270. catch(Exception ex)
  271. {
  272. LogLog.Error(declaringType, "Failed to Close appender ["+appender.Name+"]", ex);
  273. }
  274. }
  275. m_appenderList = null;
  276. m_appenderArray = null;
  277. }
  278. }
  279. /// <summary>
  280. /// Removes the specified appender from the list of attached appenders.
  281. /// </summary>
  282. /// <param name="appender">The appender to remove.</param>
  283. /// <returns>The appender removed from the list</returns>
  284. /// <remarks>
  285. /// <para>
  286. /// The appender removed is not closed.
  287. /// If you are discarding the appender you must call
  288. /// <see cref="IAppender.Close"/> on the appender removed.
  289. /// </para>
  290. /// </remarks>
  291. public IAppender RemoveAppender(IAppender appender)
  292. {
  293. if (appender != null && m_appenderList != null)
  294. {
  295. m_appenderList.Remove(appender);
  296. if (m_appenderList.Count == 0)
  297. {
  298. m_appenderList = null;
  299. }
  300. m_appenderArray = null;
  301. }
  302. return appender;
  303. }
  304. /// <summary>
  305. /// Removes the appender with the specified name from the list of appenders.
  306. /// </summary>
  307. /// <param name="name">The name of the appender to remove.</param>
  308. /// <returns>The appender removed from the list</returns>
  309. /// <remarks>
  310. /// <para>
  311. /// The appender removed is not closed.
  312. /// If you are discarding the appender you must call
  313. /// <see cref="IAppender.Close"/> on the appender removed.
  314. /// </para>
  315. /// </remarks>
  316. public IAppender RemoveAppender(string name)
  317. {
  318. return RemoveAppender(GetAppender(name));
  319. }
  320. #endregion
  321. #region Private Instance Fields
  322. /// <summary>
  323. /// List of appenders
  324. /// </summary>
  325. private AppenderCollection m_appenderList;
  326. /// <summary>
  327. /// Array of appenders, used to cache the m_appenderList
  328. /// </summary>
  329. private IAppender[] m_appenderArray;
  330. #endregion Private Instance Fields
  331. #region Private Static Fields
  332. /// <summary>
  333. /// The fully qualified type of the AppenderAttachedImpl class.
  334. /// </summary>
  335. /// <remarks>
  336. /// Used by the internal logger to record the Type of the
  337. /// log message.
  338. /// </remarks>
  339. private readonly static Type declaringType = typeof(AppenderAttachedImpl);
  340. #endregion Private Static Fields
  341. }
  342. }