Customize TCP session handling

By default, the TCP listeners handle dropped TCP sessions by trying to reconnect after increasingly long intervals. You can specify a custom reconnection policy by defining an instance of Splunk.Logging.TcpConnectionPolicy, and passing it to the constructors of the TcpTraceListener or TcpEventSink classes.

TcpConnectionPolicy has a single method, Reconnect, which tries to establish a connection or throws a TcpReconnectFailure if the policy dictates that it will no longer try to reconnect. Here is annotated source code of the default, exponential backoff policy:

public class ExponentialBackoffTcpReconnectionPolicy : TcpReconnectionPolicy
{
    private int ceiling = 10 * 60; // 10 minutes in seconds

    // the arguments are:
    //
    //     connect - a function that attempts a TCP connection given a host, port number
    //     host - the host to connect to
    //     port - the port to connect on
    //     cancellationToken - used by TcpTraceListener and TcpEventSink to cancel this method
    //         when they are disposed
    public Socket Connect(Func<IPAddress, int, Socket> connect, IPAddress host, int port, CancellationToken cancellationToken)
    {
        int delay = 1; // in seconds
        while (!cancellationToken.IsCancellationRequested)
        {
            try
            {
                return connect(host, port);
            }
            catch (SocketException) { }

            // if this is cancelled via the cancellationToken instead of
            // completing its delay, the next while-loop test will fail,
            // the loop will terminate, and the method will return null
            // with no additional connection attempts
            Task.Delay(delay * 1000, cancellationToken).Wait();
            // the nth delay is min(10 minutes, 2^n - 1 seconds)
            delay = Math.Min((delay + 1) * 2 - 1, ceiling);
        }

        // cancellationToken has been cancelled
        return null;
    }
}

Another, simpler, policy would be trying to reconnect once, and then failing:

class TryOnceTcpConnectionPolicy : TcpReconnectionPolicy
{
    public Socket Connect(Func<System.Net.IPAddress, int, Socket> connect, 
            System.Net.IPAddress host, int port, 
            System.Threading.CancellationToken cancellationToken)
    {
        try
        {
            if (cancellationToken.IsCancellationRequested)
                return null;
            return connect(host, port);
        }
        catch (SocketException e)
        {
            throw new TcpReconnectFailureException("Reconnect failed: " + e.Message);
        }
    }
}