/// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="host">Hostname to log to.</param>
 /// <param name="port">Port on remote host.</param>
 /// <param name="policy">An object embodying a reconnection policy for if the 
 /// TCP session drops (defaults to ExponentialBackoffTcpConnectionPolicy).</param>
 /// <param name="maxQueueSize">The maximum number of events to queue if the 
 /// TCP session goes down. If more events are queued, old ones will be dropped
 /// (defaults to 10,000).</param>
 /// <param name="progress">An IProgress instance that will be triggered when
 /// an event is pulled from the queue and written to the TCP port (defaults to a new
 /// Progress object accessible via the Progress property).</param>
 public TcpTraceListener(string host, int port, ITcpReconnectionPolicy policy,
                         int maxQueueSize = 10000)
     : this(host.HostnameToIPAddress(), port, policy, maxQueueSize)
 {
 }
        /// <summary>
        /// Construct a TCP socket writer that writes to the given host and port.
        /// </summary>
        /// <param name="host">IPAddress of the host to open a TCP socket to.</param>
        /// <param name="port">TCP port to use on the target host.</param>
        /// <param name="policy">A TcpConnectionPolicy object defining reconnect behavior.</param>
        /// <param name="maxQueueSize">The maximum number of log entries to queue before starting to drop entries.</param>
        /// <param name="progress">An IProgress object that reports when the queue of entries to be written reaches empty or there is
        /// a reconnection failure. This is used for testing purposes only.</param>
        public TcpSocketWriter(IPAddress host, int port, ITcpReconnectionPolicy policy,
                               int maxQueueSize, Func <IPAddress, int, Socket> connect = null)
        {
            this.host            = host;
            this.port            = port;
            this.reconnectPolicy = policy;
            this.eventQueue      = new FixedSizeQueue <string>(maxQueueSize);
            this.tokenSource     = new CancellationTokenSource();

            if (connect == null)
            {
                this.tryOpenSocket = (h, p) =>
                {
                    try
                    {
                        var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
                        socket.Connect(host, port);
                        return(socket);
                    }
                    catch (SocketException e)
                    {
                        LoggingFailureHandler(e);
                        throw;
                    }
                };
            }
            else
            {
                this.tryOpenSocket = (h, p) =>
                {
                    try
                    {
                        return(connect(h, p));
                    }
                    catch (SocketException e)
                    {
                        LoggingFailureHandler(e);
                        throw;
                    }
                };
            }

            var threadReady = new TaskCompletionSource <bool>();

            queueListener = new Thread(() =>
            {
                try
                {
                    this.socket = this.reconnectPolicy.Connect(tryOpenSocket, host, port, tokenSource.Token);
                    threadReady.SetResult(true); // Signal the calling thread that we are ready.

                    string entry = null;
                    while (this.socket != null) // null indicates that the thread has been cancelled and cleaned up.
                    {
                        if (tokenSource.Token.IsCancellationRequested)
                        {
                            eventQueue.CompleteAdding();
                            // Post-condition: no further items will be added to the queue, so there will be a finite number of items to handle.
                            while (eventQueue.Count > 0)
                            {
                                entry = eventQueue.Dequeue();
                                try
                                {
                                    this.socket.Send(Encoding.UTF8.GetBytes(entry));
                                }
                                catch (SocketException ex)
                                {
                                    LoggingFailureHandler(ex);
                                }
                            }
                            break;
                        }
                        else if (entry == null)
                        {
                            entry = eventQueue.Dequeue(tokenSource.Token);
                        }
                        else if (entry != null)
                        {
                            try
                            {
                                if (this.socket.Send(Encoding.UTF8.GetBytes(entry)) != -1)
                                {
                                    entry = null;
                                }
                            }
                            catch (SocketException ex)
                            {
                                LoggingFailureHandler(ex);
                                this.socket = this.reconnectPolicy.Connect(tryOpenSocket, host, port, tokenSource.Token);
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    LoggingFailureHandler(e);
                }
                finally
                {
                    if (socket != null)
                    {
                        socket.Dispose();
                    }

                    disposed.SetResult(true);
                }
            });
            queueListener.IsBackground = true; // Prevent the thread from blocking the process from exiting.
            queueListener.Start();
            threadReady.Task.Wait();
        }
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="host">IP address to log to.</param>
 /// <param name="port">Port on remote host.</param>
 /// <param name="policy">An object embodying a reconnection policy for if the 
 /// TCP session drops (defaults to ExponentialBackoffTcpConnectionPolicy).</param>
 /// <param name="maxQueueSize">The maximum number of events to queue if the 
 /// TCP session goes down. If more events are queued, old ones will be dropped
 /// (defaults to 10,000).</param>
 /// <param name="progress">An IProgress instance that will be triggered when
 /// an event is pulled from the queue and written to the TCP port (defaults to a new
 /// Progress object accessible via the Progress property).</param>
 public TcpTraceListener(IPAddress host, int port, ITcpReconnectionPolicy policy, 
                         int maxQueueSize = 10000)
     : base()
 {
     this.writer = new TcpSocketWriter(host, port, policy, maxQueueSize);
 }
Ejemplo n.º 4
0
 /// <summary>
 /// Set up a sink.
 /// </summary>
 /// <param name="host">Hostname of the host to write to.</param>
 /// <param name="port">TCP port to write to.</param>
 /// <param name="formatter">An object to specify the format events should be
 /// written in (default to <code>{timestamp} EventId={...} EventName={...} Level={...} "FormattedMessage={...}"</code>).</param>
 /// <param name="policy">An object defining the reconnect policy in the event
 /// of TCP errors (default: an ExponentialBackoffTcpConnectionPolicy object).</param>
 /// <param name="maxQueueSize">The maximum number of events to queue in the event of
 /// the TCP session dropping before events start to be dropped (defaults to 10,000).</param>
 /// <param name="progress">A progress reporter that triggers when events are written from
 /// the queue to the TCP port (defaults to a new Progress object). It is reachable
 /// via the Progress property.</param>
 public TcpEventSink(string host, int port, ITcpReconnectionPolicy policy,
                     IEventTextFormatter formatter = null, int maxQueueSize = 10000) :
     this(host.HostnameToIPAddress(), port, policy, formatter, maxQueueSize)
 {
 }
Ejemplo n.º 5
0
 /// <summary>
 /// Set up a sink.
 /// </summary>
 /// <param name="host">IP address of the host to write to.</param>
 /// <param name="port">TCP port to write to.</param>
 /// <param name="formatter">An object to specify the format events should be
 /// written in (defaults to <code>{timestamp} EventId={...} EventName={...} Level={...} "FormattedMessage={...}"</code>).</param>
 /// <param name="policy">An object defining the reconnect policy in the event
 /// of TCP errors (default: an ExponentialBackoffTcpConnectionPolicy object).</param>
 /// <param name="maxQueueSize">The maximum number of events to queue in the event of
 /// the TCP session dropping before events start to be dropped (defaults to 10,000).</param>
 /// <param name="progress">A progress reporter that triggers when events are written from
 /// the queue to the TCP port (defaults to a new Progress object). It is reachable
 /// via the Progress property.</param>
 public TcpEventSink(IPAddress host, int port, ITcpReconnectionPolicy policy,
                     IEventTextFormatter formatter = null, int maxQueueSize = 10000)
 {
     this.writer    = new TcpSocketWriter(host, port, policy, maxQueueSize);
     this.formatter = formatter;
 }
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="host">Hostname to log to.</param>
 /// <param name="port">Port on remote host.</param>
 /// <param name="policy">An object embodying a reconnection policy for if the
 /// TCP session drops (defaults to ExponentialBackoffTcpConnectionPolicy).</param>
 /// <param name="maxQueueSize">The maximum number of events to queue if the
 /// TCP session goes down. If more events are queued, old ones will be dropped
 /// (defaults to 10,000).</param>
 /// <param name="progress">An IProgress instance that will be triggered when
 /// an event is pulled from the queue and written to the TCP port (defaults to a new
 /// Progress object accessible via the Progress property).</param>
 public TcpTraceListener(string host, int port, ITcpReconnectionPolicy policy,
                         int maxQueueSize = 10000) :
     this(host.HostnameToIPAddress(), port, policy, maxQueueSize)
 {
 }
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="host">IP address to log to.</param>
 /// <param name="port">Port on remote host.</param>
 /// <param name="policy">An object embodying a reconnection policy for if the
 /// TCP session drops (defaults to ExponentialBackoffTcpConnectionPolicy).</param>
 /// <param name="maxQueueSize">The maximum number of events to queue if the
 /// TCP session goes down. If more events are queued, old ones will be dropped
 /// (defaults to 10,000).</param>
 /// <param name="progress">An IProgress instance that will be triggered when
 /// an event is pulled from the queue and written to the TCP port (defaults to a new
 /// Progress object accessible via the Progress property).</param>
 public TcpTraceListener(IPAddress host, int port, ITcpReconnectionPolicy policy,
                         int maxQueueSize = 10000) : base()
 {
     this.writer = new TcpSocketWriter(host, port, policy, maxQueueSize);
 }