context: // 
  // Copyright (c) 2004-2006 Jaroslaw Kowalski <jaak@jkowalski.net>
  // 
  // All rights reserved.
  // 
  // Redistribution and use in source and binary forms, with or without 
  // modification, are permitted provided that the following conditions 
  // are met:
  // 
  // * Redistributions of source code must retain the above copyright notice, 
  //   this list of conditions and the following disclaimer. 
  // 
  // * Redistributions in binary form must reproduce the above copyright notice,
  //   this list of conditions and the following disclaimer in the documentation
  //   and/or other materials provided with the distribution. 
  // 
  // * Neither the name of Jaroslaw Kowalski nor the names of its 
  //   contributors may be used to endorse or promote products derived from this
  //   software without specific prior written permission. 
  // 
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
  // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
  // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
  // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
  // THE POSSIBILITY OF SUCH DAMAGE.
  // 
  
  #if !NETCF
  
  using System;
  using System.IO;
  using System.Text;
  using System.Xml;
  using System.Reflection;
  using System.Diagnostics;
  
  using NLog.Internal;
  using System.Web;
  
  using NLog.Config;
  
  namespace NLog.Targets.Wrappers
  {
      /// <summary>
      /// A target that buffers log events for the duration of 
      /// the ASP.NET Request and sends them down to the wrapped target
      /// as soon as the request ends.
      /// </summary>
      /// <remarks>
      /// <p>
      /// Typically this target is used in cooperation with PostFilteringTargetWrapper
      /// to provide verbose logging for failing requests and normal or no logging for
      /// successful requests. We need to make the decision of the final filtering rule
      /// to apply after all logs for a page have been generated.
      /// </p>
      /// <p>
      /// To use this target, you need to add an entry in the httpModules section of
      /// web.config:
      /// </p>
      /// <code lang="XML">
      /// <![CDATA[<?xml version="1.0" ?>
      /// <configuration>
      ///   <system.web>
      ///     <httpModules>
      ///       <add name="NLog" type="NLog.Web.NLogHttpModule, NLog"/>
      ///     </httpModules>
      ///   </system.web>
      /// </configuration>
      /// ]]>
      /// </code>
      /// </remarks>
      /// <example>
      /// <p>To set up the ASP.NET Buffering target wrapper <a href="config.html">configuration file</a>, put
      /// the following in <c>web.nlog</c> file in your web application directory (this assumes
      /// that PostFilteringWrapper is used to provide the filtering and actual logs go to
      /// a file).
      /// </p>
      /// <code lang="XML" src="examples/targets/Configuration File/ASPNetBufferingWrapper/web.nlog" />
      /// <p>
      /// This assumes just one target and a single rule. More configuration
      /// options are described <a href="config.html">here</a>.
      /// </p>
      /// <p>
      /// To configure the target programmatically, put the following
      /// piece of code in your <c>Application_OnStart()</c> handler in Global.asax.cs 
      /// or some other place that gets executed at the very beginning of your code:
      /// </p>
      /// <code lang="C#" src="examples/targets/Configuration API/ASPNetBufferingWrapper/Global.asax.cs" />
      /// <p>
      /// Fully working C# project can be found in the <c>Examples/Targets/Configuration API/ASPNetBufferingWrapper</c>
      /// directory along with usage instructions.
      /// </p>
      /// </example>
      [Target("ASPNetBufferingWrapper", IgnoresLayout = true, IsWrapper = true)]
      [NotSupportedRuntime(Framework=RuntimeFramework.DotNetCompactFramework)]
      public class ASPNetBufferingTargetWrapper: WrapperTargetBase
      {
          private object _dataSlot = new object();
          private int _bufferSize = 100;
          private int _growLimit = 0;
          private bool _growBufferAsNeeded = true;
  
          /// <summary>
          /// Creates a new instance of the <see cref="ASPNetBufferingTargetWrapper"/> and initializes <see cref="BufferSize"/> to 100.
          /// </summary>
          public ASPNetBufferingTargetWrapper()
          {
              BufferSize = 100;
              GrowBufferAsNeeded = true;
          }
  
          /// <summary>
          /// Creates a new instance of the <see cref="ASPNetBufferingTargetWrapper"/>, initializes <see cref="BufferSize"/> to 100 and
          /// sets the <see cref="WrapperTargetBase.WrappedTarget"/> to the specified value.
          /// </summary>
          public ASPNetBufferingTargetWrapper(Target writeTo) : this(writeTo, 100)
          {
          }
  
          /// <summary>
          /// Creates a new instance of the <see cref="ASPNetBufferingTargetWrapper"/>, initializes <see cref="BufferSize"/> and
          /// the <see cref="WrapperTargetBase.WrappedTarget"/> to the specified values.
          /// </summary>
          public ASPNetBufferingTargetWrapper(Target writeTo, int bufferSize)
          {
              WrappedTarget = writeTo;
              BufferSize = bufferSize;
          }
  
          /// <summary>
          /// The number of log events to be buffered.
          /// </summary>
          [System.ComponentModel.DefaultValue(4000)]
          public int BufferSize
          {
              get { return _bufferSize; }
              set { _bufferSize = value; }
          }
  
          /// <summary>
          /// Grow the buffer when it gets full.
          /// </summary>
          /// <remarks>
          /// true causes the buffer to expand until <see cref="BufferGrowLimit" /> is hit,
          /// false causes the buffer to never expand and lose the earliest entries in case of overflow.
          /// </remarks>
          [System.ComponentModel.DefaultValue(false)]
          public bool GrowBufferAsNeeded
          {
              get { return _growBufferAsNeeded; }
              set { _growBufferAsNeeded = value; }
          }
  
          /// <summary>
          /// The maximum number of log events that the buffer can keep.
          /// </summary>
          public int BufferGrowLimit
          {
              get { return _growLimit; }
              set 
              {
                  _growLimit = value; 
                  GrowBufferAsNeeded = (value >= _bufferSize) ? true : false;
              }
          }
  
          /// <summary>
          /// Initializes the target by hooking up the NLogHttpModule BeginRequest and EndRequest events.
          /// </summary>
          public override void Initialize()
          {
              base.Initialize();
              NLog.Web.NLogHttpModule.BeginRequest += new EventHandler(this.OnBeginRequest);
              NLog.Web.NLogHttpModule.EndRequest += new EventHandler(this.OnEndRequest);
          }
  
          /// <summary>
          /// Adds the specified log event to the buffer.
          /// </summary>
          /// <param name="logEvent">The log event.</param>
          public override void Write(LogEventInfo logEvent)
          {
              WrappedTarget.PrecalculateVolatileLayouts(logEvent);
              LogEventInfoBuffer buffer = GetRequestBuffer();
              if (buffer != null)
              {
                  buffer.Append(logEvent);
              }
          }
  
          /// <summary>
          /// Closes the target by flushing pending events in the buffer (if any).
          /// </summary>
          public override void Close()
          {
              Flush(TimeSpan.FromSeconds(3));
              base.Close ();
          }
  
          private LogEventInfoBuffer GetRequestBuffer()
          {
              HttpContext context = HttpContext.Current;
              if (context == null)
                  return null;
              return context.Items[_dataSlot] as LogEventInfoBuffer;
          }
  
          private void OnBeginRequest(object sender, EventArgs args)
          {
              HttpContext context = HttpContext.Current;
              context.Items[_dataSlot] = new LogEventInfoBuffer(this.BufferSize, this.GrowBufferAsNeeded, this.BufferGrowLimit);
          }
  
          private void OnEndRequest(object sender, EventArgs args)
          {
              LogEventInfoBuffer buffer = GetRequestBuffer();
  
gt:             if (buffer != null)