/// <summary>
        /// Initializes a new instance of the <see cref="HttpEventCollectorSender"/> class.
        /// </summary>
        /// <param name="uri">Splunk server uri, for example https://localhost:8088.</param>
        /// <param name="token">HTTP event collector authorization token.</param>
        /// <param name="channel">HTTP event collector data channel.</param>
        /// <param name="metadata">Logger metadata.</param>
        /// <param name="sendMode">Send mode of the events.</param>
        /// <param name="batchInterval">Batch interval in milliseconds.</param>
        /// <param name="batchSizeBytes">Batch max size.</param>
        /// <param name="batchSizeCount">Max number of individual events in batch.</param>
        /// <param name="ignoreSslErrors">Server validation callback should always return true</param>
        /// <param name="useProxy">Default web proxy is used if set to true; otherwise, no proxy is used</param>
        /// <param name="middleware">HTTP client middleware. This allows to plug an HttpClient handler that
        /// intercepts logging HTTP traffic.</param>
        /// <param name="formatter">The formatter.</param>
        /// <remarks>
        /// Zero values for the batching params mean that batching is off.
        /// </remarks>
        public HttpEventCollectorSender(
            Uri uri,
            string token,
            string channel,
            HttpEventCollectorEventInfo.Metadata metadata,
            SendMode sendMode,
            int batchInterval,
            int batchSizeBytes,
            int batchSizeCount,
            bool ignoreSslErrors,
            ProxyConfiguration proxy,
            int maxConnectionsPerServer,
            HttpEventCollectorMiddleware middleware,
            HttpEventCollectorFormatter formatter = null,
            bool httpVersion10Hack = false)
        {
            NLog.Common.InternalLogger.Debug("Initializing Splunk HttpEventCollectorSender");

            this.httpEventCollectorEndpointUri = new Uri(uri, HttpEventCollectorPath);
            this.jsonSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            this.jsonSerializerSettings.Formatting            = Formatting.None;
            this.jsonSerializerSettings.Converters            = new[] { new Newtonsoft.Json.Converters.StringEnumConverter() };
            this.jsonSerializer         = JsonSerializer.CreateDefault(this.jsonSerializerSettings);
            this.sendMode               = sendMode;
            this.batchInterval          = batchInterval;
            this.batchSizeBytes         = batchSizeBytes;
            this.batchSizeCount         = batchSizeCount;
            this.metadata               = metadata;
            this.token                  = token;
            this.channel                = channel;
            this.middleware             = middleware;
            this.formatter              = formatter;
            this.applyHttpVersion10Hack = httpVersion10Hack;

            // special case - if batch interval is specified without size and count
            // they are set to "infinity", i.e., batch may have any size
            if (this.batchInterval > 0 && this.batchSizeBytes == 0 && this.batchSizeCount == 0)
            {
                this.batchSizeBytes = this.batchSizeCount = int.MaxValue;
            }

            // when size configuration setting is missing it's treated as "infinity",
            // i.e., any value is accepted.
            if (this.batchSizeCount == 0 && this.batchSizeBytes > 0)
            {
                this.batchSizeCount = int.MaxValue;
            }
            else if (this.batchSizeBytes == 0 && this.batchSizeCount > 0)
            {
                this.batchSizeBytes = int.MaxValue;
            }

            // setup the timer
            if (batchInterval != 0) // 0 means - no timer
            {
                timer = new Timer(OnTimer, null, batchInterval, batchInterval);
            }

            // setup HTTP client
            try
            {
                var httpMessageHandler = BuildHttpMessageHandler(ignoreSslErrors, proxy, maxConnectionsPerServer);
                httpClient = new HttpClient(httpMessageHandler);
            }
            catch
            {
                // Fallback on PlatformNotSupported and other funny exceptions
                httpClient = new HttpClient();
            }

            // setup splunk header token
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(AuthorizationHeaderScheme, token);

            if (this.applyHttpVersion10Hack)
            {
                httpClient.BaseAddress = uri;
                httpClient.DefaultRequestHeaders.ConnectionClose = false;
                httpClient.DefaultRequestHeaders.Add("Connection", "keep-alive");
            }

            // setup splunk channel request header
            if (!string.IsNullOrWhiteSpace(channel))
            {
                httpClient.DefaultRequestHeaders.Add(ChannelRequestHeaderName, channel);
            }
        }
        /// <summary>
        /// Builds the HTTP message handler.
        /// </summary>
        /// <param name="ignoreSslErrors">if set to <c>true</c> [ignore SSL errors].</param>
        /// <param name="maxConnectionsPerServer"></param>
        /// <param name="proxyConfig"></param>
        /// <returns></returns>
        private HttpMessageHandler BuildHttpMessageHandler(bool ignoreSslErrors, int maxConnectionsPerServer, ProxyConfiguration proxyConfig)
        {
#if NET45 || NET462
            // Uses the WebRequestHandler for .NET 4.5 - 4.7.0
            var httpMessageHandler = new WebRequestHandler();
            if (ignoreSslErrors)
            {
                httpMessageHandler.ServerCertificateValidationCallback = IgnoreServerCertificateCallback;
            }
#else
            // Uses the new and improved HttpClientHandler() for .NET 4.7.1+ and .NET Standard 2.0+
            var httpMessageHandler = new HttpClientHandler();
            if (ignoreSslErrors)
            {
                httpMessageHandler.ServerCertificateCustomValidationCallback = (msg, cert, chain, errors) => IgnoreServerCertificateCallback(msg, cert, chain, errors);
            }

            if (maxConnectionsPerServer > 0)
            {
                httpMessageHandler.MaxConnectionsPerServer = maxConnectionsPerServer;
            }
#endif
            // Setup proxy
            httpMessageHandler.UseProxy = proxyConfig.UseProxy;
            if (proxyConfig.UseProxy && !string.IsNullOrWhiteSpace(proxyConfig.ProxyUrl))
            {
                httpMessageHandler.Proxy = new WebProxy(new Uri(proxyConfig.ProxyUrl));
                if (!String.IsNullOrWhiteSpace(proxyConfig.ProxyUser) && !String.IsNullOrWhiteSpace(proxyConfig.ProxyPassword))
                {
                    httpMessageHandler.Proxy.Credentials = new NetworkCredential(proxyConfig.ProxyUser, proxyConfig.ProxyPassword);
                }
            }

            return(httpMessageHandler);
        }