BufferingAppenderSkeleton.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  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 System.Collections;
  21. using log4net.Util;
  22. using log4net.Core;
  23. namespace log4net.Appender
  24. {
  25. /// <summary>
  26. /// Abstract base class implementation of <see cref="IAppender"/> that
  27. /// buffers events in a fixed size buffer.
  28. /// </summary>
  29. /// <remarks>
  30. /// <para>
  31. /// This base class should be used by appenders that need to buffer a
  32. /// number of events before logging them. For example the <see cref="AdoNetAppender"/>
  33. /// buffers events and then submits the entire contents of the buffer to
  34. /// the underlying database in one go.
  35. /// </para>
  36. /// <para>
  37. /// Subclasses should override the <see cref="M:SendBuffer(LoggingEvent[])"/>
  38. /// method to deliver the buffered events.
  39. /// </para>
  40. /// <para>The BufferingAppenderSkeleton maintains a fixed size cyclic
  41. /// buffer of events. The size of the buffer is set using
  42. /// the <see cref="BufferSize"/> property.
  43. /// </para>
  44. /// <para>A <see cref="ITriggeringEventEvaluator"/> is used to inspect
  45. /// each event as it arrives in the appender. If the <see cref="Evaluator"/>
  46. /// triggers, then the current buffer is sent immediately
  47. /// (see <see cref="M:SendBuffer(LoggingEvent[])"/>). Otherwise the event
  48. /// is stored in the buffer. For example, an evaluator can be used to
  49. /// deliver the events immediately when an ERROR event arrives.
  50. /// </para>
  51. /// <para>
  52. /// The buffering appender can be configured in a <see cref="Lossy"/> mode.
  53. /// By default the appender is NOT lossy. When the buffer is full all
  54. /// the buffered events are sent with <see cref="M:SendBuffer(LoggingEvent[])"/>.
  55. /// If the <see cref="Lossy"/> property is set to <c>true</c> then the
  56. /// buffer will not be sent when it is full, and new events arriving
  57. /// in the appender will overwrite the oldest event in the buffer.
  58. /// In lossy mode the buffer will only be sent when the <see cref="Evaluator"/>
  59. /// triggers. This can be useful behavior when you need to know about
  60. /// ERROR events but not about events with a lower level, configure an
  61. /// evaluator that will trigger when an ERROR event arrives, the whole
  62. /// buffer will be sent which gives a history of events leading up to
  63. /// the ERROR event.
  64. /// </para>
  65. /// </remarks>
  66. /// <author>Nicko Cadell</author>
  67. /// <author>Gert Driesen</author>
  68. public abstract class BufferingAppenderSkeleton : AppenderSkeleton
  69. {
  70. #region Protected Instance Constructors
  71. /// <summary>
  72. /// Initializes a new instance of the <see cref="BufferingAppenderSkeleton" /> class.
  73. /// </summary>
  74. /// <remarks>
  75. /// <para>
  76. /// Protected default constructor to allow subclassing.
  77. /// </para>
  78. /// </remarks>
  79. protected BufferingAppenderSkeleton() : this(true)
  80. {
  81. }
  82. /// <summary>
  83. /// Initializes a new instance of the <see cref="BufferingAppenderSkeleton" /> class.
  84. /// </summary>
  85. /// <param name="eventMustBeFixed">the events passed through this appender must be
  86. /// fixed by the time that they arrive in the derived class' <c>SendBuffer</c> method.</param>
  87. /// <remarks>
  88. /// <para>
  89. /// Protected constructor to allow subclassing.
  90. /// </para>
  91. /// <para>
  92. /// The <paramref name="eventMustBeFixed"/> should be set if the subclass
  93. /// expects the events delivered to be fixed even if the
  94. /// <see cref="BufferSize"/> is set to zero, i.e. when no buffering occurs.
  95. /// </para>
  96. /// </remarks>
  97. protected BufferingAppenderSkeleton(bool eventMustBeFixed) : base()
  98. {
  99. m_eventMustBeFixed = eventMustBeFixed;
  100. }
  101. #endregion Protected Instance Constructors
  102. #region Public Instance Properties
  103. /// <summary>
  104. /// Gets or sets a value that indicates whether the appender is lossy.
  105. /// </summary>
  106. /// <value>
  107. /// <c>true</c> if the appender is lossy, otherwise <c>false</c>. The default is <c>false</c>.
  108. /// </value>
  109. /// <remarks>
  110. /// <para>
  111. /// This appender uses a buffer to store logging events before
  112. /// delivering them. A triggering event causes the whole buffer
  113. /// to be send to the remote sink. If the buffer overruns before
  114. /// a triggering event then logging events could be lost. Set
  115. /// <see cref="Lossy"/> to <c>false</c> to prevent logging events
  116. /// from being lost.
  117. /// </para>
  118. /// <para>If <see cref="Lossy"/> is set to <c>true</c> then an
  119. /// <see cref="Evaluator"/> must be specified.</para>
  120. /// </remarks>
  121. public bool Lossy
  122. {
  123. get { return m_lossy; }
  124. set { m_lossy = value; }
  125. }
  126. /// <summary>
  127. /// Gets or sets the size of the cyclic buffer used to hold the
  128. /// logging events.
  129. /// </summary>
  130. /// <value>
  131. /// The size of the cyclic buffer used to hold the logging events.
  132. /// </value>
  133. /// <remarks>
  134. /// <para>
  135. /// The <see cref="BufferSize"/> option takes a positive integer
  136. /// representing the maximum number of logging events to collect in
  137. /// a cyclic buffer. When the <see cref="BufferSize"/> is reached,
  138. /// oldest events are deleted as new events are added to the
  139. /// buffer. By default the size of the cyclic buffer is 512 events.
  140. /// </para>
  141. /// <para>
  142. /// If the <see cref="BufferSize"/> is set to a value less than
  143. /// or equal to 1 then no buffering will occur. The logging event
  144. /// will be delivered synchronously (depending on the <see cref="Lossy"/>
  145. /// and <see cref="Evaluator"/> properties). Otherwise the event will
  146. /// be buffered.
  147. /// </para>
  148. /// </remarks>
  149. public int BufferSize
  150. {
  151. get { return m_bufferSize; }
  152. set { m_bufferSize = value; }
  153. }
  154. /// <summary>
  155. /// Gets or sets the <see cref="ITriggeringEventEvaluator"/> that causes the
  156. /// buffer to be sent immediately.
  157. /// </summary>
  158. /// <value>
  159. /// The <see cref="ITriggeringEventEvaluator"/> that causes the buffer to be
  160. /// sent immediately.
  161. /// </value>
  162. /// <remarks>
  163. /// <para>
  164. /// The evaluator will be called for each event that is appended to this
  165. /// appender. If the evaluator triggers then the current buffer will
  166. /// immediately be sent (see <see cref="M:SendBuffer(LoggingEvent[])"/>).
  167. /// </para>
  168. /// <para>If <see cref="Lossy"/> is set to <c>true</c> then an
  169. /// <see cref="Evaluator"/> must be specified.</para>
  170. /// </remarks>
  171. public ITriggeringEventEvaluator Evaluator
  172. {
  173. get { return m_evaluator; }
  174. set { m_evaluator = value; }
  175. }
  176. /// <summary>
  177. /// Gets or sets the value of the <see cref="ITriggeringEventEvaluator"/> to use.
  178. /// </summary>
  179. /// <value>
  180. /// The value of the <see cref="ITriggeringEventEvaluator"/> to use.
  181. /// </value>
  182. /// <remarks>
  183. /// <para>
  184. /// The evaluator will be called for each event that is discarded from this
  185. /// appender. If the evaluator triggers then the current buffer will immediately
  186. /// be sent (see <see cref="M:SendBuffer(LoggingEvent[])"/>).
  187. /// </para>
  188. /// </remarks>
  189. public ITriggeringEventEvaluator LossyEvaluator
  190. {
  191. get { return m_lossyEvaluator; }
  192. set { m_lossyEvaluator = value; }
  193. }
  194. /// <summary>
  195. /// Gets or sets a value indicating if only part of the logging event data
  196. /// should be fixed.
  197. /// </summary>
  198. /// <value>
  199. /// <c>true</c> if the appender should only fix part of the logging event
  200. /// data, otherwise <c>false</c>. The default is <c>false</c>.
  201. /// </value>
  202. /// <remarks>
  203. /// <para>
  204. /// Setting this property to <c>true</c> will cause only part of the
  205. /// event data to be fixed and serialized. This will improve performance.
  206. /// </para>
  207. /// <para>
  208. /// See <see cref="M:LoggingEvent.FixVolatileData(FixFlags)"/> for more information.
  209. /// </para>
  210. /// </remarks>
  211. [Obsolete("Use Fix property")]
  212. virtual public bool OnlyFixPartialEventData
  213. {
  214. get { return (Fix == FixFlags.Partial); }
  215. set
  216. {
  217. if (value)
  218. {
  219. Fix = FixFlags.Partial;
  220. }
  221. else
  222. {
  223. Fix = FixFlags.All;
  224. }
  225. }
  226. }
  227. /// <summary>
  228. /// Gets or sets a the fields that will be fixed in the event
  229. /// </summary>
  230. /// <value>
  231. /// The event fields that will be fixed before the event is buffered
  232. /// </value>
  233. /// <remarks>
  234. /// <para>
  235. /// The logging event needs to have certain thread specific values
  236. /// captured before it can be buffered. See <see cref="LoggingEvent.Fix"/>
  237. /// for details.
  238. /// </para>
  239. /// </remarks>
  240. /// <seealso cref="LoggingEvent.Fix"/>
  241. virtual public FixFlags Fix
  242. {
  243. get { return m_fixFlags; }
  244. set { m_fixFlags = value; }
  245. }
  246. #endregion Public Instance Properties
  247. #region Public Methods
  248. /// <summary>
  249. /// Flushes any buffered log data.
  250. /// </summary>
  251. /// <param name="millisecondsTimeout">The maximum time to wait for logging events to be flushed.</param>
  252. /// <returns><c>True</c> if all logging events were flushed successfully, else <c>false</c>.</returns>
  253. public override bool Flush(int millisecondsTimeout)
  254. {
  255. Flush();
  256. return true;
  257. }
  258. /// <summary>
  259. /// Flush the currently buffered events
  260. /// </summary>
  261. /// <remarks>
  262. /// <para>
  263. /// Flushes any events that have been buffered.
  264. /// </para>
  265. /// <para>
  266. /// If the appender is buffering in <see cref="Lossy"/> mode then the contents
  267. /// of the buffer will NOT be flushed to the appender.
  268. /// </para>
  269. /// </remarks>
  270. public virtual void Flush()
  271. {
  272. Flush(false);
  273. }
  274. /// <summary>
  275. /// Flush the currently buffered events
  276. /// </summary>
  277. /// <param name="flushLossyBuffer">set to <c>true</c> to flush the buffer of lossy events</param>
  278. /// <remarks>
  279. /// <para>
  280. /// Flushes events that have been buffered. If <paramref name="flushLossyBuffer" /> is
  281. /// <c>false</c> then events will only be flushed if this buffer is non-lossy mode.
  282. /// </para>
  283. /// <para>
  284. /// If the appender is buffering in <see cref="Lossy"/> mode then the contents
  285. /// of the buffer will only be flushed if <paramref name="flushLossyBuffer" /> is <c>true</c>.
  286. /// In this case the contents of the buffer will be tested against the
  287. /// <see cref="LossyEvaluator"/> and if triggering will be output. All other buffered
  288. /// events will be discarded.
  289. /// </para>
  290. /// <para>
  291. /// If <paramref name="flushLossyBuffer" /> is <c>true</c> then the buffer will always
  292. /// be emptied by calling this method.
  293. /// </para>
  294. /// </remarks>
  295. public virtual void Flush(bool flushLossyBuffer)
  296. {
  297. // This method will be called outside of the AppenderSkeleton DoAppend() method
  298. // therefore it needs to be protected by its own lock. This will block any
  299. // Appends while the buffer is flushed.
  300. lock(this)
  301. {
  302. if (m_cb != null && m_cb.Length > 0)
  303. {
  304. if (m_lossy)
  305. {
  306. // If we are allowed to eagerly flush from the lossy buffer
  307. if (flushLossyBuffer)
  308. {
  309. if (m_lossyEvaluator != null)
  310. {
  311. // Test the contents of the buffer against the lossy evaluator
  312. LoggingEvent[] bufferedEvents = m_cb.PopAll();
  313. ArrayList filteredEvents = new ArrayList(bufferedEvents.Length);
  314. foreach(LoggingEvent loggingEvent in bufferedEvents)
  315. {
  316. if (m_lossyEvaluator.IsTriggeringEvent(loggingEvent))
  317. {
  318. filteredEvents.Add(loggingEvent);
  319. }
  320. }
  321. // Send the events that meet the lossy evaluator criteria
  322. if (filteredEvents.Count > 0)
  323. {
  324. SendBuffer((LoggingEvent[])filteredEvents.ToArray(typeof(LoggingEvent)));
  325. }
  326. }
  327. else
  328. {
  329. // No lossy evaluator, all buffered events are discarded
  330. m_cb.Clear();
  331. }
  332. }
  333. }
  334. else
  335. {
  336. // Not lossy, send whole buffer
  337. SendFromBuffer(null, m_cb);
  338. }
  339. }
  340. }
  341. }
  342. #endregion Public Methods
  343. #region Implementation of IOptionHandler
  344. /// <summary>
  345. /// Initialize the appender based on the options set
  346. /// </summary>
  347. /// <remarks>
  348. /// <para>
  349. /// This is part of the <see cref="IOptionHandler"/> delayed object
  350. /// activation scheme. The <see cref="ActivateOptions"/> method must
  351. /// be called on this object after the configuration properties have
  352. /// been set. Until <see cref="ActivateOptions"/> is called this
  353. /// object is in an undefined state and must not be used.
  354. /// </para>
  355. /// <para>
  356. /// If any of the configuration properties are modified then
  357. /// <see cref="ActivateOptions"/> must be called again.
  358. /// </para>
  359. /// </remarks>
  360. override public void ActivateOptions()
  361. {
  362. base.ActivateOptions();
  363. // If the appender is in Lossy mode then we will
  364. // only send the buffer when the Evaluator triggers
  365. // therefore check we have an evaluator.
  366. if (m_lossy && m_evaluator == null)
  367. {
  368. ErrorHandler.Error("Appender ["+Name+"] is Lossy but has no Evaluator. The buffer will never be sent!");
  369. }
  370. if (m_bufferSize > 1)
  371. {
  372. m_cb = new CyclicBuffer(m_bufferSize);
  373. }
  374. else
  375. {
  376. m_cb = null;
  377. }
  378. }
  379. #endregion Implementation of IOptionHandler
  380. #region Override implementation of AppenderSkeleton
  381. /// <summary>
  382. /// Close this appender instance.
  383. /// </summary>
  384. /// <remarks>
  385. /// <para>
  386. /// Close this appender instance. If this appender is marked
  387. /// as not <see cref="Lossy"/> then the remaining events in
  388. /// the buffer must be sent when the appender is closed.
  389. /// </para>
  390. /// </remarks>
  391. override protected void OnClose()
  392. {
  393. // Flush the buffer on close
  394. Flush(true);
  395. }
  396. /// <summary>
  397. /// This method is called by the <see cref="M:AppenderSkeleton.DoAppend(LoggingEvent)"/> method.
  398. /// </summary>
  399. /// <param name="loggingEvent">the event to log</param>
  400. /// <remarks>
  401. /// <para>
  402. /// Stores the <paramref name="loggingEvent"/> in the cyclic buffer.
  403. /// </para>
  404. /// <para>
  405. /// The buffer will be sent (i.e. passed to the <see cref="SendBuffer"/>
  406. /// method) if one of the following conditions is met:
  407. /// </para>
  408. /// <list type="bullet">
  409. /// <item>
  410. /// <description>The cyclic buffer is full and this appender is
  411. /// marked as not lossy (see <see cref="Lossy"/>)</description>
  412. /// </item>
  413. /// <item>
  414. /// <description>An <see cref="Evaluator"/> is set and
  415. /// it is triggered for the <paramref name="loggingEvent"/>
  416. /// specified.</description>
  417. /// </item>
  418. /// </list>
  419. /// <para>
  420. /// Before the event is stored in the buffer it is fixed
  421. /// (see <see cref="M:LoggingEvent.FixVolatileData(FixFlags)"/>) to ensure that
  422. /// any data referenced by the event will be valid when the buffer
  423. /// is processed.
  424. /// </para>
  425. /// </remarks>
  426. override protected void Append(LoggingEvent loggingEvent)
  427. {
  428. // If the buffer size is set to 1 or less then the buffer will be
  429. // sent immediately because there is not enough space in the buffer
  430. // to buffer up more than 1 event. Therefore as a special case
  431. // we don't use the buffer at all.
  432. if (m_cb == null || m_bufferSize <= 1)
  433. {
  434. // Only send the event if we are in non lossy mode or the event is a triggering event
  435. if ((!m_lossy) ||
  436. (m_evaluator != null && m_evaluator.IsTriggeringEvent(loggingEvent)) ||
  437. (m_lossyEvaluator != null && m_lossyEvaluator.IsTriggeringEvent(loggingEvent)))
  438. {
  439. if (m_eventMustBeFixed)
  440. {
  441. // Derive class expects fixed events
  442. loggingEvent.Fix = this.Fix;
  443. }
  444. // Not buffering events, send immediately
  445. SendBuffer(new LoggingEvent[] { loggingEvent } );
  446. }
  447. }
  448. else
  449. {
  450. // Because we are caching the LoggingEvent beyond the
  451. // lifetime of the Append() method we must fix any
  452. // volatile data in the event.
  453. loggingEvent.Fix = this.Fix;
  454. // Add to the buffer, returns the event discarded from the buffer if there is no space remaining after the append
  455. LoggingEvent discardedLoggingEvent = m_cb.Append(loggingEvent);
  456. if (discardedLoggingEvent != null)
  457. {
  458. // Buffer is full and has had to discard an event
  459. if (!m_lossy)
  460. {
  461. // Not lossy, must send all events
  462. SendFromBuffer(discardedLoggingEvent, m_cb);
  463. }
  464. else
  465. {
  466. // Check if the discarded event should not be logged
  467. if (m_lossyEvaluator == null || !m_lossyEvaluator.IsTriggeringEvent(discardedLoggingEvent))
  468. {
  469. // Clear the discarded event as we should not forward it
  470. discardedLoggingEvent = null;
  471. }
  472. // Check if the event should trigger the whole buffer to be sent
  473. if (m_evaluator != null && m_evaluator.IsTriggeringEvent(loggingEvent))
  474. {
  475. SendFromBuffer(discardedLoggingEvent, m_cb);
  476. }
  477. else if (discardedLoggingEvent != null)
  478. {
  479. // Just send the discarded event
  480. SendBuffer(new LoggingEvent[] { discardedLoggingEvent } );
  481. }
  482. }
  483. }
  484. else
  485. {
  486. // Buffer is not yet full
  487. // Check if the event should trigger the whole buffer to be sent
  488. if (m_evaluator != null && m_evaluator.IsTriggeringEvent(loggingEvent))
  489. {
  490. SendFromBuffer(null, m_cb);
  491. }
  492. }
  493. }
  494. }
  495. #endregion Override implementation of AppenderSkeleton
  496. #region Protected Instance Methods
  497. /// <summary>
  498. /// Sends the contents of the buffer.
  499. /// </summary>
  500. /// <param name="firstLoggingEvent">The first logging event.</param>
  501. /// <param name="buffer">The buffer containing the events that need to be send.</param>
  502. /// <remarks>
  503. /// <para>
  504. /// The subclass must override <see cref="M:SendBuffer(LoggingEvent[])"/>.
  505. /// </para>
  506. /// </remarks>
  507. virtual protected void SendFromBuffer(LoggingEvent firstLoggingEvent, CyclicBuffer buffer)
  508. {
  509. LoggingEvent[] bufferEvents = buffer.PopAll();
  510. if (firstLoggingEvent == null)
  511. {
  512. SendBuffer(bufferEvents);
  513. }
  514. else if (bufferEvents.Length == 0)
  515. {
  516. SendBuffer(new LoggingEvent[] { firstLoggingEvent } );
  517. }
  518. else
  519. {
  520. // Create new array with the firstLoggingEvent at the head
  521. LoggingEvent[] events = new LoggingEvent[bufferEvents.Length + 1];
  522. Array.Copy(bufferEvents, 0, events, 1, bufferEvents.Length);
  523. events[0] = firstLoggingEvent;
  524. SendBuffer(events);
  525. }
  526. }
  527. #endregion Protected Instance Methods
  528. /// <summary>
  529. /// Sends the events.
  530. /// </summary>
  531. /// <param name="events">The events that need to be send.</param>
  532. /// <remarks>
  533. /// <para>
  534. /// The subclass must override this method to process the buffered events.
  535. /// </para>
  536. /// </remarks>
  537. abstract protected void SendBuffer(LoggingEvent[] events);
  538. #region Private Static Fields
  539. /// <summary>
  540. /// The default buffer size.
  541. /// </summary>
  542. /// <remarks>
  543. /// The default size of the cyclic buffer used to store events.
  544. /// This is set to 512 by default.
  545. /// </remarks>
  546. private const int DEFAULT_BUFFER_SIZE = 512;
  547. #endregion Private Static Fields
  548. #region Private Instance Fields
  549. /// <summary>
  550. /// The size of the cyclic buffer used to hold the logging events.
  551. /// </summary>
  552. /// <remarks>
  553. /// Set to <see cref="DEFAULT_BUFFER_SIZE"/> by default.
  554. /// </remarks>
  555. private int m_bufferSize = DEFAULT_BUFFER_SIZE;
  556. /// <summary>
  557. /// The cyclic buffer used to store the logging events.
  558. /// </summary>
  559. private CyclicBuffer m_cb;
  560. /// <summary>
  561. /// The triggering event evaluator that causes the buffer to be sent immediately.
  562. /// </summary>
  563. /// <remarks>
  564. /// The object that is used to determine if an event causes the entire
  565. /// buffer to be sent immediately. This field can be <c>null</c>, which
  566. /// indicates that event triggering is not to be done. The evaluator
  567. /// can be set using the <see cref="Evaluator"/> property. If this appender
  568. /// has the <see cref="m_lossy"/> (<see cref="Lossy"/> property) set to
  569. /// <c>true</c> then an <see cref="Evaluator"/> must be set.
  570. /// </remarks>
  571. private ITriggeringEventEvaluator m_evaluator;
  572. /// <summary>
  573. /// Indicates if the appender should overwrite events in the cyclic buffer
  574. /// when it becomes full, or if the buffer should be flushed when the
  575. /// buffer is full.
  576. /// </summary>
  577. /// <remarks>
  578. /// If this field is set to <c>true</c> then an <see cref="Evaluator"/> must
  579. /// be set.
  580. /// </remarks>
  581. private bool m_lossy = false;
  582. /// <summary>
  583. /// The triggering event evaluator filters discarded events.
  584. /// </summary>
  585. /// <remarks>
  586. /// The object that is used to determine if an event that is discarded should
  587. /// really be discarded or if it should be sent to the appenders.
  588. /// This field can be <c>null</c>, which indicates that all discarded events will
  589. /// be discarded.
  590. /// </remarks>
  591. private ITriggeringEventEvaluator m_lossyEvaluator;
  592. /// <summary>
  593. /// Value indicating which fields in the event should be fixed
  594. /// </summary>
  595. /// <remarks>
  596. /// By default all fields are fixed
  597. /// </remarks>
  598. private FixFlags m_fixFlags = FixFlags.All;
  599. /// <summary>
  600. /// The events delivered to the subclass must be fixed.
  601. /// </summary>
  602. private readonly bool m_eventMustBeFixed;
  603. #endregion Private Instance Fields
  604. }
  605. }